30 Commits

Author SHA1 Message Date
36f385c7f3 update js dependencies
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2024-12-30 20:09:00 -05:00
ddb8bbec53 downgrade elixir version for images
Some checks reported errors
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build was killed
2024-12-30 19:45:33 -05:00
1e55039a67 fix style issues
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2024-12-30 19:38:34 -05:00
2346a82a46 fix new invite button not working 2024-12-30 19:38:33 -05:00
b63c6bd318 fix descriptions possibly overflowing widths 2024-12-30 19:38:24 -05:00
b72a79c380 update gettext syntax 2024-12-30 19:38:11 -05:00
5cd7a7eef0 update dependencies 2024-12-30 19:05:01 -05:00
f6dc41498b update versions 2024-12-30 19:02:04 -05:00
1c912a1600 improve testing db timeout 2024-07-28 13:49:22 -04:00
eeef7c94cd fix emails
All checks were successful
continuous-integration/drone/push Build is passing
2024-07-28 13:35:34 -04:00
3c3391b3a6 update deps 2024-07-28 13:35:34 -04:00
52460024b9 update versions 2024-07-28 13:35:34 -04:00
48f7c8d18e fix empty invite index page
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-24 13:14:38 -05:00
571e0b65b6 fix faq page copy 2024-02-23 23:36:00 -05:00
7dc2047e97 fix missing ssl and crypto packages
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2024-02-23 22:44:36 -05:00
f769e710d8 sanitize tags while they are being typed
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-23 22:39:01 -05:00
d09f698b71 remove requirement for note and content to have content 2024-02-23 22:34:08 -05:00
8666f663ba Prevent possible additional submissions 2024-02-23 22:31:51 -05:00
22ccea893c sanitize titles while they are being typed 2024-02-23 22:31:15 -05:00
362c406471 fix credo warning for is_owner? 2024-02-23 22:18:25 -05:00
2a87037f06 fix credo warning for is_owner_or_admin? 2024-02-23 22:17:56 -05:00
53d0dcfb15 fix credo warning for is_admin? 2024-02-23 22:17:19 -05:00
c892b5449b fix credo warning for is_already_admin? 2024-02-23 22:16:08 -05:00
7cd9dca958 update elixir deps 2024-02-23 22:14:28 -05:00
0e8ddc22c5 update npm deps 2024-02-23 22:14:28 -05:00
3671ad6199 update tool versions 2024-02-23 22:14:20 -05:00
7189c955c3 bump version 2023-11-26 17:30:20 -05:00
f56ecc0ba3 fix content being displayed when blank 2023-11-26 17:30:14 -05:00
fdfca3f7a5 bump version
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-26 11:25:29 -05:00
c61b2c67b7 fix issue with displaying content 2023-11-26 11:25:26 -05:00
77 changed files with 8432 additions and 13545 deletions

View File

@ -17,7 +17,7 @@ steps:
- .mix - .mix
- name: test - name: test
image: elixir:1.15.6-alpine image: elixir:1.18.0-alpine
environment: environment:
TEST_DATABASE_URL: ecto://postgres:postgres@database/memex_test TEST_DATABASE_URL: ecto://postgres:postgres@database/memex_test
HOST: testing.example.tld HOST: testing.example.tld
@ -26,8 +26,8 @@ steps:
MIX_ENV: test MIX_ENV: test
commands: commands:
- apk add --no-cache build-base npm git - apk add --no-cache build-base npm git
- mix local.rebar --force --if-missing - mix local.rebar --force
- mix local.hex --force --if-missing - mix local.hex --force
- 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

View File

@ -1,3 +1,3 @@
elixir 1.15.6-otp-26 elixir 1.18.0-otp-27
erlang 26.1.2 erlang 27.2
nodejs 20.6.0 nodejs 23.5.0

View File

@ -1,4 +1,4 @@
FROM elixir:1.15.6-alpine AS build FROM elixir:1.18.0-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
@ -7,8 +7,8 @@ RUN apk add --no-cache build-base npm git python3
WORKDIR /app WORKDIR /app
# install hex + rebar # install hex + rebar
RUN mix local.hex --force && \ RUN mix local.rebar --force && \
mix local.rebar --force mix local.hex --force
# set build ENV # set build ENV
ENV MIX_ENV=prod ENV MIX_ENV=prod
@ -37,7 +37,7 @@ RUN mix do compile, release
FROM alpine:latest AS app FROM alpine:latest AS app
RUN apk upgrade --no-cache && \ RUN apk upgrade --no-cache && \
apk add --no-cache bash openssl libssl1.1 libcrypto1.1 libgcc libstdc++ ncurses-libs apk add --no-cache bash openssl libssl3 libcrypto3 libgcc libstdc++ ncurses-libs
WORKDIR /app WORKDIR /app

View File

@ -1,6 +1,7 @@
@import "tailwindcss/base"; @use "tailwindcss/base";
@import "tailwindcss/components"; @use "tailwindcss/components";
@import "tailwindcss/utilities"; @use "tailwindcss/utilities";
@use "components" as memex-components;
$fa-font-path: "@fortawesome/fontawesome-free/webfonts"; $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
@import "@fortawesome/fontawesome-free/scss/fontawesome"; @import "@fortawesome/fontawesome-free/scss/fontawesome";
@ -8,8 +9,6 @@ $fa-font-path: "@fortawesome/fontawesome-free/webfonts";
@import "@fortawesome/fontawesome-free/scss/solid"; @import "@fortawesome/fontawesome-free/scss/solid";
@import "@fortawesome/fontawesome-free/scss/brands"; @import "@fortawesome/fontawesome-free/scss/brands";
@import "components";
/* fix firefox scrollbars */ /* fix firefox scrollbars */
* { * {
scrollbar-width: auto; scrollbar-width: auto;

View File

@ -30,13 +30,15 @@ import topbar from 'topbar'
import CtrlEnter from './ctrlenter' import CtrlEnter from './ctrlenter'
import Date from './date' import Date from './date'
import DateTime from './datetime' import DateTime from './datetime'
import SanitizeTags from './sanitizetags'
import SanitizeTitles from './sanitizetitles'
const csrfTokenElement = document.querySelector("meta[name='csrf-token']") const csrfTokenElement = document.querySelector("meta[name='csrf-token']")
let csrfToken let csrfToken
if (csrfTokenElement) { csrfToken = csrfTokenElement.getAttribute('content') } if (csrfTokenElement) { csrfToken = csrfTokenElement.getAttribute('content') }
const liveSocket = new LiveSocket('/live', Socket, { const liveSocket = new LiveSocket('/live', Socket, {
params: { _csrf_token: csrfToken }, params: { _csrf_token: csrfToken },
hooks: { CtrlEnter, Date, DateTime } hooks: { CtrlEnter, Date, DateTime, SanitizeTags, SanitizeTitles }
}) })
// Show progress bar on live navigation and form submits // Show progress bar on live navigation and form submits

View File

@ -7,6 +7,5 @@ export default {
} }
}) })
}, },
mounted () { this.addFormSubmit(this) }, mounted () { this.addFormSubmit(this) }
updated () { this.addFormSubmit(this) }
} }

11
assets/js/sanitizetags.js Normal file
View File

@ -0,0 +1,11 @@
export default {
SanitizeTags (context) {
context.el.addEventListener('keyup', (e) => {
e.target.value = e.target.value
.replace(' ', ',')
.replace(',,', ',')
.replace(/[^a-zA-Z0-9,]/, '')
})
},
mounted () { this.SanitizeTags(this) }
}

View File

@ -0,0 +1,10 @@
export default {
SanitizeTitles (context) {
context.el.addEventListener('keyup', (e) => {
e.target.value = e.target.value
.replace(' ', '-')
.replace(/[^a-zA-Z0-9-]/, '')
})
},
mounted () { this.SanitizeTitles(this) }
}

20940
assets/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,7 @@
"description": " ", "description": " ",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "v20.6.0", "node": "v23.5.0"
"npm": "9.8.1"
}, },
"scripts": { "scripts": {
"deploy": "NODE_ENV=production webpack --mode production", "deploy": "NODE_ENV=production webpack --mode production",
@ -13,35 +12,35 @@
"test": "standard" "test": "standard"
}, },
"dependencies": { "dependencies": {
"@fontsource/nunito-sans": "^5.0.8", "@fontsource/nunito-sans": "^5.1.1",
"@fortawesome/fontawesome-free": "^6.4.2", "@fortawesome/fontawesome-free": "^6.7.2",
"phoenix": "file:../deps/phoenix", "phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html", "phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view", "phoenix_live_view": "file:../deps/phoenix_live_view",
"topbar": "^2.0.1" "topbar": "^3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.2", "@babel/core": "^7.26.0",
"@babel/preset-env": "^7.23.2", "@babel/preset-env": "^7.26.0",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.20",
"babel-loader": "^9.1.3", "babel-loader": "^9.2.1",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^12.0.2",
"css-loader": "^6.8.1", "css-loader": "^7.1.2",
"css-minimizer-webpack-plugin": "^5.0.1", "css-minimizer-webpack-plugin": "^7.0.0",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"mini-css-extract-plugin": "^2.7.6", "mini-css-extract-plugin": "^2.9.2",
"npm-check-updates": "^16.14.6", "npm-check-updates": "^17.1.13",
"postcss": "^8.4.31", "postcss": "^8.4.49",
"postcss-import": "^15.1.0", "postcss-import": "^16.1.0",
"postcss-loader": "^7.3.3", "postcss-loader": "^8.1.1",
"postcss-preset-env": "^9.3.0", "postcss-preset-env": "^10.1.3",
"sass": "^1.69.5", "sass": "^1.83.0",
"sass-loader": "^13.3.2", "sass-loader": "^16.0.4",
"standard": "^17.1.0", "standard": "^17.1.2",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.4.17",
"terser-webpack-plugin": "^5.3.9", "terser-webpack-plugin": "^5.3.11",
"webpack": "^5.89.0", "webpack": "^5.97.1",
"webpack-cli": "^5.1.4", "webpack-cli": "^6.0.1",
"webpack-dev-server": "^4.15.1" "webpack-dev-server": "^5.2.0"
} }
} }

View File

@ -1,3 +1,24 @@
# v0.1.17
- Fix new invite button not working
- Fix some descriptions possibly overflowing widths
- Update dependencies
# v0.1.16
- Fix empty invite index page
- Fix faq copy
- Fix issue with emails
- Update deps
# v0.1.15
- Sanitize titles while they are being typed
- Sanitize tags while they are being typed
- Remove requirement for note and content to have content
- Prevent possible additional submissions
- Fix content being displayed when blank
# v0.1.14
- Fix issue with item content not able to be displayed sometimes
# v0.1.13 # v0.1.13
- Update dependencies - Update dependencies
- Fix debounces - Fix debounces

View File

@ -9,8 +9,9 @@ config :bcrypt_elixir, :log_rounds, 1
# to provide built-in test partitioning in CI environment. # to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information. # Run `mix help test` for more information.
config :memex, Memex.Repo, config :memex, Memex.Repo,
pool_size: 10,
pool: Ecto.Adapters.SQL.Sandbox, pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 10 timeout: 60000
# We don't run a server during test. If one is required, # We don't run a server during test. If one is required,
# you can enable the server option below. # you can enable the server option below.
@ -32,4 +33,4 @@ config :logger, level: :warning
config :phoenix, :plug_init_mode, :runtime config :phoenix, :plug_init_mode, :runtime
# Disable Oban # Disable Oban
config :memex, Oban, queues: false, plugins: false config :memex, Oban, queues: false, plugins: false, testing: :manual

View File

@ -219,7 +219,7 @@ defmodule Memex.Accounts do
with {:ok, query} <- UserToken.verify_change_email_token_query(token, context), with {:ok, query} <- UserToken.verify_change_email_token_query(token, context),
%UserToken{sent_to: email} <- Repo.one(query), %UserToken{sent_to: email} <- Repo.one(query),
{:ok, _} <- Repo.transaction(user_email_multi(user, email, context)) do {:ok, _result} <- Repo.transaction(user_email_multi(user, email, context)) do
:ok :ok
else else
_error_tuple -> :error _error_tuple -> :error
@ -405,15 +405,15 @@ defmodule Memex.Accounts do
## Examples ## Examples
iex> is_admin?(%User{role: :admin}) iex> admin?(%User{role: :admin})
true true
iex> is_admin?(%User{}) iex> admin?(%User{})
false false
""" """
@spec is_admin?(User.t()) :: boolean() @spec admin?(User.t()) :: boolean()
def is_admin?(%User{id: user_id}) do def admin?(%User{id: user_id}) do
Repo.exists?(from u in User, where: u.id == ^user_id, where: u.role == :admin) Repo.exists?(from u in User, where: u.id == ^user_id, where: u.role == :admin)
end end
@ -422,16 +422,16 @@ defmodule Memex.Accounts do
## Examples ## Examples
iex> is_already_admin?(%User{role: :admin}) iex> already_admin?(%User{role: :admin})
true true
iex> is_already_admin?(%User{}) iex> already_admin?(%User{})
false false
""" """
@spec is_already_admin?(User.t() | nil) :: boolean() @spec already_admin?(User.t() | nil) :: boolean()
def is_already_admin?(%User{role: :admin}), do: true def already_admin?(%User{role: :admin}), do: true
def is_already_admin?(_invalid_user), do: false def already_admin?(_invalid_user), do: false
## Confirmation ## Confirmation

View File

@ -4,8 +4,8 @@ defmodule Memex.Accounts.User do
""" """
use Ecto.Schema use Ecto.Schema
use Gettext, backend: MemexWeb.Gettext
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext
alias Ecto.{Association, Changeset, UUID} alias Ecto.{Association, Changeset, UUID}
alias Memex.Accounts.{Invite, User} alias Memex.Accounts.{Invite, User}
@ -140,7 +140,7 @@ defmodule Memex.Accounts.User do
|> cast(attrs, [:email]) |> cast(attrs, [:email])
|> validate_email() |> validate_email()
|> case do |> case do
%{changes: %{email: _}} = changeset -> changeset %{changes: %{email: _email}} = changeset -> changeset
%{} = changeset -> add_error(changeset, :email, dgettext("errors", "did not change")) %{} = changeset -> add_error(changeset, :email, dgettext("errors", "did not change"))
end end
end end

View File

@ -155,7 +155,7 @@ defmodule Memex.Accounts.UserToken do
from t in __MODULE__, where: t.user_id == ^user.id from t in __MODULE__, where: t.user_id == ^user.id
end end
def user_and_contexts_query(user, [_ | _] = contexts) do def user_and_contexts_query(user, [_head | _rest] = contexts) do
from t in __MODULE__, where: t.user_id == ^user.id and t.context in ^contexts from t in __MODULE__, where: t.user_id == ^user.id and t.context in ^contexts
end end
end end

View File

@ -229,12 +229,12 @@ defmodule Memex.Contexts do
context |> Context.update_changeset(attrs, user) context |> Context.update_changeset(attrs, user)
end end
@spec is_owner_or_admin?(Context.t(), User.t()) :: boolean() @spec owner_or_admin?(Context.t(), User.t()) :: boolean()
def is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true def owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner_or_admin?(_context, %{role: :admin}), do: true def owner_or_admin?(_context, %{role: :admin}), do: true
def is_owner_or_admin?(_context, _other_user), do: false def owner_or_admin?(_context, _other_user), do: false
@spec is_owner?(Context.t(), User.t()) :: boolean() @spec owner?(Context.t(), User.t()) :: boolean()
def is_owner?(%{user_id: user_id}, %{id: user_id}), do: true def owner?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner?(_context, _other_user), do: false def owner?(_context, _other_user), do: false
end end

View File

@ -4,8 +4,8 @@ defmodule Memex.Contexts.Context do
into a single consideration into a single consideration
""" """
use Ecto.Schema use Ecto.Schema
use Gettext, backend: MemexWeb.Gettext
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Repo} alias Memex.{Accounts.User, Repo}
@ -57,7 +57,7 @@ defmodule Memex.Contexts.Context do
|> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/, |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :user_id, :visibility]) |> validate_required([:slug, :user_id, :visibility])
|> unique_constraint(:slug) |> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo) |> unsafe_validate_unique(:slug, Repo)
end end
@ -70,7 +70,7 @@ defmodule Memex.Contexts.Context do
|> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/, |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :visibility]) |> validate_required([:slug, :visibility])
|> unique_constraint(:slug) |> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo) |> unsafe_validate_unique(:slug, Repo)
end end

View File

@ -7,8 +7,8 @@ defmodule Memex.Email do
`lib/memex_web/components/layouts/email_text.txt.eex` for text emails. `lib/memex_web/components/layouts/email_text.txt.eex` for text emails.
""" """
use Gettext, backend: MemexWeb.Gettext
import Swoosh.Email import Swoosh.Email
import MemexWeb.Gettext
import Phoenix.Template import Phoenix.Template
alias Memex.Accounts.User alias Memex.Accounts.User
alias MemexWeb.{EmailHTML, Layouts} alias MemexWeb.{EmailHTML, Layouts}

View File

@ -229,12 +229,12 @@ defmodule Memex.Notes do
note |> Note.update_changeset(attrs, user) note |> Note.update_changeset(attrs, user)
end end
@spec is_owner_or_admin?(Note.t(), User.t()) :: boolean() @spec owner_or_admin?(Note.t(), User.t()) :: boolean()
def is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true def owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner_or_admin?(_context, %{role: :admin}), do: true def owner_or_admin?(_context, %{role: :admin}), do: true
def is_owner_or_admin?(_context, _other_user), do: false def owner_or_admin?(_context, _other_user), do: false
@spec is_owner?(Note.t(), User.t()) :: boolean() @spec owner?(Note.t(), User.t()) :: boolean()
def is_owner?(%{user_id: user_id}, %{id: user_id}), do: true def owner?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner?(_context, _other_user), do: false def owner?(_context, _other_user), do: false
end end

View File

@ -3,8 +3,8 @@ defmodule Memex.Notes.Note do
Schema for a user-written note Schema for a user-written note
""" """
use Ecto.Schema use Ecto.Schema
use Gettext, backend: MemexWeb.Gettext
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Repo} alias Memex.{Accounts.User, Repo}
@ -56,7 +56,7 @@ defmodule Memex.Notes.Note do
|> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/, |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :user_id, :visibility]) |> validate_required([:slug, :user_id, :visibility])
|> unique_constraint(:slug) |> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo) |> unsafe_validate_unique(:slug, Repo)
end end
@ -69,7 +69,7 @@ defmodule Memex.Notes.Note do
|> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/, |> validate_format(:slug, ~r/^[\p{L}\p{N}\-]+$/,
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :visibility]) |> validate_required([:slug, :visibility])
|> unique_constraint(:slug) |> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo) |> unsafe_validate_unique(:slug, Repo)
end end

View File

@ -231,12 +231,12 @@ defmodule Memex.Pipelines do
pipeline |> Pipeline.update_changeset(attrs, user) pipeline |> Pipeline.update_changeset(attrs, user)
end end
@spec is_owner_or_admin?(Pipeline.t(), User.t()) :: boolean() @spec owner_or_admin?(Pipeline.t(), User.t()) :: boolean()
def is_owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true def owner_or_admin?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner_or_admin?(_context, %{role: :admin}), do: true def owner_or_admin?(_context, %{role: :admin}), do: true
def is_owner_or_admin?(_context, _other_user), do: false def owner_or_admin?(_context, _other_user), do: false
@spec is_owner?(Pipeline.t(), User.t()) :: boolean() @spec owner?(Pipeline.t(), User.t()) :: boolean()
def is_owner?(%{user_id: user_id}, %{id: user_id}), do: true def owner?(%{user_id: user_id}, %{id: user_id}), do: true
def is_owner?(_context, _other_user), do: false def owner?(_context, _other_user), do: false
end end

View File

@ -3,8 +3,8 @@ defmodule Memex.Pipelines.Pipeline do
Represents a chain of considerations to take to accomplish a task Represents a chain of considerations to take to accomplish a task
""" """
use Ecto.Schema use Ecto.Schema
use Gettext, backend: MemexWeb.Gettext
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Pipelines.Steps.Step, Repo} alias Memex.{Accounts.User, Pipelines.Steps.Step, Repo}

View File

@ -42,9 +42,9 @@ defmodule MemexWeb do
formats: [:html, :json], formats: [:html, :json],
layouts: [html: MemexWeb.Layouts] layouts: [html: MemexWeb.Layouts]
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse use Gettext, backend: MemexWeb.Gettext
import Plug.Conn import Plug.Conn
import MemexWeb.Gettext
unquote(verified_routes()) unquote(verified_routes())
end end
@ -69,6 +69,7 @@ defmodule MemexWeb do
def html do def html do
quote do quote do
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
use Phoenix.Component use Phoenix.Component
# Import convenience functions from controllers # Import convenience functions from controllers
@ -82,12 +83,10 @@ defmodule MemexWeb do
defp html_helpers do defp html_helpers do
quote do quote do
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse use PhoenixHTMLHelpers
use Phoenix.HTML use Gettext, backend: MemexWeb.Gettext
import Phoenix.{Component, HTML, HTML.Form}
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse import MemexWeb.{ErrorHelpers, CoreComponents, HTMLHelpers}
import Phoenix.Component
import MemexWeb.{ErrorHelpers, Gettext, CoreComponents, HTMLHelpers}
# Shortcut for generating JS commands # Shortcut for generating JS commands
alias Phoenix.LiveView.JS alias Phoenix.LiveView.JS

View File

@ -2,9 +2,11 @@ defmodule MemexWeb.CoreComponents do
@moduledoc """ @moduledoc """
Provides core UI components. Provides core UI components.
""" """
use PhoenixHTMLHelpers
use Phoenix.Component use Phoenix.Component
use MemexWeb, :verified_routes use MemexWeb, :verified_routes
import MemexWeb.{Gettext, HTMLHelpers} use Gettext, backend: MemexWeb.Gettext
import MemexWeb.HTMLHelpers
alias Memex.{Accounts, Accounts.Invite, Accounts.User} alias Memex.{Accounts, Accounts.Invite, Accounts.User}
alias Memex.Contexts.Context alias Memex.Contexts.Context
alias Memex.Notes.Note alias Memex.Notes.Note
@ -134,65 +136,72 @@ defmodule MemexWeb.CoreComponents do
def pipeline_content(assigns) def pipeline_content(assigns)
defp display_backlinks(record) do defp display_links(record) do
record record
|> get_text() |> get_content()
|> replace_links(record) |> replace_hyperlinks(record)
|> replace_triple_backlinks(record) |> replace_triple_links(record)
|> replace_double_backlinks(record) |> replace_double_links(record)
|> replace_single_backlinks(record) |> replace_single_links(record)
|> HTML.raw() |> HTML.raw()
end end
defp get_text(%{content: content}), do: content defp get_content(%{content: content}), do: content |> get_text()
defp get_text(%{description: description}), do: description defp get_content(%{description: description}), do: description |> get_text()
defp get_content(_fallthrough), do: nil |> get_text()
defp get_text(string) when is_binary(string), do: string
defp get_text(_fallthrough), do: "" defp get_text(_fallthrough), do: ""
# replaces hyperlinks like https://bubbletea.dev
#
# link regex from # link regex from
# https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url # https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
# and modified with additional schemes from # and modified with additional schemes from
# https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml # https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
defp replace_links(content, _record) do defp replace_hyperlinks(content, _record) do
Regex.replace( Regex.replace(
~r<((file|git|https?|ipfs|ipns|irc|jabber|magnet|mailto|mumble|tel|udp|xmpp):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))>, ~r<((file|git|https?|ipfs|ipns|irc|jabber|magnet|mailto|mumble|tel|udp|xmpp):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))>,
content, content,
fn _whole_match, link -> fn _whole_match, link ->
link = link =
HTML.Link.link( link(
link, link,
to: link, to: link,
class: "link inline", class: "link inline break-words",
target: "_blank", target: "_blank",
rel: "noopener noreferrer" rel: "noopener noreferrer"
) )
|> HTML.Safe.to_iodata() |> HTML.Safe.to_iodata()
|> IO.iodata_to_binary() |> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">" "</p>#{link}<p class=\"inline break-words\">"
end end
) )
end end
defp replace_triple_backlinks(content, _record) do # replaces triple links like [[[slug-title]]]
defp replace_triple_links(content, _record) do
Regex.replace( Regex.replace(
~r/(^|[^\[])\[\[\[([\p{L}\p{N}\-]+)\]\]\]($|[^\]])/, ~r/(^|[^\[])\[\[\[([\p{L}\p{N}\-]+)\]\]\]($|[^\]])/,
content, content,
fn _whole_match, prefix, slug, suffix -> fn _whole_match, prefix, slug, suffix ->
link = link =
HTML.Link.link( link(
"[[[#{slug}]]]", "[[[#{slug}]]]",
to: ~p"/note/#{slug}", to: ~p"/note/#{slug}",
class: "link inline" class: "link inline break-words"
) )
|> HTML.Safe.to_iodata() |> HTML.Safe.to_iodata()
|> IO.iodata_to_binary() |> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}" "#{prefix}</p>#{link}<p class=\"inline break-words\">#{suffix}"
end end
) )
end end
defp replace_double_backlinks(content, record) do # replaces double links like [[slug-title]]
defp replace_double_links(content, record) do
Regex.replace( Regex.replace(
~r/(^|[^\[])\[\[([\p{L}\p{N}\-]+)\]\]($|[^\]])/, ~r/(^|[^\[])\[\[([\p{L}\p{N}\-]+)\]\]($|[^\]])/,
content, content,
@ -205,20 +214,21 @@ defmodule MemexWeb.CoreComponents do
end end
link = link =
HTML.Link.link( link(
"[[#{slug}]]", "[[#{slug}]]",
to: target, to: target,
class: "link inline" class: "link inline break-words"
) )
|> HTML.Safe.to_iodata() |> HTML.Safe.to_iodata()
|> IO.iodata_to_binary() |> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}" "#{prefix}</p>#{link}<p class=\"inline break-words\">#{suffix}"
end end
) )
end end
defp replace_single_backlinks(content, record) do # replaces single links like [slug-title]
defp replace_single_links(content, record) do
Regex.replace( Regex.replace(
~r/(^|[^\[])\[([\p{L}\p{N}\-]+)\]($|[^\]])/, ~r/(^|[^\[])\[([\p{L}\p{N}\-]+)\]($|[^\]])/,
content, content,
@ -232,15 +242,15 @@ defmodule MemexWeb.CoreComponents do
end end
link = link =
HTML.Link.link( link(
"[#{slug}]", "[#{slug}]",
to: target, to: target,
class: "link inline" class: "link inline break-words"
) )
|> HTML.Safe.to_iodata() |> HTML.Safe.to_iodata()
|> IO.iodata_to_binary() |> IO.iodata_to_binary()
"#{prefix}</p>#{link}<p class=\"inline\">#{suffix}" "#{prefix}</p>#{link}<p class=\"inline break-words\">#{suffix}"
end end
) )
end end

View File

@ -1,7 +1,8 @@
<div <div
:if={@context.content}
id={"show-context-content-#{@context.id}"} id={"show-context-content-#{@context.id}"}
class="input input-primary h-128 min-h-128 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y" class="input input-primary h-128 min-h-128 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y"
phx-update="ignore" phx-update="ignore"
readonly readonly
phx-no-format phx-no-format
><p class="inline"><%= display_backlinks(@context) %></p></div> ><p class="inline"><%= display_links(@context) %></p></div>

View File

@ -1,7 +1,8 @@
<div <div
:if={@note.content}
id={"show-note-content-#{@note.id}"} id={"show-note-content-#{@note.id}"}
class="input input-primary h-128 min-h-128 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y" class="input input-primary h-128 min-h-128 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y"
phx-update="ignore" phx-update="ignore"
readonly readonly
phx-no-format phx-no-format
><p class="inline"><%= display_backlinks(@note) %></p></div> ><p class="inline"><%= display_links(@note) %></p></div>

View File

@ -1,7 +1,8 @@
<div <div
:if={@pipeline.description}
id={"show-pipeline-description-#{@pipeline.id}"} id={"show-pipeline-description-#{@pipeline.id}"}
class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y" class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y"
phx-update="ignore" phx-update="ignore"
readonly readonly
phx-no-format phx-no-format
><p class="inline"><%= display_backlinks(@pipeline) %></p></div> ><p class="inline"><%= display_links(@pipeline) %></p></div>

View File

@ -1,7 +1,8 @@
<div <div
:if={@step.content}
id={"show-step-content-#{@step.id}"} id={"show-step-content-#{@step.id}"}
class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y" class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto resize-y"
phx-update="ignore" phx-update="ignore"
readonly readonly
phx-no-format phx-no-format
><p class="inline"><%= display_backlinks(@step) %></p></div> ><p class="inline"><%= display_links(@step) %></p></div>

View File

@ -38,7 +38,7 @@
<li class="mx-2 my-1 border-left border border-primary-700"></li> <li class="mx-2 my-1 border-left border border-primary-700"></li>
<%= if @current_user do %> <%= if @current_user do %>
<li :if={@current_user |> Accounts.is_already_admin?()} class="mx-2 my-1"> <li :if={@current_user |> Accounts.already_admin?()} class="mx-2 my-1">
<.link navigate={~p"/invites"} class="text-primary-400 hover:underline"> <.link navigate={~p"/invites"} class="text-primary-400 hover:underline">
<%= gettext("invites") %> <%= gettext("invites") %>
</.link> </.link>

View File

@ -10,7 +10,7 @@
phx-click="lv:clear-flash" phx-click="lv:clear-flash"
phx-value-key="info" phx-value-key="info"
> >
<%= live_flash(@flash, :info) %> <%= Phoenix.Flash.get(@flash, :info) %>
</p> </p>
<p <p
@ -20,7 +20,7 @@
phx-click="lv:clear-flash" phx-click="lv:clear-flash"
phx-value-key="error" phx-value-key="error"
> >
<%= live_flash(@flash, :error) %> <%= Phoenix.Flash.get(@flash, :error) %>
</p> </p>
</div> </div>
</header> </header>

View File

@ -1,5 +1,5 @@
defmodule MemexWeb.ErrorJSON do defmodule MemexWeb.ErrorJSON do
import MemexWeb.Gettext use Gettext, backend: MemexWeb.Gettext
def render(template, _assigns) do def render(template, _assigns) do
error_string = error_string =

View File

@ -4,9 +4,9 @@ defmodule MemexWeb.UserAuth do
""" """
use MemexWeb, :verified_routes use MemexWeb, :verified_routes
use Gettext, backend: MemexWeb.Gettext
import Plug.Conn import Plug.Conn
import Phoenix.Controller import Phoenix.Controller
import MemexWeb.Gettext
alias Memex.{Accounts, Accounts.User} alias Memex.{Accounts, Accounts.User}
# Make the remember me cookie valid for 60 days. # Make the remember me cookie valid for 60 days.

View File

@ -1,7 +1,6 @@
defmodule MemexWeb.UserConfirmationController do defmodule MemexWeb.UserConfirmationController do
use MemexWeb, :controller use MemexWeb, :controller
use Gettext, backend: MemexWeb.Gettext
import MemexWeb.Gettext
alias Memex.Accounts alias Memex.Accounts
def new(conn, _params) do def new(conn, _params) do

View File

@ -1,6 +1,6 @@
defmodule MemexWeb.UserRegistrationController do defmodule MemexWeb.UserRegistrationController do
use MemexWeb, :controller use MemexWeb, :controller
import MemexWeb.Gettext use Gettext, backend: MemexWeb.Gettext
alias Ecto.Changeset alias Ecto.Changeset
alias Memex.{Accounts, Accounts.Invites} alias Memex.{Accounts, Accounts.Invites}

View File

@ -9,7 +9,7 @@
action={~p"/users/register"} action={~p"/users/register"}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center" class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
> >
<p :if={@changeset.action && not @changeset.valid?()} class="alert alert-danger col-span-3"> <p :if={@changeset.action && not @changeset.valid?} class="alert alert-danger col-span-3">
<%= dgettext("errors", "oops, something went wrong! please check the errors below.") %> <%= dgettext("errors", "oops, something went wrong! please check the errors below.") %>
</p> </p>

View File

@ -40,7 +40,7 @@ defmodule MemexWeb.UserResetPasswordController do
# leaked token giving the user access to the account. # leaked token giving the user access to the account.
def update(conn, %{"user" => user_params}) do def update(conn, %{"user" => user_params}) do
case Accounts.reset_user_password(conn.assigns.user, user_params) do case Accounts.reset_user_password(conn.assigns.user, user_params) do
{:ok, _} -> {:ok, _user} ->
conn conn
|> put_flash(:info, dgettext("prompts", "password reset successfully.")) |> put_flash(:info, dgettext("prompts", "password reset successfully."))
|> redirect(to: ~p"/users/log_in") |> redirect(to: ~p"/users/log_in")

View File

@ -9,7 +9,7 @@
action={~p"/users/reset_password/#{@token}"} action={~p"/users/reset_password/#{@token}"}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center" class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
> >
<p :if={@changeset.action && not @changeset.valid?()} class="alert alert-danger col-span-3"> <p :if={@changeset.action && not @changeset.valid?} class="alert alert-danger col-span-3">
<%= dgettext("errors", "oops, something went wrong! please check the errors below.") %> <%= dgettext("errors", "oops, something went wrong! please check the errors below.") %>
</p> </p>

View File

@ -1,6 +1,6 @@
defmodule MemexWeb.UserSettingsController do defmodule MemexWeb.UserSettingsController do
use MemexWeb, :controller use MemexWeb, :controller
import MemexWeb.Gettext use Gettext, backend: MemexWeb.Gettext
alias Memex.Accounts alias Memex.Accounts
alias MemexWeb.UserAuth alias MemexWeb.UserAuth

View File

@ -16,7 +16,7 @@
</h3> </h3>
<div <div
:if={@email_changeset.action && not @email_changeset.valid?()} :if={@email_changeset.action && not @email_changeset.valid?}
class="alert alert-danger col-span-3" class="alert alert-danger col-span-3"
> >
<%= dgettext("errors", "oops, something went wrong! please check the errors below") %> <%= dgettext("errors", "oops, something went wrong! please check the errors below") %>
@ -58,7 +58,7 @@
</h3> </h3>
<p <p
:if={@password_changeset.action && not @password_changeset.valid?()} :if={@password_changeset.action && not @password_changeset.valid?}
class="alert alert-danger col-span-3" class="alert alert-danger col-span-3"
> >
<%= dgettext("errors", "oops, something went wrong! please check the errors below.") %> <%= dgettext("errors", "oops, something went wrong! please check the errors below.") %>
@ -112,7 +112,7 @@
) %> ) %>
<div <div
:if={@locale_changeset.action && not @locale_changeset.valid?()} :if={@locale_changeset.action && not @locale_changeset.valid?}
class="alert alert-danger col-span-3" class="alert alert-danger col-span-3"
> >
<%= dgettext("errors", "oops, something went wrong! please check the errors below") %> <%= dgettext("errors", "oops, something went wrong! please check the errors below") %>

View File

@ -3,8 +3,8 @@ defmodule MemexWeb.ErrorHelpers do
Conveniences for translating and building error messages. Conveniences for translating and building error messages.
""" """
use Phoenix.HTML use PhoenixHTMLHelpers
import Phoenix.Component import Phoenix.{Component, HTML.Form}
alias Ecto.Changeset alias Ecto.Changeset
alias Phoenix.{HTML.Form, LiveView.Rendered} alias Phoenix.{HTML.Form, LiveView.Rendered}

View File

@ -5,7 +5,7 @@ defmodule MemexWeb.Gettext do
By using [Gettext](https://hexdocs.pm/gettext), By using [Gettext](https://hexdocs.pm/gettext),
your module gains a set of macros for translations, for example: your module gains a set of macros for translations, for example:
import MemexWeb.Gettext use Gettext, backend: MemexWeb.Gettext
# Simple translation # Simple translation
gettext("Here is the string to translate") gettext("Here is the string to translate")
@ -20,5 +20,5 @@ defmodule MemexWeb.Gettext do
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
""" """
use Gettext, otp_app: :memex use Gettext.Backend, otp_app: :memex
end end

View File

@ -10,10 +10,11 @@
class="flex flex-col justify-start items-stretch space-y-4" class="flex flex-col justify-start items-stretch space-y-4"
> >
<%= text_input(f, :slug, <%= text_input(f, :slug,
class: "input input-primary",
placeholder: gettext("slug"),
aria_label: gettext("slug"), aria_label: gettext("slug"),
phx_debounce: 300 class: "input input-primary",
phx_debounce: 300,
phx_hook: "SanitizeTitles",
placeholder: gettext("slug")
) %> ) %>
<%= error_tag(f, :slug) %> <%= error_tag(f, :slug) %>
@ -30,11 +31,12 @@
<%= error_tag(f, :content) %> <%= error_tag(f, :content) %>
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input",
class: "input input-primary",
placeholder: gettext("tag1,tag2"),
aria_label: gettext("tag1,tag2"), aria_label: gettext("tag1,tag2"),
phx_debounce: 300 class: "input input-primary",
id: "tags-input",
phx_debounce: 300,
phx_hook: "SanitizeTags",
placeholder: gettext("tag1,tag2")
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

@ -33,14 +33,14 @@
> >
<:actions :let={context}> <:actions :let={context}>
<.link <.link
:if={Contexts.is_owner?(context, @current_user)} :if={Contexts.owner?(context, @current_user)}
patch={~p"/contexts/#{context}/edit"} patch={~p"/contexts/#{context}/edit"}
aria-label={dgettext("actions", "edit %{context_slug}", context_slug: context.slug)} aria-label={dgettext("actions", "edit %{context_slug}", context_slug: context.slug)}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<.link <.link
:if={Contexts.is_owner_or_admin?(context, @current_user)} :if={Contexts.owner_or_admin?(context, @current_user)}
href="#" href="#"
phx-click="delete" phx-click="delete"
phx-value-id={context.id} phx-value-id={context.id}

View File

@ -17,14 +17,14 @@
<div class="self-end flex space-x-4"> <div class="self-end flex space-x-4">
<.link <.link
:if={Contexts.is_owner?(@context, @current_user)} :if={Contexts.owner?(@context, @current_user)}
class="btn btn-primary" class="btn btn-primary"
patch={~p"/context/#{@context}/edit"} patch={~p"/context/#{@context}/edit"}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<button <button
:if={Contexts.is_owner_or_admin?(@context, @current_user)} :if={Contexts.owner_or_admin?(@context, @current_user)}
type="button" type="button"
class="btn btn-primary" class="btn btn-primary"
phx-click="delete" phx-click="delete"

View File

@ -89,7 +89,7 @@
<p> <p>
<%= gettext("in my opinion, contexts should be like single-topic blog posts.") %> <%= gettext("in my opinion, contexts should be like single-topic blog posts.") %>
<%= gettext( <%= gettext(
"for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could backlink to the spoon note as an example of how it fits nicely into your hand." "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could link to the spoon note as an example of how it fits nicely into your hand."
) %> ) %>
</p> </p>
</li> </li>
@ -100,10 +100,10 @@
</b> </b>
<p> <p>
<%= gettext( <%= gettext(
"in my opinion, pipelines should be pretty lightweight, and just backlink to contexts to provide most of the heavy lifting." "in my opinion, pipelines should be pretty lightweight, and just link to contexts to provide most of the heavy lifting."
) %> ) %>
<%= gettext( <%= gettext(
"for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could backlink to the physical designs context, maybe with some notes about how it applies in this case." "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could link to the physical designs context, maybe with some notes about how it applies in this case."
) %> ) %>
</p> </p>
</li> </li>
@ -117,7 +117,7 @@
"while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document." "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
) %> ) %>
<%= gettext( <%= gettext(
"note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you." "note, context and pipeline slugs must be unique, and you are free to link to notes not written by you."
) %> ) %>
<%= gettext( <%= gettext(
"so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)" "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"

View File

@ -13,7 +13,7 @@
phx-hook="CtrlEnter" phx-hook="CtrlEnter"
> >
<div <div
:if={@changeset.action && not @changeset.valid?()} :if={@changeset.action && not @changeset.valid?}
class="invalid-feedback col-span-3 text-center" class="invalid-feedback col-span-3 text-center"
> >
<%= changeset_errors(@changeset) %> <%= changeset_errors(@changeset) %>

View File

@ -1,15 +1,15 @@
<div class="mx-auto flex flex-col justify-center items-stretch space-y-4 max-w-3xl"> <div class="flex flex-col justify-center items-stretch mx-auto space-y-4 max-w-3xl">
<h1 class="title text-xl title-primary-500"> <h1 class="text-xl title title-primary-500">
<%= gettext("invites") %> <%= gettext("invites") %>
</h1> </h1>
<%= if @invites |> Enum.empty?() do %> <%= if @invites |> Enum.empty?() do %>
<h1 class="title text-xl text-primary-400"> <h1 class="text-xl text-center title text-primary-400">
<%= gettext("no invites 😔") %> <%= gettext("no invites 😔") %>
</h1> </h1>
<.link patch={~p"/invites"} class="btn btn-primary"> <.link patch={~p"/invites/new"} class="ml-auto btn btn-primary">
<%= dgettext("actions", "invite someone new!") %> <%= dgettext("actions", "new invite") %>
</.link> </.link>
<% end %> <% end %>
@ -86,7 +86,7 @@
</.link> </.link>
</.invite_card> </.invite_card>
<.link :if={@invites != []} patch={~p"/invites/new"} class="btn btn-primary ml-auto"> <.link :if={@invites != []} patch={~p"/invites/new"} class="ml-auto btn btn-primary">
<%= dgettext("actions", "create invite") %> <%= dgettext("actions", "create invite") %>
</.link> </.link>
</div> </div>
@ -94,7 +94,7 @@
<%= unless @admins |> Enum.empty?() do %> <%= unless @admins |> Enum.empty?() do %>
<hr class="hr" /> <hr class="hr" />
<h1 class="title text-xl text-primary-400"> <h1 class="text-xl title text-primary-400">
<%= gettext("admins") %> <%= gettext("admins") %>
</h1> </h1>
@ -122,7 +122,7 @@
<%= unless @users |> Enum.empty?() do %> <%= unless @users |> Enum.empty?() do %>
<hr class="hr" /> <hr class="hr" />
<h1 class="title text-xl text-primary-400"> <h1 class="text-xl title text-primary-400">
<%= gettext("users") %> <%= gettext("users") %>
</h1> </h1>

View File

@ -10,10 +10,11 @@
class="flex flex-col justify-start items-stretch space-y-4" class="flex flex-col justify-start items-stretch space-y-4"
> >
<%= text_input(f, :slug, <%= text_input(f, :slug,
class: "input input-primary",
placeholder: gettext("slug"),
aria_label: gettext("slug"), aria_label: gettext("slug"),
phx_debounce: 300 class: "input input-primary",
phx_debounce: 300,
phx_hook: "SanitizeTitles",
placeholder: gettext("slug")
) %> ) %>
<%= error_tag(f, :slug) %> <%= error_tag(f, :slug) %>
@ -28,11 +29,12 @@
<%= error_tag(f, :content) %> <%= error_tag(f, :content) %>
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input",
class: "input input-primary",
placeholder: gettext("tag1,tag2"),
aria_label: gettext("tag1,tag2"), aria_label: gettext("tag1,tag2"),
phx_debounce: 300 class: "input input-primary",
id: "tags-input",
phx_debounce: 300,
phx_hook: "SanitizeTags",
placeholder: gettext("tag1,tag2")
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

@ -33,14 +33,14 @@
> >
<:actions :let={note}> <:actions :let={note}>
<.link <.link
:if={Notes.is_owner?(note, @current_user)} :if={Notes.owner?(note, @current_user)}
patch={~p"/notes/#{note}/edit"} patch={~p"/notes/#{note}/edit"}
aria-label={dgettext("actions", "edit %{note_slug}", note_slug: note.slug)} aria-label={dgettext("actions", "edit %{note_slug}", note_slug: note.slug)}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<.link <.link
:if={Notes.is_owner_or_admin?(note, @current_user)} :if={Notes.owner_or_admin?(note, @current_user)}
href="#" href="#"
phx-click="delete" phx-click="delete"
phx-value-id={note.id} phx-value-id={note.id}

View File

@ -17,14 +17,14 @@
<div class="self-end flex space-x-4"> <div class="self-end flex space-x-4">
<.link <.link
:if={Notes.is_owner?(@note, @current_user)} :if={Notes.owner?(@note, @current_user)}
class="btn btn-primary" class="btn btn-primary"
patch={~p"/note/#{@note}/edit"} patch={~p"/note/#{@note}/edit"}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<button <button
:if={Notes.is_owner_or_admin?(@note, @current_user)} :if={Notes.owner_or_admin?(@note, @current_user)}
type="button" type="button"
class="btn btn-primary" class="btn btn-primary"
phx-click="delete" phx-click="delete"

View File

@ -10,10 +10,11 @@
class="flex flex-col justify-start items-stretch space-y-4" class="flex flex-col justify-start items-stretch space-y-4"
> >
<%= text_input(f, :slug, <%= text_input(f, :slug,
class: "input input-primary",
placeholder: gettext("slug"),
aria_label: gettext("slug"), aria_label: gettext("slug"),
phx_debounce: 300 class: "input input-primary",
phx_debounce: 300,
phx_hook: "SanitizeTitles",
placeholder: gettext("slug")
) %> ) %>
<%= error_tag(f, :slug) %> <%= error_tag(f, :slug) %>
@ -34,11 +35,12 @@
<%= error_tag(f, :description) %> <%= error_tag(f, :description) %>
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input",
class: "input input-primary",
placeholder: gettext("tag1,tag2"),
aria_label: gettext("tag1,tag2"), aria_label: gettext("tag1,tag2"),
phx_debounce: 300 class: "input input-primary",
id: "tags-input",
phx_debounce: 300,
phx_hook: "SanitizeTags",
placeholder: gettext("tag1,tag2")
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

@ -33,14 +33,14 @@
> >
<:actions :let={pipeline}> <:actions :let={pipeline}>
<.link <.link
:if={Pipelines.is_owner?(pipeline, @current_user)} :if={Pipelines.owner?(pipeline, @current_user)}
patch={~p"/pipelines/#{pipeline}/edit"} patch={~p"/pipelines/#{pipeline}/edit"}
aria-label={dgettext("actions", "edit %{pipeline_slug}", pipeline_slug: pipeline.slug)} aria-label={dgettext("actions", "edit %{pipeline_slug}", pipeline_slug: pipeline.slug)}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<.link <.link
:if={Pipelines.is_owner_or_admin?(pipeline, @current_user)} :if={Pipelines.owner_or_admin?(pipeline, @current_user)}
href="#" href="#"
phx-click="delete" phx-click="delete"
phx-value-id={pipeline.id} phx-value-id={pipeline.id}

View File

@ -17,14 +17,14 @@
<div class="pb-4 self-end flex space-x-4"> <div class="pb-4 self-end flex space-x-4">
<.link <.link
:if={Pipelines.is_owner?(@pipeline, @current_user)} :if={Pipelines.owner?(@pipeline, @current_user)}
class="btn btn-primary" class="btn btn-primary"
patch={~p"/pipeline/#{@pipeline}/edit"} patch={~p"/pipeline/#{@pipeline}/edit"}
> >
<%= dgettext("actions", "edit") %> <%= dgettext("actions", "edit") %>
</.link> </.link>
<button <button
:if={Pipelines.is_owner_or_admin?(@pipeline, @current_user)} :if={Pipelines.owner_or_admin?(@pipeline, @current_user)}
type="button" type="button"
class="btn btn-primary" class="btn btn-primary"
phx-click="delete" phx-click="delete"
@ -52,7 +52,7 @@
<%= gettext("%{position}. %{title}", position: position + 1, title: title) %> <%= gettext("%{position}. %{title}", position: position + 1, title: title) %>
</h3> </h3>
<%= if Pipelines.is_owner?(@pipeline, @current_user) do %> <%= if Pipelines.owner?(@pipeline, @current_user) do %>
<div class="flex justify-between items-center space-x-4"> <div class="flex justify-between items-center space-x-4">
<%= if position <= 0 do %> <%= if position <= 0 do %>
<i class="fas text-xl fa-chevron-up cursor-not-allowed opacity-25"></i> <i class="fas text-xl fa-chevron-up cursor-not-allowed opacity-25"></i>
@ -113,7 +113,7 @@
<% end %> <% end %>
<.link <.link
:if={Pipelines.is_owner?(@pipeline, @current_user)} :if={Pipelines.owner?(@pipeline, @current_user)}
class="self-end btn btn-primary" class="self-end btn btn-primary"
patch={~p"/pipeline/#{@pipeline}/add_step"} patch={~p"/pipeline/#{@pipeline}/add_step"}
> >

View File

@ -10,10 +10,11 @@
class="flex flex-col justify-start items-stretch space-y-4" class="flex flex-col justify-start items-stretch space-y-4"
> >
<%= text_input(f, :title, <%= text_input(f, :title,
class: "input input-primary",
placeholder: gettext("title"),
aria_label: gettext("title"), aria_label: gettext("title"),
phx_debounce: 300 class: "input input-primary",
phx_debounce: 300,
phx_hook: "SanitizeTitles",
placeholder: gettext("title")
) %> ) %>
<%= error_tag(f, :title) %> <%= error_tag(f, :title) %>

39
mix.exs
View File

@ -4,8 +4,8 @@ defmodule Memex.MixProject do
def project do def project do
[ [
app: :memex, app: :memex,
version: "0.1.13", version: "0.1.17",
elixir: "1.15.6", elixir: "1.18.0",
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(),
@ -47,29 +47,30 @@ defmodule Memex.MixProject do
defp deps do defp deps do
[ [
{:bcrypt_elixir, "~> 3.0"}, {:bcrypt_elixir, "~> 3.0"},
{:phoenix, "~> 1.7.0"}, {:credo, "~> 1.5", only: [:dev, :test], runtime: false},
{:phoenix_ecto, "~> 4.4"}, {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false},
{:phoenix_html, "~> 3.0"}, {:ecto_psql_extras, "~> 0.6"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 0.20.0"},
{:phoenix_live_dashboard, "~> 0.8"},
{:ecto_sql, "~> 3.6"}, {:ecto_sql, "~> 3.6"},
{:postgrex, ">= 0.0.0"}, {:eqrcode, "~> 0.1.10"},
{:floki, ">= 0.30.0", only: :test},
# {:esbuild, "~> 0.3", runtime: Mix.env() == :dev}, # {:esbuild, "~> 0.3", runtime: Mix.env() == :dev},
{:ex_doc, "~> 0.27", only: :dev, runtime: false}, {:ex_doc, "~> 0.27", only: :dev, runtime: false},
{:swoosh, "~> 1.6"}, {:floki, ">= 0.30.0", only: :test},
{:gen_smtp, "~> 1.0"}, {:gen_smtp, "~> 1.0"},
{:oban, "~> 2.10"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 1.0"},
{:gettext, "~> 0.18"}, {:gettext, "~> 0.18"},
{:jason, "~> 1.2"}, {:jason, "~> 1.2"},
{:plug_cowboy, "~> 2.5"}, {:oban, "~> 2.10"},
{:ecto_psql_extras, "~> 0.6"}, {:phoenix_ecto, "~> 4.4"},
{:eqrcode, "~> 0.1.10"}, {:phoenix_html_helpers, "~> 1.0"},
{:credo, "~> 1.5", only: [:dev, :test], runtime: false}, {:phoenix_html, "~> 4.0"},
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false} {:phoenix_live_dashboard, "~> 0.8"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 0.20.0"},
{:phoenix, "~> 1.7.11"},
{:plug_cowboy, "~> 2.7.0"},
{:postgrex, ">= 0.0.0"},
{:swoosh, "~> 1.6"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 1.0"}
] ]
end end

View File

@ -1,54 +1,54 @@
%{ %{
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.2.0", "feab711974beba4cb348147170346fe097eea2e840db4e012a145e180ed4ab75", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "563e92a6c77d667b19c5f4ba17ab6d440a085696bdf4c68b9b0f5b30bc5422b8"},
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"}, "comeonin": {:hex, :comeonin, "5.5.0", "364d00df52545c44a139bad919d7eacb55abf39e86565878e17cebb787977368", [:mix], [], "hexpm", "6287fc3ba0aad34883cbe3f7949fc1d1e738e5ccdce77165bc99490aa69f47fb"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
"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.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
"credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"}, "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"},
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"}, "dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"},
"earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, "earmark_parser": {:hex, :earmark_parser, "1.4.42", "f23d856f41919f17cd06a493923a722d87a2d684f143a1e663c04a2b93100682", [:mix], [], "hexpm", "6915b6ca369b5f7346636a2f41c6a6d78b5af419d61a611079189233358b8b8b"},
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 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", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"}, "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_psql_extras": {:hex, :ecto_psql_extras, "0.7.14", "7a20cfe913b0476542b43870e67386461258734896035e3f284039fd18bd4c4c", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "22f5f98592dd597db9416fcef00effae0787669fdcb6faf447e982b553798e98"}, "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.8.3", "0c1df205bd051eaf599b3671e75356b121aa71eac09b63ecf921cb1a080c072e", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "> 0.16.0 and < 0.20.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "d0e35ea160359e759a2993a00c3a5389a9ca7ece6df5d0753fa927f988c7351a"},
"ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.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", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"}, "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"},
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
"eqrcode": {:hex, :eqrcode, "0.1.10", "6294fece9d68ad64eef1c3c92cf111cfd6469f4fbf230a2d4cc905a682178f3f", [:mix], [], "hexpm", "da30e373c36a0fd37ab6f58664b16029919896d6c45a68a95cc4d713e81076f1"}, "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.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
"ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "ex_doc": {:hex, :ex_doc, "0.36.1", "4197d034f93e0b89ec79fac56e226107824adcce8d2dd0a26f5ed3a95efc36b1", [: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", "d7d26a7cf965dacadcd48f9fa7b5953d7d0cfa3b44fa7a65514427da44eafd89"},
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"}, "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
"floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"}, "floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"},
"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.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"},
"gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "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.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "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, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [: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", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "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, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"oban": {:hex, :oban, "2.16.3", "33ebe7da637cce4da5438c1636bc25448a8628994a0c064ac6078bbe6dc97bd6", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4d8a7fb62f63cf2f2080c78954425f5fd8916ef57196b7f79b5bc657abb2ac5f"}, "oban": {:hex, :oban, "2.18.3", "1608c04f8856c108555c379f2f56bc0759149d35fa9d3b825cb8a6769f8ae926", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "36ca6ca84ef6518f9c2c759ea88efd438a3c81d667ba23b02b062a0aa785475e"},
"phoenix": {:hex, :phoenix, "1.7.10", "02189140a61b2ce85bb633a9b6fd02dff705a5f1596869547aeb2b2b95edd729", [: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.6", [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", "cf784932e010fd736d656d7fead6a584a4498efefe5b8227e9f383bf15bb79d0"}, "phoenix": {:hex, :phoenix, "1.7.18", "5310c21443514be44ed93c422e15870aef254cf1b3619e4f91538e7529d2b2e4", [: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", "1797fcc82108442a66f2c77a643a62980f342bfeb63d6c9a515ab8294870004e"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"}, "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_html": {:hex, :phoenix_html, "3.3.3", "380b8fb45912b5638d2f1d925a3771b4516b9a78587249cabe394e0a5d579dc9", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "923ebe6fec6e2e3b3e569dfbdc6560de932cd54b000ada0208b5f45024bdd76c"}, "phoenix_html": {:hex, :phoenix_html, "4.2.0", "83a4d351b66f472ebcce242e4ae48af1b781866f00ef0eb34c15030d4e2069ac", [:mix], [], "hexpm", "9713b3f238d07043583a94296cc4bbdceacd3b3a6c74667f4df13971e7866ec8"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.3", "7ff51c9b6609470f681fbea20578dede0e548302b0c8bdf338b5a753a4f045bf", [: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", "f9470a0a8bae4f56430a23d42f977b5a6205fdba6559d76f932b876bfaec652d"}, "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_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"}, "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_view": {:hex, :phoenix_live_view, "0.20.1", "92a37acf07afca67ac98bd326532ba8f44ad7d4bdf3e4361b03f7f02594e5ae9", [:mix], [{: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", [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", "be494fd1215052729298b0e97d5c2ce8e719c00854b82cd8cf15c1cd7fcf6294"}, "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_view": {:hex, :phoenix_live_view, "0.20.17", "f396bbdaf4ba227b82251eb75ac0afa6b3da5e509bc0d030206374237dfc9450", [: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", "a61d741ffb78c85fdbca0de084da6a48f8ceb5261a79165b5a0b59e5f65ce98b"},
"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.3", "32de561eefcefa951aead30a1f94f1b5f0379bc9e340bb5c667f65f1edfa4326", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "16f4b6588a4152f3cc057b9d0c0ba7e82ee23afa65543da535313ad8d25d8e2c"}, "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.15.1", "b7efd81c1a1286f13efb3f769de343236bd8b7d23b4a9f40d3002fc39ad8f74c", [: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", "459497bd94d041d98d948054ec6c0b76feacd28eec38b219ca04c0de13c79d30"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [: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", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_cowboy": {:hex, :plug_cowboy, "2.6.1", "9a3bbfceeb65eff5f39dab529e5cd79137ac36e913c02067dba3963a26efe9b2", [: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", "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613"}, "plug_cowboy": {:hex, :plug_cowboy, "2.7.2", "fdadb973799ae691bf9ecad99125b16625b1c6039999da5fe544d99218e662e4", [: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", "245d8a11ee2306094840c000e8816f0cbed69a23fc0ac2bcf8d7835ae019bb2f"},
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"postgrex": {:hex, :postgrex, "0.17.3", "c92cda8de2033a7585dae8c61b1d420a1a1322421df84da9a82a6764580c503d", [: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", "946cf46935a4fdca7a81448be76ba3503cff082df42c6ec1ff16a4bdfbfb098d"}, "postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [: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", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"swoosh": {:hex, :swoosh, "1.14.0", "710e363e114dedb4080b737e0307f5410887ffc9a239f818231e5618b6b84e1b", [:mix], [{: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]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dccfc986ac99c18345ab3e1a8b934b2d817fd6d59a2494f0af78502184c71025"}, "swoosh": {:hex, :swoosh, "1.17.5", "14910d267a2633d4335917b37846e376e2067815601592629366c39845dad145", [: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 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "629113d477bc82c4c3bffd15a25e8becc1c7ccc0f0e67743b017caddebb06f04"},
"table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, "table_rex": {:hex, :table_rex, "4.0.0", "3c613a68ebdc6d4d1e731bc973c233500974ec3993c99fcdabb210407b90959b", [:mix], [], "hexpm", "c35c4d5612ca49ebb0344ea10387da4d2afe278387d4019e4d8111e815df8f55"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"},
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
"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.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [: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", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, "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

@ -66,11 +66,6 @@ msgstr ""
msgid "edit" msgid "edit"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:85 #: lib/memex_web/components/core_components/topbar.html.heex:85
#: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28 #: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28
#: lib/memex_web/controllers/user_registration_html/new.html.heex:44 #: lib/memex_web/controllers/user_registration_html/new.html.heex:44
@ -108,11 +103,11 @@ msgstr ""
msgid "register" msgid "register"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:49 #: lib/memex_web/live/context_live/form_component.html.heex:51
#: lib/memex_web/live/invite_live/form_component.html.heex:47 #: lib/memex_web/live/invite_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:47 #: lib/memex_web/live/note_live/form_component.html.heex:49
#: lib/memex_web/live/pipeline_live/form_component.html.heex:53 #: lib/memex_web/live/pipeline_live/form_component.html.heex:55
#: lib/memex_web/live/step_live/form_component.html.heex:37 #: lib/memex_web/live/step_live/form_component.html.heex:38
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "save" msgid "save"
msgstr "" msgstr ""
@ -217,3 +212,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "reset password" msgid "reset password"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format
msgid "new invite"
msgstr ""

View File

@ -66,11 +66,6 @@ msgstr ""
msgid "edit" msgid "edit"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:85 #: lib/memex_web/components/core_components/topbar.html.heex:85
#: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28 #: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28
#: lib/memex_web/controllers/user_registration_html/new.html.heex:44 #: lib/memex_web/controllers/user_registration_html/new.html.heex:44
@ -108,11 +103,11 @@ msgstr ""
msgid "register" msgid "register"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:49 #: lib/memex_web/live/context_live/form_component.html.heex:51
#: lib/memex_web/live/invite_live/form_component.html.heex:47 #: lib/memex_web/live/invite_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:47 #: lib/memex_web/live/note_live/form_component.html.heex:49
#: lib/memex_web/live/pipeline_live/form_component.html.heex:53 #: lib/memex_web/live/pipeline_live/form_component.html.heex:55
#: lib/memex_web/live/step_live/form_component.html.heex:37 #: lib/memex_web/live/step_live/form_component.html.heex:38
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "save" msgid "save"
msgstr "" msgstr ""
@ -217,3 +212,8 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "reset password" msgid "reset password"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format, fuzzy
msgid "new invite"
msgstr ""

View File

@ -237,20 +237,20 @@ msgstr ""
msgid "report bugs or request features" msgid "report bugs or request features"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:50 #: lib/memex_web/live/context_live/form_component.html.heex:52
#: lib/memex_web/live/note_live/form_component.html.heex:48 #: lib/memex_web/live/note_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:54 #: lib/memex_web/live/pipeline_live/form_component.html.heex:56
#: lib/memex_web/live/step_live/form_component.html.heex:38 #: lib/memex_web/live/step_live/form_component.html.heex:39
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:44 #: lib/memex_web/live/context_live/form_component.html.heex:46
#: lib/memex_web/live/context_live/form_component.html.heex:45 #: lib/memex_web/live/context_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:42 #: lib/memex_web/live/note_live/form_component.html.heex:44
#: lib/memex_web/live/note_live/form_component.html.heex:43 #: lib/memex_web/live/note_live/form_component.html.heex:45
#: lib/memex_web/live/pipeline_live/form_component.html.heex:48 #: lib/memex_web/live/pipeline_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:49 #: lib/memex_web/live/pipeline_live/form_component.html.heex:51
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "select privacy" msgid "select privacy"
msgstr "" msgstr ""
@ -266,12 +266,12 @@ msgstr ""
msgid "settings" msgid "settings"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:35 #: lib/memex_web/live/context_live/form_component.html.heex:34
#: lib/memex_web/live/context_live/form_component.html.heex:36 #: lib/memex_web/live/context_live/form_component.html.heex:39
#: lib/memex_web/live/note_live/form_component.html.heex:33 #: lib/memex_web/live/note_live/form_component.html.heex:32
#: lib/memex_web/live/note_live/form_component.html.heex:34 #: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:39 #: lib/memex_web/live/pipeline_live/form_component.html.heex:38
#: lib/memex_web/live/pipeline_live/form_component.html.heex:40 #: lib/memex_web/live/pipeline_live/form_component.html.heex:43
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "tag1,tag2" msgid "tag1,tag2"
msgstr "" msgstr ""
@ -379,12 +379,12 @@ msgstr ""
#: lib/memex_web/components/contexts_table_component.ex:47 #: lib/memex_web/components/contexts_table_component.ex:47
#: lib/memex_web/components/notes_table_component.ex:47 #: lib/memex_web/components/notes_table_component.ex:47
#: lib/memex_web/components/pipelines_table_component.ex:47 #: lib/memex_web/components/pipelines_table_component.ex:47
#: lib/memex_web/live/context_live/form_component.html.heex:14 #: lib/memex_web/live/context_live/form_component.html.heex:13
#: lib/memex_web/live/context_live/form_component.html.heex:15 #: lib/memex_web/live/context_live/form_component.html.heex:17
#: lib/memex_web/live/note_live/form_component.html.heex:14 #: lib/memex_web/live/note_live/form_component.html.heex:13
#: lib/memex_web/live/note_live/form_component.html.heex:15 #: lib/memex_web/live/note_live/form_component.html.heex:17
#: lib/memex_web/live/pipeline_live/form_component.html.heex:14 #: lib/memex_web/live/pipeline_live/form_component.html.heex:13
#: lib/memex_web/live/pipeline_live/form_component.html.heex:15 #: lib/memex_web/live/pipeline_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "slug" msgid "slug"
msgstr "" msgstr ""
@ -457,8 +457,8 @@ msgstr ""
msgid "steps:" msgid "steps:"
msgstr "" msgstr ""
#: lib/memex_web/live/step_live/form_component.html.heex:14 #: lib/memex_web/live/step_live/form_component.html.heex:13
#: lib/memex_web/live/step_live/form_component.html.heex:15 #: lib/memex_web/live/step_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "title" msgid "title"
msgstr "" msgstr ""
@ -468,16 +468,6 @@ msgstr ""
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!" msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could backlink to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could backlink to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:59 #: lib/memex_web/live/faq_live.html.heex:59
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy." msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy."
@ -498,11 +488,6 @@ msgstr ""
msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life." msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life."
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format
msgid "in my opinion, pipelines should be pretty lightweight, and just backlink to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:28 #: lib/memex_web/live/faq_live.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "memex" msgid "memex"
@ -568,11 +553,6 @@ msgstr ""
msgid "how many people should i invite?" msgid "how many people should i invite?"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:122 #: lib/memex_web/live/faq_live.html.heex:122
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)" msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
@ -682,7 +662,7 @@ msgstr ""
msgid "log out" msgid "log out"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:8 #: lib/memex_web/controllers/user_confirmation_controller.ex:7
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "confirm your account" msgid "confirm your account"
msgstr "" msgstr ""
@ -692,22 +672,42 @@ msgstr ""
msgid "reset your password" msgid "reset your password"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/form_component.html.heex:25 #: lib/memex_web/live/pipeline_live/form_component.html.heex:26
#: lib/memex_web/live/pipeline_live/form_component.html.heex:29 #: lib/memex_web/live/pipeline_live/form_component.html.heex:30
#: lib/memex_web/live/step_live/form_component.html.heex:25 #: lib/memex_web/live/step_live/form_component.html.heex:26
#: lib/memex_web/live/step_live/form_component.html.heex:29 #: lib/memex_web/live/step_live/form_component.html.heex:30
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline" msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:25 #: lib/memex_web/live/context_live/form_component.html.heex:26
#: lib/memex_web/live/context_live/form_component.html.heex:27 #: lib/memex_web/live/context_live/form_component.html.heex:28
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context" msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context"
msgstr "" msgstr ""
#: lib/memex_web/live/note_live/form_component.html.heex:24
#: lib/memex_web/live/note_live/form_component.html.heex:25 #: lib/memex_web/live/note_live/form_component.html.heex:25
#: lib/memex_web/live/note_live/form_component.html.heex:26
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "use [note-slug] to link to a note" msgid "use [note-slug] to link to a note"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format, fuzzy
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could link to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format, fuzzy
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could link to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format, fuzzy
msgid "in my opinion, pipelines should be pretty lightweight, and just link to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format, fuzzy
msgid "note, context and pipeline slugs must be unique, and you are free to link to notes not written by you."
msgstr ""

View File

@ -66,12 +66,12 @@ msgstr ""
msgid "Welcome to memEx" msgid "Welcome to memEx"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:31 #: lib/memex/email.ex:31
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "confirm your memEx account" msgid "confirm your memEx account"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:37 #: lib/memex/email.ex:37
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "reset your memEx password" msgid "reset your memEx password"
msgstr "" msgstr ""
@ -86,7 +86,7 @@ msgstr ""
msgid "this email was sent from memEx at %{url}" msgid "this email was sent from memEx at %{url}"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:43 #: lib/memex/email.ex:43
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "update your memEx email" msgid "update your memEx email"
msgstr "" msgstr ""

View File

@ -135,7 +135,7 @@ msgstr ""
msgid "sorry, public registration is disabled" msgid "sorry, public registration is disabled"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:53 #: lib/memex_web/controllers/user_confirmation_controller.ex:52
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "user confirmation link is invalid or it has expired." msgid "user confirmation link is invalid or it has expired."
msgstr "" msgstr ""

View File

@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Language: de\n" "Language: de\n"
#: lib/memex_web/controllers/user_confirmation_controller.ex:37 #: lib/memex_web/controllers/user_confirmation_controller.ex:36
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{email} confirmed successfully." msgid "%{email} confirmed successfully."
msgstr "" msgstr ""
@ -142,7 +142,7 @@ msgstr ""
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:23 #: lib/memex_web/controllers/user_confirmation_controller.ex:22
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly."
msgstr "" msgstr ""

View File

@ -235,20 +235,20 @@ msgstr ""
msgid "report bugs or request features" msgid "report bugs or request features"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:50 #: lib/memex_web/live/context_live/form_component.html.heex:52
#: lib/memex_web/live/note_live/form_component.html.heex:48 #: lib/memex_web/live/note_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:54 #: lib/memex_web/live/pipeline_live/form_component.html.heex:56
#: lib/memex_web/live/step_live/form_component.html.heex:38 #: lib/memex_web/live/step_live/form_component.html.heex:39
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:44 #: lib/memex_web/live/context_live/form_component.html.heex:46
#: lib/memex_web/live/context_live/form_component.html.heex:45 #: lib/memex_web/live/context_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:42 #: lib/memex_web/live/note_live/form_component.html.heex:44
#: lib/memex_web/live/note_live/form_component.html.heex:43 #: lib/memex_web/live/note_live/form_component.html.heex:45
#: lib/memex_web/live/pipeline_live/form_component.html.heex:48 #: lib/memex_web/live/pipeline_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:49 #: lib/memex_web/live/pipeline_live/form_component.html.heex:51
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "select privacy" msgid "select privacy"
msgstr "" msgstr ""
@ -264,12 +264,12 @@ msgstr ""
msgid "settings" msgid "settings"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:35 #: lib/memex_web/live/context_live/form_component.html.heex:34
#: lib/memex_web/live/context_live/form_component.html.heex:36 #: lib/memex_web/live/context_live/form_component.html.heex:39
#: lib/memex_web/live/note_live/form_component.html.heex:33 #: lib/memex_web/live/note_live/form_component.html.heex:32
#: lib/memex_web/live/note_live/form_component.html.heex:34 #: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:39 #: lib/memex_web/live/pipeline_live/form_component.html.heex:38
#: lib/memex_web/live/pipeline_live/form_component.html.heex:40 #: lib/memex_web/live/pipeline_live/form_component.html.heex:43
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "tag1,tag2" msgid "tag1,tag2"
msgstr "" msgstr ""
@ -377,12 +377,12 @@ msgstr ""
#: lib/memex_web/components/contexts_table_component.ex:47 #: lib/memex_web/components/contexts_table_component.ex:47
#: lib/memex_web/components/notes_table_component.ex:47 #: lib/memex_web/components/notes_table_component.ex:47
#: lib/memex_web/components/pipelines_table_component.ex:47 #: lib/memex_web/components/pipelines_table_component.ex:47
#: lib/memex_web/live/context_live/form_component.html.heex:14 #: lib/memex_web/live/context_live/form_component.html.heex:13
#: lib/memex_web/live/context_live/form_component.html.heex:15 #: lib/memex_web/live/context_live/form_component.html.heex:17
#: lib/memex_web/live/note_live/form_component.html.heex:14 #: lib/memex_web/live/note_live/form_component.html.heex:13
#: lib/memex_web/live/note_live/form_component.html.heex:15 #: lib/memex_web/live/note_live/form_component.html.heex:17
#: lib/memex_web/live/pipeline_live/form_component.html.heex:14 #: lib/memex_web/live/pipeline_live/form_component.html.heex:13
#: lib/memex_web/live/pipeline_live/form_component.html.heex:15 #: lib/memex_web/live/pipeline_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "slug" msgid "slug"
msgstr "" msgstr ""
@ -455,8 +455,8 @@ msgstr ""
msgid "steps:" msgid "steps:"
msgstr "" msgstr ""
#: lib/memex_web/live/step_live/form_component.html.heex:14 #: lib/memex_web/live/step_live/form_component.html.heex:13
#: lib/memex_web/live/step_live/form_component.html.heex:15 #: lib/memex_web/live/step_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "title" msgid "title"
msgstr "" msgstr ""
@ -466,16 +466,6 @@ msgstr ""
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!" msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could backlink to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could backlink to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:59 #: lib/memex_web/live/faq_live.html.heex:59
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy." msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy."
@ -496,11 +486,6 @@ msgstr ""
msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life." msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life."
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format
msgid "in my opinion, pipelines should be pretty lightweight, and just backlink to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:28 #: lib/memex_web/live/faq_live.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "memex" msgid "memex"
@ -566,11 +551,6 @@ msgstr ""
msgid "how many people should i invite?" msgid "how many people should i invite?"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:122 #: lib/memex_web/live/faq_live.html.heex:122
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)" msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
@ -680,7 +660,7 @@ msgstr ""
msgid "log out" msgid "log out"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:8 #: lib/memex_web/controllers/user_confirmation_controller.ex:7
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "confirm your account" msgid "confirm your account"
msgstr "" msgstr ""
@ -690,22 +670,42 @@ msgstr ""
msgid "reset your password" msgid "reset your password"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/form_component.html.heex:25 #: lib/memex_web/live/pipeline_live/form_component.html.heex:26
#: lib/memex_web/live/pipeline_live/form_component.html.heex:29 #: lib/memex_web/live/pipeline_live/form_component.html.heex:30
#: lib/memex_web/live/step_live/form_component.html.heex:25 #: lib/memex_web/live/step_live/form_component.html.heex:26
#: lib/memex_web/live/step_live/form_component.html.heex:29 #: lib/memex_web/live/step_live/form_component.html.heex:30
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline" msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:25 #: lib/memex_web/live/context_live/form_component.html.heex:26
#: lib/memex_web/live/context_live/form_component.html.heex:27 #: lib/memex_web/live/context_live/form_component.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context" msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context"
msgstr "" msgstr ""
#: lib/memex_web/live/note_live/form_component.html.heex:24
#: lib/memex_web/live/note_live/form_component.html.heex:25 #: lib/memex_web/live/note_live/form_component.html.heex:25
#: lib/memex_web/live/note_live/form_component.html.heex:26
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "use [note-slug] to link to a note" msgid "use [note-slug] to link to a note"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could link to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could link to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format
msgid "in my opinion, pipelines should be pretty lightweight, and just link to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to link to notes not written by you."
msgstr ""

View File

@ -66,12 +66,12 @@ msgstr ""
msgid "Welcome to memEx" msgid "Welcome to memEx"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:31 #: lib/memex/email.ex:31
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "confirm your memEx account" msgid "confirm your memEx account"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:37 #: lib/memex/email.ex:37
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "reset your memEx password" msgid "reset your memEx password"
msgstr "" msgstr ""
@ -86,7 +86,7 @@ msgstr ""
msgid "this email was sent from memEx at %{url}" msgid "this email was sent from memEx at %{url}"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:43 #: lib/memex/email.ex:43
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "update your memEx email" msgid "update your memEx email"
msgstr "" msgstr ""

View File

@ -67,11 +67,6 @@ msgstr ""
msgid "edit" msgid "edit"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:85 #: lib/memex_web/components/core_components/topbar.html.heex:85
#: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28 #: lib/memex_web/controllers/user_confirmation_html/new.html.heex:28
#: lib/memex_web/controllers/user_registration_html/new.html.heex:44 #: lib/memex_web/controllers/user_registration_html/new.html.heex:44
@ -109,11 +104,11 @@ msgstr ""
msgid "register" msgid "register"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:49 #: lib/memex_web/live/context_live/form_component.html.heex:51
#: lib/memex_web/live/invite_live/form_component.html.heex:47 #: lib/memex_web/live/invite_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:47 #: lib/memex_web/live/note_live/form_component.html.heex:49
#: lib/memex_web/live/pipeline_live/form_component.html.heex:53 #: lib/memex_web/live/pipeline_live/form_component.html.heex:55
#: lib/memex_web/live/step_live/form_component.html.heex:37 #: lib/memex_web/live/step_live/form_component.html.heex:38
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "save" msgid "save"
msgstr "" msgstr ""
@ -218,3 +213,8 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "reset password" msgid "reset password"
msgstr "" msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:12
#, elixir-autogen, elixir-format, fuzzy
msgid "new invite"
msgstr ""

View File

@ -236,20 +236,20 @@ msgstr ""
msgid "report bugs or request features" msgid "report bugs or request features"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:50 #: lib/memex_web/live/context_live/form_component.html.heex:52
#: lib/memex_web/live/note_live/form_component.html.heex:48 #: lib/memex_web/live/note_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:54 #: lib/memex_web/live/pipeline_live/form_component.html.heex:56
#: lib/memex_web/live/step_live/form_component.html.heex:38 #: lib/memex_web/live/step_live/form_component.html.heex:39
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:44 #: lib/memex_web/live/context_live/form_component.html.heex:46
#: lib/memex_web/live/context_live/form_component.html.heex:45 #: lib/memex_web/live/context_live/form_component.html.heex:47
#: lib/memex_web/live/note_live/form_component.html.heex:42 #: lib/memex_web/live/note_live/form_component.html.heex:44
#: lib/memex_web/live/note_live/form_component.html.heex:43 #: lib/memex_web/live/note_live/form_component.html.heex:45
#: lib/memex_web/live/pipeline_live/form_component.html.heex:48 #: lib/memex_web/live/pipeline_live/form_component.html.heex:50
#: lib/memex_web/live/pipeline_live/form_component.html.heex:49 #: lib/memex_web/live/pipeline_live/form_component.html.heex:51
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "select privacy" msgid "select privacy"
msgstr "" msgstr ""
@ -265,12 +265,12 @@ msgstr ""
msgid "settings" msgid "settings"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:35 #: lib/memex_web/live/context_live/form_component.html.heex:34
#: lib/memex_web/live/context_live/form_component.html.heex:36 #: lib/memex_web/live/context_live/form_component.html.heex:39
#: lib/memex_web/live/note_live/form_component.html.heex:33 #: lib/memex_web/live/note_live/form_component.html.heex:32
#: lib/memex_web/live/note_live/form_component.html.heex:34 #: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:39 #: lib/memex_web/live/pipeline_live/form_component.html.heex:38
#: lib/memex_web/live/pipeline_live/form_component.html.heex:40 #: lib/memex_web/live/pipeline_live/form_component.html.heex:43
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "tag1,tag2" msgid "tag1,tag2"
msgstr "" msgstr ""
@ -378,12 +378,12 @@ msgstr ""
#: lib/memex_web/components/contexts_table_component.ex:47 #: lib/memex_web/components/contexts_table_component.ex:47
#: lib/memex_web/components/notes_table_component.ex:47 #: lib/memex_web/components/notes_table_component.ex:47
#: lib/memex_web/components/pipelines_table_component.ex:47 #: lib/memex_web/components/pipelines_table_component.ex:47
#: lib/memex_web/live/context_live/form_component.html.heex:14 #: lib/memex_web/live/context_live/form_component.html.heex:13
#: lib/memex_web/live/context_live/form_component.html.heex:15 #: lib/memex_web/live/context_live/form_component.html.heex:17
#: lib/memex_web/live/note_live/form_component.html.heex:14 #: lib/memex_web/live/note_live/form_component.html.heex:13
#: lib/memex_web/live/note_live/form_component.html.heex:15 #: lib/memex_web/live/note_live/form_component.html.heex:17
#: lib/memex_web/live/pipeline_live/form_component.html.heex:14 #: lib/memex_web/live/pipeline_live/form_component.html.heex:13
#: lib/memex_web/live/pipeline_live/form_component.html.heex:15 #: lib/memex_web/live/pipeline_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "slug" msgid "slug"
msgstr "" msgstr ""
@ -456,8 +456,8 @@ msgstr ""
msgid "steps:" msgid "steps:"
msgstr "" msgstr ""
#: lib/memex_web/live/step_live/form_component.html.heex:14 #: lib/memex_web/live/step_live/form_component.html.heex:13
#: lib/memex_web/live/step_live/form_component.html.heex:15 #: lib/memex_web/live/step_live/form_component.html.heex:17
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "title" msgid "title"
msgstr "" msgstr ""
@ -467,16 +467,6 @@ msgstr ""
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!" msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could backlink to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could backlink to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:59 #: lib/memex_web/live/faq_live.html.heex:59
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy." msgid "i really admired the idea of a zettelkasten, especially with org-mode backlinks, however I felt like my notes would immediately become too messy by just putting everything into a single hierarchy."
@ -497,11 +487,6 @@ msgstr ""
msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life." msgid "in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life."
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format
msgid "in my opinion, pipelines should be pretty lightweight, and just backlink to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:28 #: lib/memex_web/live/faq_live.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "memex" msgid "memex"
@ -567,11 +552,6 @@ msgstr ""
msgid "how many people should i invite?" msgid "how many people should i invite?"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:122 #: lib/memex_web/live/faq_live.html.heex:122
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)" msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
@ -681,7 +661,7 @@ msgstr ""
msgid "log out" msgid "log out"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:8 #: lib/memex_web/controllers/user_confirmation_controller.ex:7
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "confirm your account" msgid "confirm your account"
msgstr "" msgstr ""
@ -691,22 +671,42 @@ msgstr ""
msgid "reset your password" msgid "reset your password"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/form_component.html.heex:25 #: lib/memex_web/live/pipeline_live/form_component.html.heex:26
#: lib/memex_web/live/pipeline_live/form_component.html.heex:29 #: lib/memex_web/live/pipeline_live/form_component.html.heex:30
#: lib/memex_web/live/step_live/form_component.html.heex:25 #: lib/memex_web/live/step_live/form_component.html.heex:26
#: lib/memex_web/live/step_live/form_component.html.heex:29 #: lib/memex_web/live/step_live/form_component.html.heex:30
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline" msgid "use [[[note-slug]]] to link to a note or use [[context-slug]] to link to a context or [pipeline-slug] to link to a pipeline"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:25 #: lib/memex_web/live/context_live/form_component.html.heex:26
#: lib/memex_web/live/context_live/form_component.html.heex:27 #: lib/memex_web/live/context_live/form_component.html.heex:28
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context" msgid "use [[note-slug]] to link to a note or [context-slug] to link to a context"
msgstr "" msgstr ""
#: lib/memex_web/live/note_live/form_component.html.heex:24
#: lib/memex_web/live/note_live/form_component.html.heex:25 #: lib/memex_web/live/note_live/form_component.html.heex:25
#: lib/memex_web/live/note_live/form_component.html.heex:26
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "use [note-slug] to link to a note" msgid "use [note-slug] to link to a note"
msgstr "" msgstr ""
#: lib/memex_web/live/faq_live.html.heex:91
#, elixir-autogen, elixir-format, fuzzy
msgid "for instance, a good context could be what makes some physical designs spark joy for you, and in that context you could link to the spoon note as an example of how it fits nicely into your hand."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:105
#, elixir-autogen, elixir-format, fuzzy
msgid "for instance, a pipeline for buying an object could have a step where you consider how much it sparks joy, and it could link to the physical designs context, maybe with some notes about how it applies in this case."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#, elixir-autogen, elixir-format, fuzzy
msgid "in my opinion, pipelines should be pretty lightweight, and just link to contexts to provide most of the heavy lifting."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:119
#, elixir-autogen, elixir-format, fuzzy
msgid "note, context and pipeline slugs must be unique, and you are free to link to notes not written by you."
msgstr ""

View File

@ -67,12 +67,12 @@ msgstr ""
msgid "Welcome to memEx" msgid "Welcome to memEx"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:31 #: lib/memex/email.ex:31
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "confirm your memEx account" msgid "confirm your memEx account"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:37 #: lib/memex/email.ex:37
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "reset your memEx password" msgid "reset your memEx password"
msgstr "" msgstr ""
@ -87,7 +87,7 @@ msgstr ""
msgid "this email was sent from memEx at %{url}" msgid "this email was sent from memEx at %{url}"
msgstr "" msgstr ""
#: lib/memex/accounts/email.ex:43 #: lib/memex/email.ex:43
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "update your memEx email" msgid "update your memEx email"
msgstr "" msgstr ""

View File

@ -136,7 +136,7 @@ msgstr ""
msgid "sorry, public registration is disabled" msgid "sorry, public registration is disabled"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:53 #: lib/memex_web/controllers/user_confirmation_controller.ex:52
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "user confirmation link is invalid or it has expired." msgid "user confirmation link is invalid or it has expired."
msgstr "" msgstr ""

View File

@ -11,7 +11,7 @@ msgstr ""
"Language: en\n" "Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex_web/controllers/user_confirmation_controller.ex:37 #: lib/memex_web/controllers/user_confirmation_controller.ex:36
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{email} confirmed successfully." msgid "%{email} confirmed successfully."
msgstr "" msgstr ""
@ -143,7 +143,7 @@ msgstr ""
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:23 #: lib/memex_web/controllers/user_confirmation_controller.ex:22
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly."
msgstr "" msgstr ""

View File

@ -135,7 +135,7 @@ msgstr ""
msgid "sorry, public registration is disabled" msgid "sorry, public registration is disabled"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:53 #: lib/memex_web/controllers/user_confirmation_controller.ex:52
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "user confirmation link is invalid or it has expired." msgid "user confirmation link is invalid or it has expired."
msgstr "" msgstr ""

View File

@ -10,7 +10,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:37 #: lib/memex_web/controllers/user_confirmation_controller.ex:36
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{email} confirmed successfully." msgid "%{email} confirmed successfully."
msgstr "" msgstr ""
@ -142,7 +142,7 @@ msgstr ""
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:23 #: lib/memex_web/controllers/user_confirmation_controller.ex:22
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly." msgid "if your email is in our system and it has not been confirmed yet, you will receive an email with instructions shortly."
msgstr "" msgstr ""

View File

@ -316,7 +316,7 @@ defmodule Memex.AccountsTest do
test "deletes all tokens for the given user", %{user: user} do test "deletes all tokens for the given user", %{user: user} do
_session_token = Accounts.generate_user_session_token(user) _session_token = Accounts.generate_user_session_token(user)
{:ok, _} = {:ok, _user} =
Accounts.update_user_password(user, valid_user_password(), %{ Accounts.update_user_password(user, valid_user_password(), %{
"password" => "new valid password" "password" => "new valid password"
}) })

View File

@ -0,0 +1,40 @@
defmodule Memex.EmailWorkerTest do
use Memex.DataCase, async: true
def perform_job(worker, args) do
Oban.Testing.perform_job(worker, args, [])
end
test "sending welcome email" do
user = user_fixture()
{:ok, _user} =
perform_job(Memex.EmailWorker, %{
"email" => "welcome",
"user_id" => user.id,
"attrs" => %{"url" => "test_url"}
})
end
test "sending reset password email" do
user = user_fixture()
{:ok, _user} =
perform_job(Memex.EmailWorker, %{
"email" => "reset_password",
"user_id" => user.id,
"attrs" => %{"url" => "test_url"}
})
end
test "sending update email email" do
user = user_fixture()
{:ok, _user} =
perform_job(Memex.EmailWorker, %{
"email" => "update_email",
"user_id" => user.id,
"attrs" => %{"url" => "test_url"}
})
end
end

View File

@ -64,7 +64,7 @@ defmodule Memex.DataCase do
symbols = ~c"0123456789abcdef-" symbols = ~c"0123456789abcdef-"
symbol_count = Enum.count(symbols) symbol_count = Enum.count(symbols)
for _ <- Range.new(1, length), for _index <- 1..length//1,
into: "", into: "",
do: <<Enum.at(symbols, :rand.uniform(symbol_count - 1))>> do: <<Enum.at(symbols, :rand.uniform(symbol_count - 1))>>
end end

View File

@ -38,16 +38,17 @@ defmodule Memex.Fixtures do
def extract_user_token(fun) do def extract_user_token(fun) do
%{args: %{attrs: attrs, email: email_key, user_id: user_id}} = fun.(&"[TOKEN]#{&1}[TOKEN]") %{args: %{attrs: attrs, email: email_key, user_id: user_id}} = fun.(&"[TOKEN]#{&1}[TOKEN]")
# convert atoms to string keys attrs =
attrs = attrs |> Map.new(fn {atom_key, value} -> {atom_key |> Atom.to_string(), value} end) attrs
|> Map.new(fn {key, value} -> {Atom.to_string(key), value} end)
email = email =
email_key email_key
|> Atom.to_string() |> Atom.to_string()
|> Email.generate_email(Accounts.get_user!(user_id), attrs) |> Email.generate_email(Accounts.get_user!(user_id), attrs)
[_, html_token | _] = email.html_body |> String.split("[TOKEN]") [_prefix, html_token | _postfix] = email.html_body |> String.split("[TOKEN]")
[_, text_token | _] = email.text_body |> String.split("[TOKEN]") [_prefix, text_token | _postfix] = email.text_body |> String.split("[TOKEN]")
^text_token = html_token ^text_token = html_token
end end