17 Commits

Author SHA1 Message Date
05b1630a96 fix dialyzer for otp 28
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-07-05 23:25:44 +00:00
1fd3a1bebe bump version
Some checks failed
continuous-integration/drone/push Build is failing
2025-07-05 23:10:12 +00:00
6e9bc94f35 add better reverse proxy instructions
Some checks are pending
continuous-integration/drone/push Build is running
2025-07-05 23:07:21 +00:00
4e1cf81242 add database upgrade instructions 2025-07-05 23:06:47 +00:00
09e59c94f0 update deps 2025-07-05 22:55:21 +00:00
859e5756ae add new language note to contributing guide
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-13 19:09:01 +00:00
45b46b761d update version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-04-05 04:20:07 +00:00
bda051ebc8 fix cannery logo on home page
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-04-05 04:12:37 +00:00
01fa306429 eliminate possible style conflicts
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-05 04:05:10 +00:00
5cff5d8280 update deps again
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-04-05 03:04:45 +00:00
71778d12a6 shorten config 2025-04-05 02:54:34 +00:00
9b721a170b fix migrations
All checks were successful
continuous-integration/drone/push Build is passing
2025-04-05 02:46:59 +00:00
366a6d160d format migration
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-04-05 01:20:35 +00:00
926d2fe6c2 fix cast_datetime
Some checks are pending
continuous-integration/drone/push Build is running
2025-04-05 01:19:20 +00:00
c7bd7238c6 improve accuracy of timestamps
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-05 01:13:00 +00:00
e2c17b6b51 fix drone
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-05 00:33:09 +00:00
20988ac1ec fix dockerfile
Some checks failed
continuous-integration/drone/push Build is failing
2025-04-05 00:31:35 +00:00
42 changed files with 274 additions and 136 deletions

View File

@@ -17,7 +17,7 @@ steps:
- .mix - .mix
- name: test - name: test
image: elixir:1.18.3-otp-27-alpine image: elixir:1.18.4-otp-28-alpine
environment: environment:
TEST_DATABASE_URL: ecto://postgres:postgres@database/cannery_test TEST_DATABASE_URL: ecto://postgres:postgres@database/cannery_test
HOST: testing.example.tld HOST: testing.example.tld
@@ -31,8 +31,7 @@ steps:
- mix deps.get - mix deps.get
- npm set cache .npm - npm set cache .npm
- npm --prefix ./assets ci --no-audit --prefer-offline - npm --prefix ./assets ci --no-audit --prefer-offline
- npm run --prefix ./assets deploy - mix do phx.digest, gettext.extract, assets.deploy
- mix do phx.digest, gettext.extract
- mix test.all - mix test.all
- name: build and publish stable - name: build and publish stable

View File

@@ -1,3 +1,3 @@
elixir 1.18.3-otp-27 elixir 1.18.4-otp-28
erlang 27.3.1 erlang 28.0.1
nodejs 23.10.0 nodejs 24.3.0

View File

@@ -1,6 +1,11 @@
# v0.9.15
- Update deps
- Add better reverse proxy and database upgrade instructions
# v0.9.14 # v0.9.14
- Update deps - Update deps
- Fix wrapping issues with search bars - Fix wrapping issues with search bars
- Improve accuracy of timestamps
# v0.9.13 # v0.9.13
- Add button to resend email verification email - Add button to resend email verification email

View File

@@ -10,6 +10,9 @@ status](https://weblate.bubbletea.dev/widgets/cannery/-/287x66-black.png)](https
If you're multilingual, this project can use your translations! Visit If you're multilingual, this project can use your translations! Visit
[weblate](https://weblate.bubbletea.dev/engage/cannery/) for more information. [weblate](https://weblate.bubbletea.dev/engage/cannery/) for more information.
Also, if your language isn't displayed here, I'd love to add that language so
you can start! Please contact me at
(shibao@bubbletea.dev)[mailto:shibao@bubbletea.dev] and let me know!
## Style Tips ## Style Tips

View File

@@ -1,4 +1,4 @@
FROM elixir:1.18.3-otp-27-alpine AS build FROM elixir:1.18.4-otp-28-alpine AS build
# install build dependencies # install build dependencies
RUN apk add --no-cache build-base npm git python3 RUN apk add --no-cache build-base npm git python3
@@ -25,13 +25,12 @@ RUN npm --prefix ./assets ci --progress=false --no-audit --loglevel=error
COPY lib lib COPY lib lib
COPY priv priv COPY priv priv
COPY assets assets COPY assets assets
RUN npm run --prefix ./assets deploy
RUN mix do phx.digest, gettext.extract RUN mix do phx.digest, gettext.extract
# compile and build release # compile and build release
# uncomment COPY if rel/ exists # uncomment COPY if rel/ exists
# COPY rel rel # COPY rel rel
RUN mix do compile, release RUN mix do assets.deploy, compile, release
# prepare release image # prepare release image
FROM alpine:latest AS app FROM alpine:latest AS app
@@ -43,6 +42,8 @@ WORKDIR /app
RUN chown nobody:nobody /app RUN chown nobody:nobody /app
ENV MIX_ENV=prod
USER nobody:nobody USER nobody:nobody
COPY --from=build --chown=nobody:nobody /app/_build/prod/rel/cannery ./ COPY --from=build --chown=nobody:nobody /app/_build/prod/rel/cannery ./

View File

@@ -46,6 +46,16 @@ ports:
``` ```
and reverse proxy to `http://localhost:4000`. and reverse proxy to `http://localhost:4000`.
If you don't already have a reverse proxy on the machine, I recommend installing
[Nginx Proxy Manager](https://nginxproxymanager.com/), which is a GUI for Nginx
that makes it easy to configure and modify as your hosting needs change. By
adding NPM to cannery's `docker-compose.yml`, you can avoid needing to bind any
ports to your machine and have all the internal traffic routed through the
generated docker network, which can be a bit more secure. The example
configuration is commented out in the `docker-compose.yml` file, and more
information can be found on their documentation
[here](https://nginxproxymanager.com/setup/).
# Configuration # Configuration
You can use the following environment variables to configure Cannery in You can use the following environment variables to configure Cannery in
@@ -74,6 +84,20 @@ You can use the following environment variables to configure Cannery in
`no-reply@HOST` where `HOST` was previously defined. `no-reply@HOST` where `HOST` was previously defined.
- `EMAIL_NAME`: Sets the sender name in sent emails. Defaults to "Cannery". - `EMAIL_NAME`: Sets the sender name in sent emails. Defaults to "Cannery".
# Upgrading the Database
Typically, PostgreSQL updates can improve the performance of the database, and
the cannery app. However, these require some additional maintenance. While the
typical method is to manually dump and restore the database using the `pg_dump`
tool, I recommend using the
[pgautoupgrade tool](https://github.com/pgautoupgrade/docker-pgautoupgrade),
which can perform this for you automatically. In the `docker-compose.yml` file,
you can do this easily by switching the `image:` value from for example,
`postgres:13` to `pgautoupgrade/pgautoupgrade:17-alpine` and rerun
`docker-compose up -d`. This will automatically migrate your database to
Postgres 17, and then you can switch back to the original `postgres:17` image
for additional performance, or keep using the upgrade image if you'd like.
# Contribution # Contribution
Contributions are greatly appreciated, no ability to code needed! You can browse Contributions are greatly appreciated, no ability to code needed! You can browse

View File

@@ -6,18 +6,19 @@
"": { "": {
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2", "@fortawesome/fontawesome-free": "^6.7.2",
"chart.js": "^4.4.8", "chart.js": "^4.5.0",
"chartjs-adapter-date-fns": "^3.0.0", "chartjs-adapter-date-fns": "^3.0.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"slim-select": "^2.11.0", "slim-select": "^2.12.1",
"topbar": "^3.0.0" "topbar": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"npm-check-updates": "^17.1.16", "npm-check-updates": "^18.0.1",
"standard": "^17.1.2" "standard": "^17.1.2"
}, },
"engines": { "engines": {
"node": "v23.10.0" "node": "v24.3.0",
"npm": "11.4.2"
} }
}, },
"../deps/phoenix": { "../deps/phoenix": {
@@ -562,9 +563,9 @@
} }
}, },
"node_modules/chart.js": { "node_modules/chart.js": {
"version": "4.4.8", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz",
"integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@kurkle/color": "^0.3.0" "@kurkle/color": "^0.3.0"
@@ -2650,9 +2651,9 @@
"dev": true "dev": true
}, },
"node_modules/npm-check-updates": { "node_modules/npm-check-updates": {
"version": "17.1.16", "version": "18.0.1",
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.16.tgz", "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-18.0.1.tgz",
"integrity": "sha512-9nohkfjLRzLfsLVGbO34eXBejvrOOTuw5tvNammH73KEFG5XlFoi3G2TgjTExHtnrKWCbZ+mTT+dbNeSjASIPw==", "integrity": "sha512-MO7mLp/8nm6kZNLLyPgz4gHmr9tLoU+pWPLdXuGAx+oZydBHkHWN0ibTonsrfwC2WEQNIQxuZagYwB67JQpAuw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@@ -3259,9 +3260,9 @@
} }
}, },
"node_modules/slim-select": { "node_modules/slim-select": {
"version": "2.11.0", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/slim-select/-/slim-select-2.11.0.tgz", "resolved": "https://registry.npmjs.org/slim-select/-/slim-select-2.12.1.tgz",
"integrity": "sha512-Y0FEJKIPBy8ax7jArUxICxtKAnhX8GH7ydaFhcrYH7OznfpvxCe8uU2etyuRPKhE23c2LhT2GROFvZzGVplA0g==", "integrity": "sha512-6Ad4M/UZ/xJUOjoNSvYuS9qWoLcEfZj28/Wpkc+fZMi3psZGZvReRU0DmvegFijfTh6Bxhi3wJWUFgNzjXksIQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/standard": { "node_modules/standard": {

View File

@@ -1,6 +1,7 @@
{ {
"engines": { "engines": {
"node": "v23.10.0" "node": "v24.3.0",
"npm": "11.4.2"
}, },
"scripts": { "scripts": {
"format": "standard --fix", "format": "standard --fix",
@@ -8,14 +9,14 @@
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2", "@fortawesome/fontawesome-free": "^6.7.2",
"chart.js": "^4.4.8", "chart.js": "^4.5.0",
"chartjs-adapter-date-fns": "^3.0.0", "chartjs-adapter-date-fns": "^3.0.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"slim-select": "^2.11.0", "slim-select": "^2.12.1",
"topbar": "^3.0.0" "topbar": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"npm-check-updates": "^17.1.16", "npm-check-updates": "^18.0.1",
"standard": "^17.1.2" "standard": "^17.1.2"
} }
} }

View File

@@ -9,8 +9,7 @@ import Config
config :cannery, config :cannery,
env: :dev, env: :dev,
ecto_repos: [Cannery.Repo], ecto_repos: [Cannery.Repo]
generators: [binary_id: true, timestamp_type: :utc_datetime]
config :cannery, Cannery.Accounts, registration: System.get_env("REGISTRATION", "invite") config :cannery, Cannery.Accounts, registration: System.get_env("REGISTRATION", "invite")
@@ -30,9 +29,10 @@ config :cannery, CanneryWeb.Endpoint,
config :cannery, Cannery.Application, automigrate: false config :cannery, Cannery.Application, automigrate: false
config :cannery, :generators, config :cannery, :generators,
migration: true,
binary_id: true, binary_id: true,
sample_binary_id: "11111111-1111-1111-1111-111111111111" migration: true,
sample_binary_id: "11111111-1111-1111-1111-111111111111",
timestamp_type: :utc_datetime_usec
# Configures the mailer # Configures the mailer
# #
@@ -70,8 +70,8 @@ config :tailwind,
version: "4.0.0", version: "4.0.0",
cannery: [ cannery: [
args: ~w( args: ~w(
--input=css/app.css --input=css/style.css
--output=../priv/static/assets/app.css --output=../priv/static/assets/style.css
), ),
cd: Path.expand("../assets", __DIR__) cd: Path.expand("../assets", __DIR__)
] ]

View File

@@ -32,7 +32,12 @@ services:
- cannery-db - cannery-db
cannery-db: cannery-db:
image: postgres:13 image: postgres:17
# To upgrade your database from a previous version, replace the existing
# image with the following line. Once the container has been booted and your
# database updated, you can revert back to the original `postgres:17` image
# if you'd like
# image: pgautoupgrade/pgautoupgrade:17-alpine
container_name: cannery-db container_name: cannery-db
environment: environment:
- POSTGRES_USER="postgres" - POSTGRES_USER="postgres"
@@ -40,4 +45,47 @@ services:
- POSTGRES_DB="cannery" - POSTGRES_DB="cannery"
restart: always restart: always
volumes: volumes:
- ./data:/var/lib/postgresql/data - ./cannery/data:/var/lib/postgresql/data
# Optional, if you don't have a reverse proxy set up already. You can replace
# this with any other reverse proxy like nginx, apache or caddy if you would
# like something more minimalist.
# nginx:
# image: jc21/nginx-proxy-manager
# container_name: nginx
# restart: on-failure
# ports:
# - 443:443
# - 80:80
# # Access via http://localhost:81, although once you access this, you can
# # reverse proxy itself to a domain name to control it from anywhere if
# # you'd like, and then you can remove the following line
# - 127.0.0.1:81:81
# # expose:
# # - 81
# environment:
# # DISABLE_IPV6: 'true'
# DB_MYSQL_HOST: "nginx-db"
# DB_MYSQL_NAME: "nginx"
# DB_MYSQL_PASSWORD: "my-password"
# DB_MYSQL_PORT: 3306
# DB_MYSQL_USER: "nginx"
# PGID: 9000
# PUID: 9000
# volumes:
# - /etc/letsencrypt:/etc/letsencrypt
# - ./nginx/data:/data
# - /tmp:/tmp
# nginx-db:
# image: 'jc21/mariadb-aria:latest'
# container_name: nginx-db
# restart: on-failure
# environment:
# MYSQL_DATABASE: 'nginx'
# MYSQL_PASSWORD: 'my-password'
# MYSQL_ROOT_PASSWORD: 'my-root-password'
# MYSQL_USER: 'nginx'
# volumes:
# - ./nginx/mysql:/var/lib/mysql

View File

@@ -27,6 +27,7 @@ defmodule Cannery do
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id
@timestamps_opts [type: :utc_datetime_usec]
end end
end end

View File

@@ -11,13 +11,13 @@ defmodule Cannery.Accounts.Invite do
field :name, :string field :name, :string
field :token, :string field :token, :string
field :uses_left, :integer, default: nil field :uses_left, :integer, default: nil
field :disabled_at, :naive_datetime field :disabled_at, :utc_datetime_usec
belongs_to :created_by, User belongs_to :created_by, User
has_many :users, User has_many :users, User
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -25,12 +25,12 @@ defmodule Cannery.Accounts.Invite do
name: String.t(), name: String.t(),
token: token(), token: token(),
uses_left: integer() | nil, uses_left: integer() | nil,
disabled_at: NaiveDateTime.t(), disabled_at: DateTime.t(),
created_by: User.t() | nil | Association.NotLoaded.t(), created_by: User.t() | nil | Association.NotLoaded.t(),
created_by_id: User.id() | nil, created_by_id: User.id() | nil,
users: [User.t()] | Association.NotLoaded.t(), users: [User.t()] | Association.NotLoaded.t(),
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_invite :: %__MODULE__{} @type new_invite :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -123,7 +123,7 @@ defmodule Cannery.Accounts.Invites do
end end
defp decrement_invite_changeset(%Invite{uses_left: 1} = invite) do defp decrement_invite_changeset(%Invite{uses_left: 1} = invite) do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) now = DateTime.utc_now()
invite |> Invite.update_changeset(%{uses_left: 0, disabled_at: now}) invite |> Invite.update_changeset(%{uses_left: 0, disabled_at: now})
end end

View File

@@ -22,7 +22,7 @@ defmodule Cannery.Accounts.User do
field :password, :string, virtual: true field :password, :string, virtual: true
field :hashed_password, :string field :hashed_password, :string
field :current_password, :string, virtual: true, redact: true field :current_password, :string, virtual: true, redact: true
field :confirmed_at, :naive_datetime field :confirmed_at, :utc_datetime_usec
field :role, Ecto.Enum, values: [:admin, :user], default: :user field :role, Ecto.Enum, values: [:admin, :user], default: :user
field :locale, :string field :locale, :string
@@ -30,7 +30,7 @@ defmodule Cannery.Accounts.User do
belongs_to :invite, Invite belongs_to :invite, Invite
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %User{ @type t :: %User{
@@ -38,14 +38,14 @@ defmodule Cannery.Accounts.User do
email: String.t(), email: String.t(),
password: String.t(), password: String.t(),
hashed_password: String.t(), hashed_password: String.t(),
confirmed_at: NaiveDateTime.t(), confirmed_at: DateTime.t(),
role: role(), role: role(),
locale: String.t() | nil, locale: String.t() | nil,
created_invites: [Invite.t()] | Association.NotLoaded.t(), created_invites: [Invite.t()] | Association.NotLoaded.t(),
invite: Invite.t() | nil | Association.NotLoaded.t(), invite: Invite.t() | nil | Association.NotLoaded.t(),
invite_id: Invite.id() | nil, invite_id: Invite.id() | nil,
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_user :: %User{} @type new_user :: %User{}
@type id :: UUID.t() @type id :: UUID.t()
@@ -168,7 +168,7 @@ defmodule Cannery.Accounts.User do
""" """
@spec confirm_changeset(t() | changeset()) :: changeset() @spec confirm_changeset(t() | changeset()) :: changeset()
def confirm_changeset(user_or_changeset) do def confirm_changeset(user_or_changeset) do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) now = DateTime.utc_now()
user_or_changeset |> change(confirmed_at: now) user_or_changeset |> change(confirmed_at: now)
end end

View File

@@ -32,7 +32,7 @@ defmodule Cannery.Accounts.UserToken do
sent_to: String.t(), sent_to: String.t(),
user: User.t() | Association.NotLoaded.t(), user: User.t() | Association.NotLoaded.t(),
user_id: User.id() | nil, user_id: User.id() | nil,
inserted_at: NaiveDateTime.t() inserted_at: DateTime.t()
} }
@type new_user_token :: %__MODULE__{} @type new_user_token :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -24,7 +24,7 @@ defmodule Cannery.ActivityLog.ShotRecord do
field :user_id, :binary_id field :user_id, :binary_id
field :pack_id, :binary_id field :pack_id, :binary_id
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -34,8 +34,8 @@ defmodule Cannery.ActivityLog.ShotRecord do
date: Date.t() | nil, date: Date.t() | nil,
pack_id: Pack.id(), pack_id: Pack.id(),
user_id: User.id(), user_id: User.id(),
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_shot_record :: %__MODULE__{} @type new_shot_record :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -920,7 +920,7 @@ defmodule Cannery.Ammo do
multiplier <= @pack_create_limit and multiplier <= @pack_create_limit and
type_id |> is_binary() and type_id |> is_binary() and
container_id |> is_binary() do container_id |> is_binary() do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) now = DateTime.utc_now()
changesets = changesets =
Enum.map(1..multiplier, fn _count -> Enum.map(1..multiplier, fn _count ->

View File

@@ -30,7 +30,7 @@ defmodule Cannery.Ammo.Pack do
field :container_id, :binary_id field :container_id, :binary_id
field :user_id, :binary_id field :user_id, :binary_id
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -44,8 +44,8 @@ defmodule Cannery.Ammo.Pack do
type_id: Type.id(), type_id: Type.id(),
container_id: Container.id(), container_id: Container.id(),
user_id: User.id(), user_id: User.id(),
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_pack :: %__MODULE__{} @type new_pack :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -90,7 +90,7 @@ defmodule Cannery.Ammo.Type do
field :user_id, :binary_id field :user_id, :binary_id
has_many :packs, Pack has_many :packs, Pack
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -129,8 +129,8 @@ defmodule Cannery.Ammo.Type do
dram_equivalent: String.t() | nil, dram_equivalent: String.t() | nil,
user_id: User.id(), user_id: User.id(),
packs: [Pack.t()] | nil, packs: [Pack.t()] | nil,
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_type :: %__MODULE__{} @type new_type :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -27,7 +27,7 @@ defmodule Cannery.Containers.Container do
many_to_many :tags, Tag, join_through: ContainerTag many_to_many :tags, Tag, join_through: ContainerTag
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -39,8 +39,8 @@ defmodule Cannery.Containers.Container do
type: String.t(), type: String.t(),
user_id: User.id(), user_id: User.id(),
tags: [Tag.t()] | nil, tags: [Tag.t()] | nil,
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_container :: %__MODULE__{} @type new_container :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -11,7 +11,7 @@ defmodule Cannery.Containers.ContainerTag do
belongs_to :container, Container belongs_to :container, Container
belongs_to :tag, Tag belongs_to :tag, Tag
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -20,8 +20,8 @@ defmodule Cannery.Containers.ContainerTag do
container_id: Container.id(), container_id: Container.id(),
tag: Tag.t(), tag: Tag.t(),
tag_id: Tag.id(), tag_id: Tag.id(),
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_container_tag :: %__MODULE__{} @type new_container_tag :: %__MODULE__{}
@type id :: UUID.t() @type id :: UUID.t()

View File

@@ -20,7 +20,7 @@ defmodule Cannery.Containers.Tag do
field :user_id, :binary_id field :user_id, :binary_id
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime_usec)
end end
@type t :: %__MODULE__{ @type t :: %__MODULE__{
@@ -29,8 +29,8 @@ defmodule Cannery.Containers.Tag do
bg_color: String.t(), bg_color: String.t(),
text_color: String.t(), text_color: String.t(),
user_id: User.id(), user_id: User.id(),
inserted_at: NaiveDateTime.t(), inserted_at: DateTime.t(),
updated_at: NaiveDateTime.t() updated_at: DateTime.t()
} }
@type new_tag() :: %__MODULE__{} @type new_tag() :: %__MODULE__{}
@type id() :: UUID.t() @type id() :: UUID.t()

View File

@@ -136,7 +136,7 @@ defmodule CanneryWeb.CoreComponents do
attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil" attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil"
@doc """ @doc """
Phoenix.Component for a <time> element that renders the naivedatetime in the Phoenix.Component for a <time> element that renders the DateTime in the
user's local timezone user's local timezone
""" """
def datetime(assigns) def datetime(assigns)
@@ -153,9 +153,9 @@ defmodule CanneryWeb.CoreComponents do
""" """
def date_range(assigns) def date_range(assigns)
@spec cast_datetime(NaiveDateTime.t() | nil) :: String.t() @spec cast_datetime(DateTime.t() | nil) :: String.t()
defp cast_datetime(%NaiveDateTime{} = datetime) do defp cast_datetime(%DateTime{} = datetime) do
datetime |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(:extended) datetime |> DateTime.to_iso8601(:extended)
end end
defp cast_datetime(_datetime), do: "" defp cast_datetime(_datetime), do: ""

View File

@@ -8,7 +8,7 @@
<.live_title suffix={" | #{gettext("Cannery")}"}> <.live_title suffix={" | #{gettext("Cannery")}"}>
{assigns[:page_title] || gettext("Cannery")} {assigns[:page_title] || gettext("Cannery")}
</.live_title> </.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} /> <link phx-track-static rel="stylesheet" href={~p"/assets/style.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}> <script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script> </script>
</head> </head>

View File

@@ -1,16 +1,16 @@
<div class="mx-auto px-8 sm:px-16 flex flex-col justify-center items-center text-center space-y-4 max-w-3xl"> <div class="flex flex-col justify-center items-center px-8 mx-auto space-y-4 max-w-3xl text-center sm:px-16">
<img <img
src={~p"/images/cannery.svg"} src={~p"/images/cannery.svg"}
alt={gettext("Cannery logo")} alt={gettext("Cannery logo")}
class="inline-block w-32 hover:-mt-2 hover:mb-2 transition-all duration-500 ease-in-out" class="inline-block pt-2 pb-0 mb-8 w-32 transition-all duration-500 ease-in-out hover:pt-0 hover:pb-2"
title={gettext("isn't he cute >:3")} title={gettext("isn't he cute >:3")}
/> />
<h1 class="title text-primary-600 text-2xl"> <h1 class="text-2xl title text-primary-600">
{gettext("Welcome to Cannery")} {gettext("Welcome to Cannery")}
</h1> </h1>
<h2 class="title text-primary-600 text-lg"> <h2 class="text-lg title text-primary-600">
{gettext("The self-hosted firearm tracker website")} {gettext("The self-hosted firearm tracker website")}
</h2> </h2>
@@ -48,8 +48,8 @@
<hr class="hr" /> <hr class="hr" />
<ul class="flex flex-col space-y-2 text-center justify-center"> <ul class="flex flex-col justify-center space-y-2 text-center">
<h2 class="title text-primary-600 text-lg"> <h2 class="text-lg title text-primary-600">
{gettext("Instance Information")} {gettext("Instance Information")}
</h2> </h2>
@@ -104,8 +104,8 @@
<hr class="hr" /> <hr class="hr" />
<ul class="flex flex-col space-y-2 text-center justify-center"> <ul class="flex flex-col justify-center space-y-2 text-center">
<h2 class="title text-primary-600 text-lg"> <h2 class="text-lg title text-primary-600">
{gettext("Get involved!")} {gettext("Get involved!")}
</h2> </h2>

View File

@@ -93,7 +93,7 @@ defmodule CanneryWeb.InviteLive.Index do
%{"id" => id}, %{"id" => id},
%{assigns: %{current_user: current_user}} = socket %{assigns: %{current_user: current_user}} = socket
) do ) do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) now = DateTime.utc_now()
socket = socket =
Invites.get_invite!(id, current_user) Invites.get_invite!(id, current_user)

12
mix.exs
View File

@@ -4,13 +4,17 @@ defmodule Cannery.MixProject do
def project do def project do
[ [
app: :cannery, app: :cannery,
version: "0.9.13", version: "0.9.15",
elixir: "1.18.3", elixir: "1.18.4",
elixirc_paths: elixirc_paths(Mix.env()), elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
aliases: aliases(), aliases: aliases(),
deps: deps(), deps: deps(),
dialyzer: [plt_add_apps: [:ex_unit]], dialyzer: [
# Added for OTP 28 bug https://github.com/jeremyjh/dialyxir/issues/561
flags: [:no_opaque],
plt_add_apps: [:ex_unit]
],
consolidate_protocols: Mix.env() not in [:dev, :test], consolidate_protocols: Mix.env() not in [:dev, :test],
preferred_cli_env: ["test.all": :test], preferred_cli_env: ["test.all": :test],
# ExDoc # ExDoc
@@ -68,7 +72,7 @@ defmodule Cannery.MixProject do
{:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 1.0.0"}, {:phoenix_live_view, "~> 1.0.0"},
{:phoenix, "~> 1.7.19"}, {:phoenix, "~> 1.7.19"},
{:plug_cowboy, "~> 2.7"}, {:plug_cowboy, "~> 2.7.0"},
{:postgrex, ">= 0.0.0"}, {:postgrex, ">= 0.0.0"},
{:swoosh, "~> 1.6"}, {:swoosh, "~> 1.6"},
{:tailwind, "~> 0.2", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.2", runtime: Mix.env() == :dev},

View File

@@ -1,60 +1,60 @@
%{ %{
"bandit": {:hex, :bandit, "1.6.10", "ec218849b753b84ed52fb7f19f42bec4ab8b1ff3f74806c6525e4b53eafcad60", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5c5e1d155cbdf98610197d2814934ef431e70b5fd4f487b19c341d9b49cc19a2"}, "bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.2.1", "e361261a0401d82dadc1ab7b969f91d250bf7577283e933fe8c5b72f8f5b3c46", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "81170177d5c2e280d12141a0b9d9e299bf731535e2d959982bdcd4cfe3c82865"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.12", "053f0e32700cbec356280c0e835df425a3be4bc1e0627b714330ad9d0f05497f", [:mix], [], "hexpm", "3dca286b2186055ba0c9449b4e95b97bf1b57b47c1f2644555879e659960c224"}, "castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"},
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"}, "comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
"cowboy": {:hex, :cowboy, "2.13.0", "09d770dd5f6a22cc60c071f432cd7cb87776164527f205c5a6b0f24ff6b38990", [:make, :rebar3], [{:cowlib, ">= 2.14.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e724d3a70995025d654c1992c7b11dbfea95205c047d86ff9bf1cda92ddc5614"}, "cowboy": {:hex, :cowboy, "2.13.0", "09d770dd5f6a22cc60c071f432cd7cb87776164527f205c5a6b0f24ff6b38990", [:make, :rebar3], [{:cowlib, ">= 2.14.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e724d3a70995025d654c1992c7b11dbfea95205c047d86ff9bf1cda92ddc5614"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.14.0", "623791c56c1cc9df54a71a9c55147a401549917f00a2e48a6ae12b812c586ced", [:make, :rebar3], [], "hexpm", "0af652d1550c8411c3b58eed7a035a7fb088c0b86aff6bc504b0bc3b7f791aa2"}, "cowlib": {:hex, :cowlib, "2.15.0", "3c97a318a933962d1c12b96ab7c1d728267d2c523c25a5b57b0f93392b6e9e25", [:make, :rebar3], [], "hexpm", "4f00c879a64b4fe7c8fcb42a4281925e9ffdb928820b03c3ad325a617e857532"},
"credo": {:hex, :credo, "1.7.11", "d3e805f7ddf6c9c854fd36f089649d7cf6ba74c42bc3795d587814e3c9847102", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "56826b4306843253a66e47ae45e98e7d284ee1f95d53d1612bb483f88a8cf219"}, "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "db_connection": {:hex, :db_connection, "2.8.0", "64fd82cfa6d8e25ec6660cea73e92a4cbc6a18b31343910427b702838c4b33b2", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "008399dae5eee1bf5caa6e86d204dcb44242c82b1ed5e22c881f2c34da201b15"},
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
"dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"}, "dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
"dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"}, "dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"},
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
"ecto": {:hex, :ecto, "3.12.5", "4a312960ce612e17337e7cefcf9be45b95a3be6b36b6f94dfb3d8c361d631866", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6eb18e80bef8bb57e17f5a7f068a1719fbda384d40fc37acb8eb8aeca493b6ea"}, "ecto": {:hex, :ecto, "3.13.2", "7d0c0863f3fc8d71d17fc3ad3b9424beae13f02712ad84191a826c7169484f01", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "669d9291370513ff56e7b7e7081b7af3283d02e046cf3d403053c557894a0b3e"},
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.8.7", "49943fe6bce07281fe3adfc2a23d3794e2acc644dfe98411cb5712ffecb6ad1a", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "ac0a0bce57ffe36b30fac2a2d0d427b04de016e6af5db6f4b41afa1241f39cda"}, "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.8.8", "aa02529c97f69aed5722899f5dc6360128735a92dd169f23c5d50b1f7fdede08", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "04c63d92b141723ad6fed2e60a4b461ca00b3594d16df47bbc48f1f4534f2c49"},
"ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 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", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"}, "ecto_sql": {:hex, :ecto_sql, "3.13.2", "a07d2461d84107b3d037097c822ffdd36ed69d1cf7c0f70e12a3d1decf04e2e1", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 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", "539274ab0ecf1a0078a6a72ef3465629e4d6018a3028095dc90f60a19c371717"},
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
"eqrcode": {:hex, :eqrcode, "0.2.1", "d12838813e8fc87b8940cc05f9baadb189031f6009facdc56ff074375ec73b6e", [:mix], [], "hexpm", "d5828a222b904c68360e7dc2a40c3ef33a1328b7c074583898040f389f928025"}, "eqrcode": {:hex, :eqrcode, "0.2.1", "d12838813e8fc87b8940cc05f9baadb189031f6009facdc56ff074375ec73b6e", [:mix], [], "hexpm", "d5828a222b904c68360e7dc2a40c3ef33a1328b7c074583898040f389f928025"},
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"esbuild": {:hex, :esbuild, "0.9.0", "f043eeaca4932ca8e16e5429aebd90f7766f31ac160a25cbd9befe84f2bc068f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b415027f71d5ab57ef2be844b2a10d0c1b5a492d431727f43937adce22ba45ae"}, "esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"},
"ex_doc": {:hex, :ex_doc, "0.37.3", "f7816881a443cd77872b7d6118e8a55f547f49903aef8747dbcb345a75b462f9", [:mix], [{:earmark_parser, "~> 1.4.42", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "e6aebca7156e7c29b5da4daa17f6361205b2ae5f26e5c7d8ca0d3f7e18972233"}, "ex_doc": {:hex, :ex_doc, "0.38.2", "504d25eef296b4dec3b8e33e810bc8b5344d565998cd83914ffe1b8503737c02", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "732f2d972e42c116a70802f9898c51b54916e542cc50968ac6980512ec90f42b"},
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"}, "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
"floki": {:hex, :floki, "0.37.1", "d7aaee758c8a5b4a7495799a4260754fec5530d95b9c383c03b27359dea117cf", [:mix], [], "hexpm", "673d040cb594d31318d514590246b6dd587ed341d3b67e17c1c0eb8ce7ca6f04"}, "floki": {:hex, :floki, "0.38.0", "62b642386fa3f2f90713f6e231da0fa3256e41ef1089f83b6ceac7a3fd3abf33", [:mix], [], "hexpm", "a5943ee91e93fb2d635b612caf5508e36d37548e84928463ef9dd986f0d1abd9"},
"gen_smtp": {:hex, :gen_smtp, "1.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"}, "gen_smtp": {:hex, :gen_smtp, "1.3.0", "62c3d91f0dcf6ce9db71bcb6881d7ad0d1d834c7f38c13fa8e952f4104a8442e", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0b73fbf069864ecbce02fe653b16d3f35fd889d0fdd4e14527675565c39d84e6"},
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
"oban": {:hex, :oban, "2.19.4", "045adb10db1161dceb75c254782f97cdc6596e7044af456a59decb6d06da73c1", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fcc6219e6464525b808d97add17896e724131f498444a292071bf8991c99f97"}, "oban": {:hex, :oban, "2.19.4", "045adb10db1161dceb75c254782f97cdc6596e7044af456a59decb6d06da73c1", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fcc6219e6464525b808d97add17896e724131f498444a292071bf8991c99f97"},
"phoenix": {:hex, :phoenix, "1.7.21", "14ca4f1071a5f65121217d6b57ac5712d1857e40a0833aff7a691b7870fc9a3b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "336dce4f86cba56fed312a7d280bf2282c720abb6074bdb1b61ec8095bdd0bc9"}, "phoenix": {:hex, :phoenix, "1.7.21", "14ca4f1071a5f65121217d6b57ac5712d1857e40a0833aff7a691b7870fc9a3b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "336dce4f86cba56fed312a7d280bf2282c720abb6074bdb1b61ec8095bdd0bc9"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.5", "c4ef322acd15a574a8b1a08eff0ee0a85e73096b53ce1403b6563709f15e1cea", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "26ec3208eef407f31b748cadd044045c6fd485fbff168e35963d2f9dfff28d4b"},
"phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"}, "phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"},
"phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"}, "phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.6", "7b1f0327f54c9eb69845fd09a77accf922f488c549a7e7b8618775eb603a62c7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "1681ab813ec26ca6915beb3414aa138f298e17721dc6a2bde9e6eb8a62360ff6"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"}, "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.0", "2791fac0e2776b640192308cc90c0dbcf67843ad51387ed4ecae2038263d708d", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b3a1fa036d7eb2f956774eda7a7638cf5123f8f2175aca6d6420a7f95e598e1c"},
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.9", "4dc5e535832733df68df22f9de168b11c0c74bca65b27b088a10ac36dfb75d04", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1dccb04ec8544340e01608e108f32724458d0ac4b07e551406b3b920c40ba2e5"}, "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.17", "beeb16d83a7d3760f7ad463df94e83b087577665d2acc0bf2987cd7d9778068f", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a4ca05c1eb6922c4d07a508a75bfa12c45e5f4d8f77ae83283465f02c53741e1"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
"plug": {:hex, :plug, "1.17.0", "a0832e7af4ae0f4819e0c08dd2e7482364937aea6a8a997a679f2cbb7e026b2e", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f6692046652a69a00a5a21d0b7e11fcf401064839d59d6b8787f23af55b1e6bc"}, "plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
"plug_cowboy": {:hex, :plug_cowboy, "2.7.3", "1304d36752e8bdde213cea59ef424ca932910a91a07ef9f3874be709c4ddb94b", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "77c95524b2aa5364b247fa17089029e73b951ebc1adeef429361eab0bb55819d"}, "plug_cowboy": {:hex, :plug_cowboy, "2.7.4", "729c752d17cf364e2b8da5bdb34fb5804f56251e88bb602aff48ae0bd8673d11", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "9b85632bd7012615bae0a5d70084deb1b25d2bcbb32cab82d1e9a1e023168aa3"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
"postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"}, "postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"},
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"}, "ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
"swoosh": {:hex, :swoosh, "1.18.3", "ca12197550bd7456654179055b1446168cc0f55067f784a3707e0e4462e269f5", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a533daccea84e887a061a919295212b37f4f2c7916436037eb8be7f1265bacba"}, "swoosh": {:hex, :swoosh, "1.19.3", "02ad4455939f502386e4e1443d4de94c514995fd0e51b3cafffd6bd270ffe81c", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "04a10f8496786b744b84130e3510eb53ca51e769c39511b65023bdf4136b732f"},
"table_rex": {:hex, :table_rex, "4.1.0", "fbaa8b1ce154c9772012bf445bfb86b587430fb96f3b12022d3f35ee4a68c918", [:mix], [], "hexpm", "95932701df195d43bc2d1c6531178fc8338aa8f38c80f098504d529c43bc2601"}, "table_rex": {:hex, :table_rex, "4.1.0", "fbaa8b1ce154c9772012bf445bfb86b587430fb96f3b12022d3f35ee4a68c918", [:mix], [], "hexpm", "95932701df195d43bc2d1c6531178fc8338aa8f38c80f098504d529c43bc2601"},
"tailwind": {:hex, :tailwind, "0.3.1", "a89d2835c580748c7a975ad7dd3f2ea5e63216dc16d44f9df492fbd12c094bed", [:mix], [], "hexpm", "98a45febdf4a87bc26682e1171acdedd6317d0919953c353fcd1b4f9f4b676a2"}, "tailwind": {:hex, :tailwind, "0.3.1", "a89d2835c580748c7a975ad7dd3f2ea5e63216dc16d44f9df492fbd12c094bed", [:mix], [], "hexpm", "98a45febdf4a87bc26682e1171acdedd6317d0919953c353fcd1b4f9f4b676a2"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
"telemetry_poller": {:hex, :telemetry_poller, "1.2.0", "ba82e333215aed9dd2096f93bd1d13ae89d249f82760fcada0850ba33bac154b", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7216e21a6c326eb9aa44328028c34e9fd348fb53667ca837be59d0aa2a0156e8"}, "telemetry_poller": {:hex, :telemetry_poller, "1.2.0", "ba82e333215aed9dd2096f93bd1d13ae89d249f82760fcada0850ba33bac154b", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7216e21a6c326eb9aa44328028c34e9fd348fb53667ca837be59d0aa2a0156e8"},
"thousand_island": {:hex, :thousand_island, "1.3.12", "590ff651a6d2a59ed7eabea398021749bdc664e2da33e0355e6c64e7e1a2ef93", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "55d0b1c868b513a7225892b8a8af0234d7c8981a51b0740369f3125f7c99a549"}, "thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
} }

View File

@@ -10,7 +10,7 @@ defmodule Cannery.Repo.Migrations.CreateUsersAuthTables do
add :hashed_password, :string, null: false add :hashed_password, :string, null: false
add :confirmed_at, :naive_datetime add :confirmed_at, :naive_datetime
add :role, :string add :role, :string
timestamps(type: :utc_datetime) timestamps()
end end
create unique_index(:users, [:email]) create unique_index(:users, [:email])

View File

@@ -10,7 +10,7 @@ defmodule Cannery.Repo.Migrations.CreateTags do
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:tags, [:user_id]) create index(:tags, [:user_id])

View File

@@ -31,7 +31,7 @@ defmodule Cannery.Repo.Migrations.CreateAmmoTypes do
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
end end
end end

View File

@@ -11,7 +11,7 @@ defmodule Cannery.Repo.Migrations.CreateContainers do
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:containers, [:user_id]) create index(:containers, [:user_id])

View File

@@ -12,7 +12,7 @@ defmodule Cannery.Repo.Migrations.CreateAmmoGroups do
add :container_id, references(:containers, on_delete: :nothing, type: :binary_id) add :container_id, references(:containers, on_delete: :nothing, type: :binary_id)
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:ammo_groups, [:ammo_type_id]) create index(:ammo_groups, [:ammo_type_id])

View File

@@ -11,7 +11,7 @@ defmodule Cannery.Repo.Migrations.CreateInvites do
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:invites, [:user_id]) create index(:invites, [:user_id])

View File

@@ -8,7 +8,7 @@ defmodule Cannery.Repo.Migrations.CreateContainerTags do
add :container_id, references(:containers, on_delete: :delete_all, type: :binary_id) add :container_id, references(:containers, on_delete: :delete_all, type: :binary_id)
add :tag_id, references(:tags, on_delete: :delete_all, type: :binary_id) add :tag_id, references(:tags, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:container_tags, [:container_id]) create index(:container_tags, [:container_id])

View File

@@ -11,7 +11,7 @@ defmodule Cannery.Repo.Migrations.CreateShotGroups do
add :user_id, references(:users, on_delete: :delete_all, type: :binary_id) add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
add :ammo_group_id, references(:ammo_groups, on_delete: :delete_all, type: :binary_id) add :ammo_group_id, references(:ammo_groups, on_delete: :delete_all, type: :binary_id)
timestamps(type: :utc_datetime) timestamps()
end end
create index(:shot_groups, [:id]) create index(:shot_groups, [:id])

View File

@@ -0,0 +1,51 @@
defmodule Cannery.Repo.Migrations.SetUtcDatetime do
use Ecto.Migration
def change do
alter table(:users) do
modify :confirmed_at, :utc_datetime_usec, from: :naive_datetime
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:users_tokens) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:tags) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:types) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:containers) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:packs) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:invites) do
modify :disabled_at, :utc_datetime_usec, from: :naive_datetime
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:container_tags) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
alter table(:shot_records) do
modify :inserted_at, :utc_datetime_usec, from: :naive_datetime
modify :updated_at, :utc_datetime_usec, from: :naive_datetime
end
end
end

View File

@@ -131,8 +131,8 @@ defmodule CanneryWeb.ExportControllerTest do
"id" => current_user.id, "id" => current_user.id,
"locale" => current_user.locale, "locale" => current_user.locale,
"role" => to_string(current_user.role), "role" => to_string(current_user.role),
"inserted_at" => current_user.inserted_at |> NaiveDateTime.to_iso8601(), "inserted_at" => current_user.inserted_at |> DateTime.to_iso8601(),
"updated_at" => current_user.updated_at |> NaiveDateTime.to_iso8601() "updated_at" => current_user.updated_at |> DateTime.to_iso8601()
} }
json_resp = conn |> json_response(200) json_resp = conn |> json_response(200)

View File

@@ -305,7 +305,7 @@ defmodule CanneryWeb.ContainerLiveTest do
{:ok, _show_live, html} = live(conn, ~p"/container/#{container}") {:ok, _show_live, html} = live(conn, ~p"/container/#{container}")
assert html =~ type_name assert html =~ type_name
assert html =~ "\n20\n" assert html =~ " 20\n"
end end
test "displays pack in table", test "displays pack in table",
@@ -318,7 +318,7 @@ defmodule CanneryWeb.ContainerLiveTest do
|> render_click() |> render_click()
assert html =~ type_name assert html =~ type_name
assert html =~ "\n20\n" assert html =~ " 20\n"
end end
end end
end end

View File

@@ -157,7 +157,7 @@ defmodule CanneryWeb.PackLiveTest do
|> follow_redirect(conn, ~p"/ammo") |> follow_redirect(conn, ~p"/ammo")
assert html =~ "Ammo added successfully" assert html =~ "Ammo added successfully"
assert html =~ "\n42\n" assert html =~ " 42\n"
end end
test "saves multiple new packs", %{conn: conn, current_user: current_user} do test "saves multiple new packs", %{conn: conn, current_user: current_user} do
@@ -220,7 +220,7 @@ defmodule CanneryWeb.PackLiveTest do
|> follow_redirect(conn, ~p"/ammo") |> follow_redirect(conn, ~p"/ammo")
assert html =~ "Ammo updated successfully" assert html =~ "Ammo updated successfully"
assert html =~ "\n43\n" assert html =~ " 43\n"
end end
test "clones pack in listing", %{conn: conn, pack: pack} do test "clones pack in listing", %{conn: conn, pack: pack} do
@@ -242,7 +242,7 @@ defmodule CanneryWeb.PackLiveTest do
|> follow_redirect(conn, ~p"/ammo") |> follow_redirect(conn, ~p"/ammo")
assert html =~ "Ammo added successfully" assert html =~ "Ammo added successfully"
assert html =~ "\n42\n" assert html =~ " 42\n"
assert html =~ "$#{display_currency(120.5)}" assert html =~ "$#{display_currency(120.5)}"
end end
@@ -286,7 +286,7 @@ defmodule CanneryWeb.PackLiveTest do
|> follow_redirect(conn, ~p"/ammo") |> follow_redirect(conn, ~p"/ammo")
assert html =~ "Ammo added successfully" assert html =~ "Ammo added successfully"
assert html =~ "\n43\n" assert html =~ " 43\n"
assert html =~ "$#{display_currency(120.5)}" assert html =~ "$#{display_currency(120.5)}"
end end
@@ -334,7 +334,7 @@ defmodule CanneryWeb.PackLiveTest do
assert html =~ "Show used" assert html =~ "Show used"
refute html =~ "$#{display_currency(50.00)}" refute html =~ "$#{display_currency(50.00)}"
percentage = pack |> Ammo.get_percentage_remaining(current_user) percentage = pack |> Ammo.get_percentage_remaining(current_user)
refute html =~ "\n#{"#{percentage}%"}\n" refute html =~ " #{"#{percentage}%"}\n"
html = html =
show_live show_live
@@ -343,7 +343,7 @@ defmodule CanneryWeb.PackLiveTest do
assert html =~ "$#{display_currency(50.00)}" assert html =~ "$#{display_currency(50.00)}"
percentage = pack |> Ammo.get_percentage_remaining(current_user) percentage = pack |> Ammo.get_percentage_remaining(current_user)
assert html =~ "\n#{"#{percentage}%"}\n" assert html =~ " #{"#{percentage}%"}\n"
end end
end end

View File

@@ -261,9 +261,9 @@ defmodule CanneryWeb.TypeLiveTest do
assert html =~ "Total ever rounds" assert html =~ "Total ever rounds"
assert html =~ "Used packs" assert html =~ "Used packs"
assert html =~ "Total ever packs" assert html =~ "Total ever packs"
assert html =~ "\n20\n" assert html =~ "20\n"
assert html =~ "\n0\n" assert html =~ " 0\n"
assert html =~ "\n1\n" assert html =~ " 1\n"
shot_record_fixture(%{count: 5}, current_user, pack) shot_record_fixture(%{count: 5}, current_user, pack)
{:ok, index_live, _html} = live(conn, ~p"/catalog") {:ok, index_live, _html} = live(conn, ~p"/catalog")
@@ -273,8 +273,8 @@ defmodule CanneryWeb.TypeLiveTest do
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/)
|> render_click() |> render_click()
assert html =~ "\n15\n" assert html =~ " 15\n"
assert html =~ "\n5\n" assert html =~ " 5\n"
end end
end end
@@ -325,7 +325,7 @@ defmodule CanneryWeb.TypeLiveTest do
} do } do
{:ok, _show_live, html} = live(conn, ~p"/type/#{type}") {:ok, _show_live, html} = live(conn, ~p"/type/#{type}")
assert html =~ type_name assert html =~ type_name
assert html =~ "\n20\n" assert html =~ " 20\n"
assert html =~ container_name assert html =~ container_name
end end
@@ -338,7 +338,7 @@ defmodule CanneryWeb.TypeLiveTest do
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/) |> element(~s/input[type="checkbox"][aria-labelledby="toggle_table-label"}]/)
|> render_click() |> render_click()
assert html =~ "\n20\n" assert html =~ " 20\n"
assert html =~ container_name assert html =~ container_name
end end
end end
@@ -350,14 +350,14 @@ defmodule CanneryWeb.TypeLiveTest do
%{conn: conn, type: type, container: %{name: container_name}} do %{conn: conn, type: type, container: %{name: container_name}} do
{:ok, show_live, html} = live(conn, ~p"/type/#{type}") {:ok, show_live, html} = live(conn, ~p"/type/#{type}")
assert html =~ "Show used" assert html =~ "Show used"
refute html =~ "\n20\n" refute html =~ " 20\n"
html = html =
show_live show_live
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/)
|> render_click() |> render_click()
assert html =~ "\n20\n" assert html =~ " 20\n"
assert html =~ "Empty" assert html =~ "Empty"
assert html =~ container_name assert html =~ container_name
end end
@@ -372,14 +372,14 @@ defmodule CanneryWeb.TypeLiveTest do
|> render_click() |> render_click()
assert html =~ "Show used" assert html =~ "Show used"
refute html =~ "\n20\n" refute html =~ " 20\n"
html = html =
show_live show_live
|> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/) |> element(~s/input[type="checkbox"][aria-labelledby="toggle_show_used-label"}]/)
|> render_click() |> render_click()
assert html =~ "\n20\n" assert html =~ " 20\n"
assert html =~ "Empty" assert html =~ "Empty"
assert html =~ container_name assert html =~ container_name
end end