Compare commits
	
		
			7 Commits
		
	
	
		
			09d3754f92
			...
			0b27c8f80b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 0b27c8f80b | |||
| 0ad1ee47de | |||
| 8ea2b06487 | |||
| 1e4accec9d | |||
| 076d5eea18 | |||
| 5b6bd00047 | |||
| 8dd471afa8 | 
@@ -2,6 +2,7 @@
 | 
				
			|||||||
- Update dependencies
 | 
					- Update dependencies
 | 
				
			||||||
- Show topbar on form submit/page refresh
 | 
					- Show topbar on form submit/page refresh
 | 
				
			||||||
- Make loading/reconnection less intrusive
 | 
					- Make loading/reconnection less intrusive
 | 
				
			||||||
 | 
					- Add QR code for invite link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# v0.8.0
 | 
					# v0.8.0
 | 
				
			||||||
- Add search to catalog, ammo, container, tag and range index pages
 | 
					- Add search to catalog, ammo, container, tag and range index pages
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ import 'phoenix_html'
 | 
				
			|||||||
// Establish Phoenix Socket and LiveView configuration.
 | 
					// Establish Phoenix Socket and LiveView configuration.
 | 
				
			||||||
import { Socket } from 'phoenix'
 | 
					import { Socket } from 'phoenix'
 | 
				
			||||||
import { LiveSocket } from 'phoenix_live_view'
 | 
					import { LiveSocket } from 'phoenix_live_view'
 | 
				
			||||||
import topbar from '../vendor/topbar'
 | 
					import topbar from 'topbar'
 | 
				
			||||||
import MaintainAttrs from './maintain_attrs'
 | 
					import MaintainAttrs from './maintain_attrs'
 | 
				
			||||||
import ShotLogChart from './shot_log_chart'
 | 
					import ShotLogChart from './shot_log_chart'
 | 
				
			||||||
import Alpine from 'alpinejs'
 | 
					import Alpine from 'alpinejs'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										157
									
								
								assets/vendor/topbar.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										157
									
								
								assets/vendor/topbar.js
									
									
									
									
										vendored
									
									
								
							@@ -1,157 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * @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,17 +15,18 @@ end
 | 
				
			|||||||
config :cannery, CanneryWeb.ViewHelpers, shibao_mode: System.get_env("SHIBAO_MODE") == "true"
 | 
					config :cannery, CanneryWeb.ViewHelpers, shibao_mode: System.get_env("SHIBAO_MODE") == "true"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set default locale
 | 
					# 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: []
 | 
					maybe_ipv6 = if System.get_env("ECTO_IPV6") == "true", do: [:inet6], else: []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
database_url =
 | 
					database_url =
 | 
				
			||||||
  if config_env() == :test do
 | 
					  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")}"
 | 
					      "ecto://postgres:postgres@localhost/cannery_test#{System.get_env("MIX_TEST_PARTITION")}"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    System.get_env("DATABASE_URL") ||
 | 
					    System.get_env("DATABASE_URL", "ecto://postgres:postgres@cannery-db/cannery")
 | 
				
			||||||
      "ecto://postgres:postgres@cannery-db/cannery"
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
host =
 | 
					host =
 | 
				
			||||||
@@ -40,7 +41,7 @@ interface =
 | 
				
			|||||||
config :cannery, Cannery.Repo,
 | 
					config :cannery, Cannery.Repo,
 | 
				
			||||||
  # ssl: true,
 | 
					  # ssl: true,
 | 
				
			||||||
  url: database_url,
 | 
					  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
 | 
					  socket_options: maybe_ipv6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config :cannery, CanneryWeb.Endpoint,
 | 
					config :cannery, CanneryWeb.Endpoint,
 | 
				
			||||||
@@ -49,10 +50,10 @@ config :cannery, CanneryWeb.Endpoint,
 | 
				
			|||||||
    # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
 | 
					    # See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
 | 
				
			||||||
    # for details about using IPv6 vs IPv4 and loopback vs public addresses.
 | 
					    # for details about using IPv6 vs IPv4 and loopback vs public addresses.
 | 
				
			||||||
    ip: interface,
 | 
					    ip: interface,
 | 
				
			||||||
    port: String.to_integer(System.get_env("PORT") || "4000")
 | 
					    port: String.to_integer(System.get_env("PORT", "4000"))
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  server: true,
 | 
					  server: true,
 | 
				
			||||||
  registration: System.get_env("REGISTRATION") || "invite"
 | 
					  registration: System.get_env("REGISTRATION", "invite")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if config_env() == :prod do
 | 
					if config_env() == :prod do
 | 
				
			||||||
  # The secret key base is used to sign/encrypt cookies and other secrets.
 | 
					  # The secret key base is used to sign/encrypt cookies and other secrets.
 | 
				
			||||||
@@ -76,12 +77,12 @@ if config_env() == :prod do
 | 
				
			|||||||
  config :cannery, Cannery.Mailer,
 | 
					  config :cannery, Cannery.Mailer,
 | 
				
			||||||
    adapter: Swoosh.Adapters.SMTP,
 | 
					    adapter: Swoosh.Adapters.SMTP,
 | 
				
			||||||
    relay: System.get_env("SMTP_HOST") || raise("No SMTP_HOST set!"),
 | 
					    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!"),
 | 
					    username: System.get_env("SMTP_USERNAME") || raise("No SMTP_USERNAME set!"),
 | 
				
			||||||
    password: System.get_env("SMTP_PASSWORD") || raise("No SMTP_PASSWORD set!"),
 | 
					    password: System.get_env("SMTP_PASSWORD") || raise("No SMTP_PASSWORD set!"),
 | 
				
			||||||
    ssl: System.get_env("SMTP_SSL") == "true",
 | 
					    ssl: System.get_env("SMTP_SSL") == "true",
 | 
				
			||||||
    email_from: System.get_env("EMAIL_FROM") || "no-reply@#{System.get_env("HOST")}",
 | 
					    email_from: System.get_env("EMAIL_FROM", "no-reply@#{System.get_env("HOST")}"),
 | 
				
			||||||
    email_name: System.get_env("EMAIL_NAME") || "Cannery"
 | 
					    email_name: System.get_env("EMAIL_NAME", "Cannery")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # ## Using releases
 | 
					  # ## Using releases
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,13 +55,13 @@ defmodule CanneryWeb.Components.AmmoGroupCard do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <span class="rounded-lg title text-lg">
 | 
					        <span class="rounded-lg title text-lg">
 | 
				
			||||||
          <%= gettext("Purchased on:") %>
 | 
					          <%= gettext("Purchased on:") %>
 | 
				
			||||||
          <%= @ammo_group.purchased_on |> display_date() %>
 | 
					          <.date date={@ammo_group.purchased_on} />
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <%= if @ammo_group |> Ammo.get_last_used_shot_group() do %>
 | 
					        <%= if @ammo_group |> Ammo.get_last_used_shot_group() do %>
 | 
				
			||||||
          <span class="rounded-lg title text-lg">
 | 
					          <span class="rounded-lg title text-lg">
 | 
				
			||||||
            <%= gettext("Last used on:") %>
 | 
					            <%= gettext("Last used on:") %>
 | 
				
			||||||
            <%= @ammo_group |> Ammo.get_last_used_shot_group() |> Map.get(:date) |> display_date() %>
 | 
					            <.date date={@ammo_group |> Ammo.get_last_used_shot_group() |> Map.get(:date)} />
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
        <% end %>
 | 
					        <% end %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,7 +157,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {purchased_on,
 | 
					    {purchased_on,
 | 
				
			||||||
     ~H"""
 | 
					     ~H"""
 | 
				
			||||||
     <%= @purchased_on |> display_date() %>
 | 
					     <.date date={@purchased_on} />
 | 
				
			||||||
     """}
 | 
					     """}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -173,7 +173,7 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
 | 
				
			|||||||
    {last_shot_group_date,
 | 
					    {last_shot_group_date,
 | 
				
			||||||
     ~H"""
 | 
					     ~H"""
 | 
				
			||||||
     <%= if @last_shot_group_date do %>
 | 
					     <%= if @last_shot_group_date do %>
 | 
				
			||||||
       <%= @last_shot_group_date |> display_date() %>
 | 
					       <.date date={@last_shot_group_date} />
 | 
				
			||||||
     <% else %>
 | 
					     <% else %>
 | 
				
			||||||
       <%= gettext("Never used") %>
 | 
					       <%= gettext("Never used") %>
 | 
				
			||||||
     <% end %>
 | 
					     <% end %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,8 +27,14 @@ defmodule CanneryWeb.Components.InviteCard do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      <%= if @invite.disabled_at |> is_nil() do %>
 | 
					      <%= if @invite.disabled_at |> is_nil() do %>
 | 
				
			||||||
        <h2 class="title text-md">
 | 
					        <h2 class="title text-md">
 | 
				
			||||||
          <%= gettext("Uses Left:") %>
 | 
					          <%= if @invite.uses_left do %>
 | 
				
			||||||
          <%= @invite.uses_left || "Unlimited" %>
 | 
					            <%= gettext(
 | 
				
			||||||
 | 
					              "Uses Left: %{uses_left}",
 | 
				
			||||||
 | 
					              uses_left: @invite.uses_left
 | 
				
			||||||
 | 
					            ) %>
 | 
				
			||||||
 | 
					          <% else %>
 | 
				
			||||||
 | 
					            <%= gettext("Uses Left: Unlimited") %>
 | 
				
			||||||
 | 
					          <% end %>
 | 
				
			||||||
        </h2>
 | 
					        </h2>
 | 
				
			||||||
      <% else %>
 | 
					      <% else %>
 | 
				
			||||||
        <h2 class="title text-md">
 | 
					        <h2 class="title text-md">
 | 
				
			||||||
@@ -36,6 +42,11 @@ defmodule CanneryWeb.Components.InviteCard do
 | 
				
			|||||||
        </h2>
 | 
					        </h2>
 | 
				
			||||||
      <% end %>
 | 
					      <% 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">
 | 
					      <div class="flex flex-row flex-wrap justify-center items-center">
 | 
				
			||||||
        <code
 | 
					        <code
 | 
				
			||||||
          id={"code-#{@invite.id}"}
 | 
					          id={"code-#{@invite.id}"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,11 @@ defmodule CanneryWeb.Components.ShotGroupTableComponent do
 | 
				
			|||||||
    {ammo_type_name, name_block}
 | 
					    {ammo_type_name, name_block}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp get_row_value(:date, %{date: date}, _extra_data), do: date |> display_date()
 | 
					  defp get_row_value(:date, assigns = %{date: _date}, _extra_data) do
 | 
				
			||||||
 | 
					    ~H"""
 | 
				
			||||||
 | 
					    <.date date={@date} />
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp get_row_value(:actions, shot_group, %{actions: actions}) do
 | 
					  defp get_row_value(:actions, shot_group, %{actions: actions}) do
 | 
				
			||||||
    assigns = %{actions: actions, shot_group: shot_group}
 | 
					    assigns = %{actions: actions, shot_group: shot_group}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
      <tr>
 | 
					      <tr>
 | 
				
			||||||
        <%= for %{key: key, label: label} = column <- @columns do %>
 | 
					        <%= for %{key: key, label: label} = column <- @columns do %>
 | 
				
			||||||
          <%= if column |> Map.get(:sortable, true) do %>
 | 
					          <%= if column |> Map.get(:sortable, true) do %>
 | 
				
			||||||
            <th class={"p-2 #{column[:class]}"}>
 | 
					            <th class={["p-2", column[:class]]}>
 | 
				
			||||||
              <span
 | 
					              <span
 | 
				
			||||||
                class="cursor-pointer flex justify-center items-center space-x-2"
 | 
					                class="cursor-pointer flex justify-center items-center space-x-2"
 | 
				
			||||||
                phx-click="sort_by"
 | 
					                phx-click="sort_by"
 | 
				
			||||||
@@ -26,7 +26,7 @@
 | 
				
			|||||||
              </span>
 | 
					              </span>
 | 
				
			||||||
            </th>
 | 
					            </th>
 | 
				
			||||||
          <% else %>
 | 
					          <% else %>
 | 
				
			||||||
            <th class={"p-2 cursor-not-allowed #{column[:class]}"}>
 | 
					            <th class={["p-2 cursor-not-allowed", column[:class]]}>
 | 
				
			||||||
              <%= label %>
 | 
					              <%= label %>
 | 
				
			||||||
            </th>
 | 
					            </th>
 | 
				
			||||||
          <% end %>
 | 
					          <% end %>
 | 
				
			||||||
@@ -37,7 +37,7 @@
 | 
				
			|||||||
      <%= for {values, i} <- @rows |> Enum.with_index() do %>
 | 
					      <%= for {values, i} <- @rows |> Enum.with_index() do %>
 | 
				
			||||||
        <tr class={if i |> Integer.is_even(), do: @row_class, else: @alternate_row_class}>
 | 
					        <tr class={if i |> Integer.is_even(), do: @row_class, else: @alternate_row_class}>
 | 
				
			||||||
          <%= for %{key: key} = value <- @columns do %>
 | 
					          <%= for %{key: key} = value <- @columns do %>
 | 
				
			||||||
            <td class={"p-2 #{value[:class]}"}>
 | 
					            <td class={["p-2", value[:class]]}>
 | 
				
			||||||
              <%= case values |> Map.get(key) do %>
 | 
					              <%= case values |> Map.get(key) do %>
 | 
				
			||||||
                <% {_custom_sort_value, value} -> %>
 | 
					                <% {_custom_sort_value, value} -> %>
 | 
				
			||||||
                  <%= value %>
 | 
					                  <%= value %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,16 +23,23 @@ defmodule CanneryWeb.Components.UserCard do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      <h3 class="px-4 py-2 rounded-lg title text-lg">
 | 
					      <h3 class="px-4 py-2 rounded-lg title text-lg">
 | 
				
			||||||
        <p>
 | 
					        <p>
 | 
				
			||||||
          <%= if @user.confirmed_at |> is_nil() do %>
 | 
					          <%= if @user.confirmed_at do %>
 | 
				
			||||||
            Email unconfirmed
 | 
					            <%= gettext(
 | 
				
			||||||
 | 
					              "User was confirmed at%{confirmed_datetime}",
 | 
				
			||||||
 | 
					              confirmed_datetime: ""
 | 
				
			||||||
 | 
					            ) %>
 | 
				
			||||||
 | 
					            <.datetime datetime={@user.confirmed_at} />
 | 
				
			||||||
          <% else %>
 | 
					          <% else %>
 | 
				
			||||||
            User was confirmed at <%= @user.confirmed_at |> display_datetime() %>
 | 
					            <%= gettext("Email unconfirmed") %>
 | 
				
			||||||
          <% end %>
 | 
					          <% end %>
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <p>
 | 
					        <p>
 | 
				
			||||||
          <%= gettext("User registered on") %>
 | 
					          <%= gettext(
 | 
				
			||||||
          <%= @user.inserted_at |> display_datetime() %>
 | 
					            "User registered on%{registered_datetime}",
 | 
				
			||||||
 | 
					            registered_datetime: ""
 | 
				
			||||||
 | 
					          ) %>
 | 
				
			||||||
 | 
					          <.datetime datetime={@user.inserted_at} />
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
      </h3>
 | 
					      </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,12 @@ defmodule CanneryWeb.AmmoGroupLive.Show do
 | 
				
			|||||||
      value =
 | 
					      value =
 | 
				
			||||||
        case key do
 | 
					        case key do
 | 
				
			||||||
          :date ->
 | 
					          :date ->
 | 
				
			||||||
            {date, date |> display_date()}
 | 
					            assigns = %{date: date}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {date,
 | 
				
			||||||
 | 
					             ~H"""
 | 
				
			||||||
 | 
					             <.date date={@date} />
 | 
				
			||||||
 | 
					             """}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          :actions ->
 | 
					          :actions ->
 | 
				
			||||||
            ~H"""
 | 
					            ~H"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <span class="rounded-lg title text-lg">
 | 
					    <span class="rounded-lg title text-lg">
 | 
				
			||||||
      <%= gettext("Purchased on:") %>
 | 
					      <%= gettext("Purchased on:") %>
 | 
				
			||||||
      <%= @ammo_group.purchased_on |> display_date() %>
 | 
					      <.date date={@ammo_group.purchased_on} />
 | 
				
			||||||
    </span>
 | 
					    </span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <%= if @ammo_group.price_paid do %>
 | 
					    <%= if @ammo_group.price_paid do %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -124,7 +124,7 @@
 | 
				
			|||||||
    </h3>
 | 
					    </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <span class="text-primary-600">
 | 
					    <span class="text-primary-600">
 | 
				
			||||||
      <%= @ammo_type.inserted_at |> display_datetime() %>
 | 
					      <.datetime datetime={@ammo_type.inserted_at} />
 | 
				
			||||||
    </span>
 | 
					    </span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <%= if @avg_cost_per_round do %>
 | 
					    <%= if @avg_cost_per_round do %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,15 +11,17 @@ defmodule CanneryWeb.Router do
 | 
				
			|||||||
    plug :protect_from_forgery
 | 
					    plug :protect_from_forgery
 | 
				
			||||||
    plug :put_secure_browser_headers
 | 
					    plug :put_secure_browser_headers
 | 
				
			||||||
    plug :fetch_current_user
 | 
					    plug :fetch_current_user
 | 
				
			||||||
    plug :put_user_locale, default: Application.compile_env(:gettext, :default_locale, "en_US")
 | 
					    plug :put_user_locale
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp put_user_locale(%{assigns: %{current_user: %{locale: locale}}} = conn, default: default) do
 | 
					  defp put_user_locale(%{assigns: %{current_user: %{locale: locale}}} = conn, _opts) do
 | 
				
			||||||
 | 
					    default = Application.fetch_env!(:gettext, :default_locale)
 | 
				
			||||||
    Gettext.put_locale(locale || default)
 | 
					    Gettext.put_locale(locale || default)
 | 
				
			||||||
    conn |> put_session(:locale, locale || default)
 | 
					    conn |> put_session(:locale, locale || default)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp put_user_locale(conn, default: default) do
 | 
					  defp put_user_locale(conn, _opts) do
 | 
				
			||||||
 | 
					    default = Application.fetch_env!(:gettext, :default_locale)
 | 
				
			||||||
    Gettext.put_locale(default)
 | 
					    Gettext.put_locale(default)
 | 
				
			||||||
    conn |> put_session(:locale, default)
 | 
					    conn |> put_session(:locale, default)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
<main class="mb-8 min-w-full">
 | 
					<main class="pb-8 min-w-full">
 | 
				
			||||||
  <header>
 | 
					  <header>
 | 
				
			||||||
    <.topbar current_user={assigns[:current_user]}></.topbar>
 | 
					    <.topbar current_user={assigns[:current_user]}></.topbar>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,8 +10,8 @@
 | 
				
			|||||||
      type="image/jpg"
 | 
					      type="image/jpg"
 | 
				
			||||||
      href={Routes.static_path(@conn, "/images/cannery.svg")}
 | 
					      href={Routes.static_path(@conn, "/images/cannery.svg")}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
    <.live_title suffix=" | Cannery">
 | 
					    <.live_title suffix={" | #{gettext("Cannery")}"}>
 | 
				
			||||||
      <%= assigns[:page_title] || "Cannery" %>
 | 
					      <%= assigns[:page_title] || gettext("Cannery") %>
 | 
				
			||||||
    </.live_title>
 | 
					    </.live_title>
 | 
				
			||||||
    <link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")} />
 | 
					    <link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/css/app.css")} />
 | 
				
			||||||
    <script
 | 
					    <script
 | 
				
			||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <body class="m-0 p-0 w-full h-full bg-white">
 | 
					  <body class="m-0 p-0 w-full h-full subpixel-antialiased">
 | 
				
			||||||
    <%= @inner_content %>
 | 
					    <%= @inner_content %>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ defmodule CanneryWeb.ErrorHelpers do
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ~H"""
 | 
					    ~H"""
 | 
				
			||||||
    <%= for error <- Keyword.get_values(@form.errors, @field) do %>
 | 
					    <%= 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) %>
 | 
					        <%= translate_error(error) %>
 | 
				
			||||||
      </span>
 | 
					      </span>
 | 
				
			||||||
    <% end %>
 | 
					    <% end %>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,64 +5,62 @@ defmodule CanneryWeb.ViewHelpers do
 | 
				
			|||||||
  :view`
 | 
					  :view`
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  import Phoenix.Component
 | 
					  use Phoenix.Component
 | 
				
			||||||
 | 
					 | 
				
			||||||
  @id_length 16
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Returns a <time> element that renders the naivedatetime in the user's local
 | 
					  Phoenix.Component for a <time> element that renders the naivedatetime in the
 | 
				
			||||||
  timezone with Alpine.js
 | 
					  user's local timezone with Alpine.js
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec display_datetime(NaiveDateTime.t() | nil) :: Phoenix.LiveView.Rendered.t()
 | 
					 | 
				
			||||||
  def display_datetime(nil), do: ""
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def display_datetime(datetime) do
 | 
					  attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil"
 | 
				
			||||||
    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"""
 | 
					    ~H"""
 | 
				
			||||||
    <time
 | 
					    <%= if @datetime do %>
 | 
				
			||||||
      id={@id}
 | 
					      <time
 | 
				
			||||||
      datetime={@datetime}
 | 
					        datetime={cast_datetime(@datetime)}
 | 
				
			||||||
      x-data={"{
 | 
					        x-data={"{
 | 
				
			||||||
        date:
 | 
					          datetime:
 | 
				
			||||||
          Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'})
 | 
					            Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'})
 | 
				
			||||||
            .format(new Date(\"#{@datetime}\"))
 | 
					              .format(new Date(\"#{cast_datetime(@datetime)}\"))
 | 
				
			||||||
      }"}
 | 
					        }"}
 | 
				
			||||||
      x-text="date"
 | 
					        x-text="datetime"
 | 
				
			||||||
    >
 | 
					      >
 | 
				
			||||||
      <%= @datetime %>
 | 
					        <%= cast_datetime(@datetime) %>
 | 
				
			||||||
    </time>
 | 
					      </time>
 | 
				
			||||||
 | 
					    <% end %>
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
  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 """
 | 
					  @doc """
 | 
				
			||||||
  Returns a <date> element that renders the Date in the user's local
 | 
					  Phoenix.Component for a <date> element that renders the Date in the user's
 | 
				
			||||||
  timezone with Alpine.js
 | 
					  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
 | 
					  attr :date, :any, required: true, doc: "A `Date` struct or nil"
 | 
				
			||||||
    assigns = %{
 | 
					 | 
				
			||||||
      id: :crypto.strong_rand_bytes(@id_length) |> Base.url_encode64(),
 | 
					 | 
				
			||||||
      date: date |> Date.to_iso8601(:extended)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def date(assigns) do
 | 
				
			||||||
    ~H"""
 | 
					    ~H"""
 | 
				
			||||||
    <time
 | 
					    <%= if @date do %>
 | 
				
			||||||
      id={@id}
 | 
					      <time
 | 
				
			||||||
      datetime={@date}
 | 
					        datetime={@date |> Date.to_iso8601(:extended)}
 | 
				
			||||||
      x-data={"{
 | 
					        x-data={"{
 | 
				
			||||||
        date:
 | 
					          date:
 | 
				
			||||||
          Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'}).format(new Date(\"#{@date}\"))
 | 
					            Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'})
 | 
				
			||||||
      }"}
 | 
					              .format(new Date(\"#{@date |> Date.to_iso8601(:extended)}\"))
 | 
				
			||||||
      x-text="date"
 | 
					        }"}
 | 
				
			||||||
    >
 | 
					        x-text="date"
 | 
				
			||||||
      <%= @date %>
 | 
					      >
 | 
				
			||||||
    </time>
 | 
					        <%= @date |> Date.to_iso8601(:extended) %>
 | 
				
			||||||
 | 
					      </time>
 | 
				
			||||||
 | 
					    <% end %>
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -70,12 +68,44 @@ defmodule CanneryWeb.ViewHelpers do
 | 
				
			|||||||
  Displays emoji as text emoji if SHIBAO_MODE is set to true :)
 | 
					  Displays emoji as text emoji if SHIBAO_MODE is set to true :)
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec display_emoji(String.t()) :: String.t()
 | 
					  @spec display_emoji(String.t()) :: String.t()
 | 
				
			||||||
  def display_emoji("😔"),
 | 
					  def display_emoji("😔") do
 | 
				
			||||||
    do:
 | 
					    if Application.get_env(:cannery, CanneryWeb.ViewHelpers)[:shibao_mode], do: "q_q", else: "😔"
 | 
				
			||||||
      if(Application.get_env(:cannery, CanneryWeb.ViewHelpers)[:shibao_mode], do: "q_q", else: "😔")
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def display_emoji(other_emoji), do: other_emoji
 | 
					  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 """
 | 
					  @doc """
 | 
				
			||||||
  Get a random color in `#ffffff` hex format
 | 
					  Get a random color in `#ffffff` hex format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								mix.exs
									
									
									
									
									
								
							@@ -70,6 +70,7 @@ defmodule Cannery.MixProject do
 | 
				
			|||||||
      {:jason, "~> 1.2"},
 | 
					      {:jason, "~> 1.2"},
 | 
				
			||||||
      {:plug_cowboy, "~> 2.5"},
 | 
					      {:plug_cowboy, "~> 2.5"},
 | 
				
			||||||
      {:ecto_psql_extras, "~> 0.6"},
 | 
					      {:ecto_psql_extras, "~> 0.6"},
 | 
				
			||||||
 | 
					      {:eqrcode, "~> 0.1.10"},
 | 
				
			||||||
      {:credo, "~> 1.5", only: [:dev, :test], runtime: false},
 | 
					      {:credo, "~> 1.5", only: [:dev, :test], runtime: false},
 | 
				
			||||||
      {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}
 | 
					      {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								mix.lock
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								mix.lock
									
									
									
									
									
								
							@@ -16,6 +16,7 @@
 | 
				
			|||||||
  "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_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"},
 | 
					  "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"},
 | 
					  "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"},
 | 
					  "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"},
 | 
					  "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"},
 | 
					  "expo": {:hex, :expo, "0.3.0", "13127c1d5f653b2927f2616a4c9ace5ae372efd67c7c2693b87fd0fdc30c6feb", [:mix], [], "hexpm", "fb3cd4bf012a77bc1608915497dae2ff684a06f0fa633c7afa90c4d72b881823"},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,7 +194,7 @@ msgstr "Brandmunition"
 | 
				
			|||||||
msgid "Instance Information"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr "Instanzinformationen"
 | 
					msgstr "Instanzinformationen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr "Einladung deaktiviert"
 | 
					msgstr "Einladung deaktiviert"
 | 
				
			||||||
@@ -441,11 +441,6 @@ msgstr "Art:"
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr "Benutzer"
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -734,11 +729,6 @@ msgstr "Kopien"
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr "Hinzugefügt am:"
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1146,3 +1136,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?"
 | 
					msgstr "Sind sie sicher, dass Sie diese Munition demarkieren möchten?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					msgid "Are you sure you want to delete this shot record?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -179,7 +179,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Instance Information"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -424,11 +424,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr ""
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -717,11 +712,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr ""
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1129,3 +1119,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -424,11 +424,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr ""
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -717,11 +712,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr ""
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1129,3 +1119,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					msgid "Are you sure you want to delete this shot record?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,7 +194,7 @@ msgstr "Incendiaria"
 | 
				
			|||||||
msgid "Instance Information"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr "Información de Instancia"
 | 
					msgstr "Información de Instancia"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr "Invitación Desactivada"
 | 
					msgstr "Invitación Desactivada"
 | 
				
			||||||
@@ -442,11 +442,6 @@ msgstr "Tipo:"
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr "Usuarios"
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -735,11 +730,6 @@ msgstr "Copias"
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr "Añadido en:"
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1148,3 +1138,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr "Está seguro que desea desmontar esta munición?"
 | 
					msgstr "Está seguro que desea desmontar esta munición?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					msgid "Are you sure you want to delete this shot record?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -194,7 +194,7 @@ msgstr "Incendiaire"
 | 
				
			|||||||
msgid "Instance Information"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr "Information de l’instance"
 | 
					msgstr "Information de l’instance"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr "Invitation désactivée"
 | 
					msgstr "Invitation désactivée"
 | 
				
			||||||
@@ -443,11 +443,6 @@ msgstr "Type :"
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr "Utilisateurs"
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -736,11 +731,6 @@ msgstr "Exemplaires"
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr "Ajouté le :"
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1149,3 +1139,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?"
 | 
					msgstr "Êtes-vous certain·e de vouloir désélectionner cette munition ?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					msgid "Are you sure you want to delete this shot record?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,7 +190,7 @@ msgstr ""
 | 
				
			|||||||
msgid "Instance Information"
 | 
					msgid "Instance Information"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/components/invite_card.ex:35
 | 
					#: lib/cannery_web/components/invite_card.ex:41
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Invite Disabled"
 | 
					msgid "Invite Disabled"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
@@ -435,11 +435,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Users"
 | 
					msgid "Users"
 | 
				
			||||||
msgstr ""
 | 
					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
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:24
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Uses left"
 | 
					msgid "Uses left"
 | 
				
			||||||
@@ -728,11 +723,6 @@ msgstr ""
 | 
				
			|||||||
msgid "Added on:"
 | 
					msgid "Added on:"
 | 
				
			||||||
msgstr ""
 | 
					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_registration/new.html.heex:37
 | 
				
			||||||
#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
					#: lib/cannery_web/templates/user_settings/edit.html.heex:130
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
@@ -1140,3 +1130,34 @@ msgstr ""
 | 
				
			|||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Spanish"
 | 
					msgid "Spanish"
 | 
				
			||||||
msgstr ""
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					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?"
 | 
					msgid "Are you sure you want to unstage this ammo?"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:137
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:142
 | 
				
			||||||
#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
					#: lib/cannery_web/live/range_live/index.html.heex:118
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
msgid "Are you sure you want to delete this shot record?"
 | 
					msgid "Are you sure you want to delete this shot record?"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user