91 Commits

Author SHA1 Message Date
2d0f6eefab run npm audit fix
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 22:02:45 -04:00
d33da32b2f run npx npm-check-updates -u 2023-03-18 22:01:38 -04:00
468489f872 add ncu as dev dependency 2023-03-18 21:54:43 -04:00
5dedb4668b use hooks for datetime, remove alpinejs 2023-03-18 21:52:04 -04:00
0d4deb6805 fix n+1 queries with invite card
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 15:06:04 -04:00
8f288afeb9 fix table component not sorting structs correctly
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 11:28:15 -04:00
aa5a1f30f9 add Accounts.registration_mode/0
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 01:31:56 -04:00
daa50039a7 use .link helpers
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 00:47:02 -04:00
98bb99881d add ids to dynamic date and datetime elements 2023-03-18 00:47:02 -04:00
56956f37fb migrate view helper components into core components
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-18 00:29:51 -04:00
a0b93d0f46 use better gettext domain for aria labels 2023-03-18 00:26:32 -04:00
066587f839 use strict context boundaries
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-16 23:53:34 -04:00
5cde99de90 use core components 2023-03-16 23:53:34 -04:00
cc29f875fa remove extra @impl true
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-16 17:29:46 -04:00
5f2e69abbd use component macros for live_helper components
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-15 00:43:35 -04:00
8ef5147078 remove data-qa
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-14 23:51:50 -04:00
c5e82c60b6 add to changelog
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-10 16:55:34 -05:00
c7debb331c merge base project into memex
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-26 01:47:26 -05:00
bc2c936480 rename to memex 2023-02-26 00:49:24 -05:00
9b4837a044 tweak topbar component 2023-02-26 00:39:26 -05:00
bd5dd57c6c name discard 2023-02-26 00:39:22 -05:00
4f0f3ec610 improve invite styling 2023-02-26 00:39:20 -05:00
6b7abdb3e1 improve moduledoc 2023-02-26 00:39:13 -05:00
db2ec3b4a3 use attrs for user card 2023-02-26 00:39:11 -05:00
f8a1d88e0e fix topbar links 2023-02-26 00:37:07 -05:00
0eafb54266 improve table component 2023-02-26 00:37:01 -05:00
b1d442ea88 remove user notifier 2023-02-26 00:34:11 -05:00
8b59339f74 add note about registration in readme 2023-02-26 00:34:04 -05:00
563bbaedf8 use elixir 1.14 2023-02-26 00:33:54 -05:00
12814be5e1 remove doctests
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-25 00:59:19 -05:00
bc034c0361 remove doctests 2023-02-25 00:58:33 -05:00
eb9280fa7e fix missing gettexts 2023-02-25 00:39:02 -05:00
ad1e44fd42 improve user settings 2023-02-14 01:06:50 -05:00
482a3902b5 bump version 2023-02-14 01:06:11 -05:00
2fa1105f40 style 大一點 2023-02-14 01:04:15 -05:00
df44be2b1b improve logger
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-07 00:18:08 -05:00
56dae6cdfe improve logger 2023-02-07 00:14:20 -05:00
8ef3bd65a3 remove search from topbar 2023-02-07 00:06:25 -05:00
6e635d1b30 improve ci
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-05 10:38:57 -05:00
ebe09bcf84 improve ci 2023-02-05 10:24:47 -05:00
fd0b2c455a fix tests 2023-02-04 21:50:43 -05:00
f1139d0ec4 improve oban logging 2023-02-04 20:47:47 -05:00
cd6bb6fbc3 fix padding on chrome 2023-02-04 20:40:46 -05:00
5c05f3b6fe use credo style 2023-02-04 17:32:40 -05:00
30d3f76fe1 record invites 2023-02-04 16:11:58 -05:00
ed8c20e967 improve invites 2023-02-04 15:05:00 -05:00
7b60938a75 improve templates 2023-02-04 13:01:11 -05:00
f19d024d8a fix bug with public registration being disabled 2023-02-04 11:35:32 -05:00
1fbed50b0f add crypto to extra applications 2023-02-01 22:39:38 -05:00
737484c36e add accounts doctests 2023-01-29 15:24:14 -05:00
6dbadc58ae fix runtime config 2023-01-26 19:55:59 -05:00
f155a43ee8 add qr code for invite link 2023-01-26 00:46:21 -05:00
bbaa1dfd6b update to liveview 0.18 2023-01-26 00:31:13 -05:00
2c2b9fefc9 use list for classes 2023-01-25 23:13:18 -05:00
bafc824a32 add subpixel antialiasing 2023-01-25 22:15:18 -05:00
8c2f7e0509 fix padding at bottom of page in chrome 2023-01-25 22:14:17 -05:00
22abc7a8d0 improve locale 2023-01-25 21:50:14 -05:00
5a685ac00e use topbar through npm 2023-01-25 21:18:00 -05:00
a5c12b3e17 fix webpack 2023-01-25 21:14:55 -05:00
27af5acf8b minimize disconnection modal 2023-01-25 21:00:34 -05:00
469428c007 add topbar.js on form submit and page navigate 2023-01-25 20:31:36 -05:00
1cd28e43b8 update elixir and npm versions 2023-01-22 23:20:02 -05:00
695002c9d9 don't override core aliases 2023-01-22 22:41:42 -05:00
dde60d71d1 update gettext 2023-01-22 22:37:49 -05:00
91794ddc55 upgrade dependencies 2023-01-22 22:36:20 -05:00
1e3cec95fe update drone config 2023-01-07 21:00:15 -05:00
f0a8c515f9 update deps 2023-01-07 21:00:15 -05:00
e99775eef2 fix gettext merge command 2023-01-07 21:00:15 -05:00
6760f83ca0 add gettext changes 2023-01-07 21:00:15 -05:00
10877bb754 rename page path to home path 2023-01-07 21:00:15 -05:00
38a581b639 add registered on date to user card 2023-01-07 21:00:15 -05:00
9408705430 update deps 2023-01-07 21:00:14 -05:00
302aa7eeda add locale to user settings 2023-01-07 21:00:14 -05:00
fd4fdcc36b add table component 2023-01-07 21:00:14 -05:00
3cb723b9e4 update build settings 2023-01-07 21:00:14 -05:00
1f92c452d1 fix tests 2023-01-07 21:00:14 -05:00
c10cff63ea add invites route 2023-01-07 21:00:14 -05:00
70faed71d0 style disconnection and loading screens 2023-01-07 21:00:14 -05:00
b5c46c09ec fix oban 2023-01-07 21:00:14 -05:00
7745765fc0 update npm 2023-01-07 21:00:14 -05:00
e16fbba810 gettext page_live 2023-01-07 21:00:14 -05:00
e35bdf101b update components 2023-01-07 21:00:14 -05:00
aa314e5ca1 update main routes 2023-01-07 21:00:14 -05:00
616de3c117 update tests 2023-01-07 21:00:14 -05:00
74bcec6cfe update controllers and auth 2023-01-07 21:00:14 -05:00
41090c46d0 add invites 2023-01-07 21:00:14 -05:00
c3f5744ad6 fix layout 2023-01-07 21:00:14 -05:00
95a339fe02 add random script 2023-01-07 21:00:14 -05:00
1e3b027367 fix docker files 2023-01-07 21:00:14 -05:00
dd46e1795f add credo 2023-01-07 21:00:14 -05:00
9e517e6477 add emails 2023-01-07 21:00:14 -05:00
94 changed files with 12905 additions and 5402 deletions

View File

@ -13,20 +13,24 @@ steps:
mount:
- _build
- deps
- assets/node_modules/
- .npm
- .mix
- name: test
image: elixir:1.14.1-alpine
environment:
TEST_DATABASE_URL: ecto://postgres:postgres@database/memex_test
HOST: testing.example.tld
MIX_HOME: /drone/src/.mix
MIX_ARCHIVES: /drone/src/.mix/archives
MIX_ENV: test
commands:
- apk add --no-cache build-base npm git python3
- mix local.rebar --force
- mix local.hex --force
- apk add --no-cache build-base npm git
- mix local.rebar --force --if-missing
- mix local.hex --force --if-missing
- mix deps.get
- mix deps.compile
- npm --prefix ./assets ci --progress=false --no-audit --loglevel=error
- npm set cache .npm
- npm --prefix ./assets ci --no-audit --prefer-offline
- npm run --prefix ./assets deploy
- mix do phx.digest, gettext.extract
- mix test.all
@ -76,7 +80,8 @@ steps:
mount:
- _build
- deps
- assets/node_modules/
- .npm
- .mix
services:
- name: database

View File

@ -1,3 +1,3 @@
elixir 1.14.1-otp-25
erlang 25.1.2
nodejs 16.18.0
nodejs 18.9.1

View File

@ -11,6 +11,7 @@
}
.checkbox {
@apply bg-primary-900;
-ms-transform: scale(1.5);
-moz-transform: scale(1.5);
-webkit-transform: scale(1.5);
@ -26,25 +27,31 @@
.btn {
@apply focus:outline-none px-4 py-2 rounded-lg;
@apply shadow-sm focus:shadow-lg;
@apply shadow-sm active:shadow-lg;
@apply border;
@apply transition-all duration-300 ease-in-out;
}
.btn-primary {
@apply bg-primary-900 focus:bg-primary-900 active:bg-primary-800;
@apply bg-primary-900 active:bg-primary-800;
@apply border-primary-900 hover:border-primary-800 active:border-primary-700;
@apply text-primary-400;
}
.btn-secondary {
@apply bg-primary-800 active:bg-primary-700;
@apply border-primary-800 hover:border-primary-700 active:border-primary-600;
@apply text-primary-400;
}
.btn-alert {
@apply bg-red-700 focus:bg-red-800 active:bg-red-900;
@apply border-red-700 focus:border-red-800 active:border-red-900;
@apply bg-red-700 active:bg-red-900;
@apply border-red-700 active:border-red-900;
@apply text-primary-300;
}
.hr {
@apply mx-auto border border-primary-600 w-full max-w-2xl;
@apply mx-auto border border-primary-600 w-full max-w-3xl;
}
.link {

View File

@ -26,26 +26,18 @@ import 'phoenix_html'
import { Socket } from 'phoenix'
import { LiveSocket } from 'phoenix_live_view'
import topbar from 'topbar'
import Date from './date'
import DateTime from './datetime'
import MaintainAttrs from './maintain_attrs'
import Alpine from 'alpinejs'
const csrfTokenElement = document.querySelector("meta[name='csrf-token']")
let csrfToken
if (csrfTokenElement) { csrfToken = csrfTokenElement.getAttribute('content') }
const liveSocket = new LiveSocket('/live', Socket, {
dom: {
onBeforeElUpdated (from, to) {
if (from._x_dataStack) { window.Alpine.clone(from, to) }
}
},
params: { _csrf_token: csrfToken },
hooks: { MaintainAttrs }
hooks: { Date, DateTime, MaintainAttrs }
})
// alpine.js
window.Alpine = Alpine
Alpine.start()
// Show progress bar on live navigation and form submits
topbar.config({ barThickness: 1, barColors: { 0: '#fff' }, shadowColor: 'rgba(0, 0, 0, .3)' })
window.addEventListener('phx:page-loading-start', info => topbar.show())

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

@ -0,0 +1,11 @@
export default {
displayDate (el) {
const date =
Intl.DateTimeFormat([], { timeZone: 'Etc/UTC', dateStyle: 'short' })
.format(new Date(el.dateTime))
el.innerText = date
},
mounted () { this.displayDate(this.el) },
updated () { this.displayDate(this.el) }
}

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

@ -0,0 +1,11 @@
export default {
displayDateTime (el) {
const date =
Intl.DateTimeFormat([], { dateStyle: 'short', timeStyle: 'long' })
.format(new Date(el.dateTime))
el.innerText = date
},
mounted () { this.displayDateTime(this.el) },
updated () { this.displayDateTime(this.el) }
}

13986
assets/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@
"description": " ",
"license": "MIT",
"engines": {
"node": "18.12.1",
"npm": "8.19.2"
"node": "v18.9.1",
"npm": "8.19.1"
},
"scripts": {
"deploy": "NODE_ENV=production webpack --mode production",
@ -13,35 +13,35 @@
"test": "standard"
},
"dependencies": {
"@fontsource/nunito-sans": "^4.5.8",
"@fortawesome/fontawesome-free": "^6.1.1",
"alpinejs": "^3.10.2",
"@fontsource/nunito-sans": "^4.5.10",
"@fortawesome/fontawesome-free": "^6.3.0",
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
"topbar": "^1.0.1"
"topbar": "^2.0.1"
},
"devDependencies": {
"@babel/core": "^7.17.10",
"@babel/preset-env": "^7.17.10",
"autoprefixer": "^10.4.7",
"babel-loader": "^8.2.5",
"copy-webpack-plugin": "^10.2.4",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^3.4.1",
"@babel/core": "^7.21.3",
"@babel/preset-env": "^7.20.2",
"autoprefixer": "^10.4.14",
"babel-loader": "^9.1.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^4.2.2",
"file-loader": "^6.2.0",
"mini-css-extract-plugin": "^2.6.0",
"postcss": "^8.4.13",
"postcss-import": "^14.1.0",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.5.0",
"sass": "^1.56.0",
"sass-loader": "^12.6.0",
"mini-css-extract-plugin": "^2.7.5",
"npm-check-updates": "^16.7.12",
"postcss": "^8.4.21",
"postcss-import": "^15.1.0",
"postcss-loader": "^7.1.0",
"postcss-preset-env": "^8.0.1",
"sass": "^1.59.3",
"sass-loader": "^13.2.1",
"standard": "^17.0.0",
"tailwindcss": "^3.0.24",
"terser-webpack-plugin": "^5.3.1",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.0"
"tailwindcss": "^3.2.7",
"terser-webpack-plugin": "^5.3.7",
"webpack": "^5.76.2",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.13.1"
}
}

View File

@ -1,3 +1,13 @@
# v0.1.10
- Improve accessibility
- Code quality improvements
- Fix dates displaying incorrectly
# v0.1.9
- Improve server log
- Style 大一點
- Various minor improvements
# v0.1.8
- Fix bug with public registration
- Improve templates

View File

@ -16,9 +16,8 @@ defmodule Memex.Accounts do
## Examples
iex> register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %User{} <- get_user_by_email("foo@example.com"), do: :passed
:passed
iex> get_user_by_email("foo@example.com")
%User{}
iex> get_user_by_email("unknown@example.com")
nil
@ -34,9 +33,8 @@ defmodule Memex.Accounts do
## Examples
iex> register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %User{} <- get_user_by_email_and_password("foo@example.com", "valid_password"), do: :passed
:passed
iex> get_user_by_email_and_password("foo@example.com", "valid_password")
%User{}
iex> get_user_by_email_and_password("foo@example.com", "invalid_password")
nil
@ -57,15 +55,14 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> get_user!(user.id)
iex> get_user!(user_id)
user
> get_user!()
iex> get_user!()
** (Ecto.NoResultsError)
"""
@spec get_user!(User.t()) :: User.t()
@spec get_user!(User.id()) :: User.t()
def get_user!(id) do
Repo.get!(User, id)
end
@ -75,10 +72,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user1} = register_user(%{email: "foo1@example.com", password: "valid_password"})
iex> {:ok, user2} = register_user(%{email: "foo2@example.com", password: "valid_password"})
iex> with %{admin: [^user1], user: [^user2]} <- list_all_users_by_role(user1), do: :passed
:passed
iex> list_all_users_by_role(user1)
%{admin: [%User{role: :admin}], user: [%User{role: :user}]}
"""
@spec list_all_users_by_role(User.t()) :: %{User.role() => [User.t()]}
@ -91,9 +86,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with [^user] <- list_users_by_role(:admin), do: :passed
:passed
iex> list_users_by_role(:admin)
[%User{role: :admin}]
"""
@spec list_users_by_role(:admin) :: [User.t()]
@ -108,13 +102,11 @@ defmodule Memex.Accounts do
## Examples
iex> with {:ok, %User{email: "foo@example.com"}} <-
...> register_user(%{email: "foo@example.com", password: "valid_password"}),
...> do: :passed
:passed
iex> register_user(%{email: "foo@example.com", password: "valid_password"})
{:ok, %User{email: "foo@example.com"}}
iex> with {:error, %Changeset{}} <- register_user(%{email: "foo@example"}), do: :passed
:passed
iex> register_user(%{email: "foo@example"})
{:error, %Changeset{}}
"""
@spec register_user(attrs :: map()) ::
@ -149,11 +141,11 @@ defmodule Memex.Accounts do
## Examples
iex> with %Changeset{} <- change_user_registration(), do: :passed
:passed
iex> change_user_registration()
%Changeset{}
iex> with %Changeset{} <- change_user_registration(%{password: "hi"}), do: :passed
:passed
iex> change_user_registration(%{password: "hi"}
%Changeset{}
"""
@spec change_user_registration() :: User.changeset()
@ -169,8 +161,8 @@ defmodule Memex.Accounts do
## Examples
iex> with %Changeset{} <- change_user_email(%User{email: "foo@example.com"}), do: :passed
:passed
iex> change_user_email(%User{email: "foo@example.com"})
%Changeset{}
"""
@spec change_user_email(User.t()) :: User.changeset()
@ -184,8 +176,8 @@ defmodule Memex.Accounts do
## Examples
iex> with %Changeset{} <- change_user_role(%User{}, :user), do: :passed
:passed
iex> change_user_role(%User{}, :user)
%Changeset{}
"""
@spec change_user_role(User.t(), User.role()) :: User.changeset()
@ -199,17 +191,11 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:ok, %User{}} <-
...> apply_user_email(user, "valid_password", %{email: "new_email@account.com"}),
...> do: :passed
:passed
iex> apply_user_email(user, "valid_password", %{email: "new_email@account.com"})
{:ok, %User{}}
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:error, %Changeset{}} <-
...> apply_user_email(user, "invalid password", %{email: "new_email@account"}),
...> do: :passed
:passed
iex> apply_user_email(user, "invalid password", %{email: "new_email@account"})
{:error, %Changeset{}}
"""
@spec apply_user_email(User.t(), email :: String.t(), attrs :: map()) ::
@ -254,12 +240,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, %{id: user_id} = user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %Oban.Job{
...> args: %{email: :update_email, user_id: ^user_id, attrs: %{url: "example url"}}
...> } <- deliver_update_email_instructions(user, "new_foo@example.com", fn _token -> "example url" end),
...> do: :passed
:passed
iex> deliver_update_email_instructions(user, "new_foo@example.com", fn _token -> "example url" end)
%Oban.Job{args: %{email: :update_email, user_id: ^user_id, attrs: %{url: "example url"}}}
"""
@spec deliver_update_email_instructions(User.t(), current_email :: String.t(), function) ::
@ -276,8 +258,8 @@ defmodule Memex.Accounts do
## Examples
iex> with %Changeset{} <- change_user_password(%User{}), do: :passed
:passed
iex> change_user_password(%User{})
%Changeset{}
"""
@spec change_user_password(User.t(), attrs :: map()) :: User.changeset()
@ -290,20 +272,14 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:ok, %User{}} <-
...> reset_user_password(user, %{
...> password: "new password",
...> password_confirmation: "new password"
...> }),
...> do: :passed
:passed
iex> reset_user_password(user, %{
...> password: "new password",
...> password_confirmation: "new password"
...> })
{:ok, %User{}}
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:error, %Changeset{}} <-
...> update_user_password(user, "invalid password", %{password: "123"}),
...> do: :passed
:passed
iex> update_user_password(user, "invalid password", %{password: "123"})
{:error, %Changeset{}}
"""
@spec update_user_password(User.t(), String.t(), attrs :: map()) ::
@ -329,8 +305,8 @@ defmodule Memex.Accounts do
## Examples
iex> with %Changeset{} <- change_user_locale(%User{}), do: :passed
:passed
iex> change_user_locale(%User{})
%Changeset{}
"""
@spec change_user_locale(User.t()) :: User.changeset()
@ -343,9 +319,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:ok, %User{}} <- update_user_locale(user, "en_US"), do: :passed
:passed
iex> update_user_locale(user, "en_US")
{:ok, %User{}}
"""
@spec update_user_locale(User.t(), locale :: String.t()) ::
@ -359,13 +334,11 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %User{} <- delete_user!(user, %User{id: 123, role: :admin}), do: :passed
:passed
iex> delete_user!(user, %User{id: 123, role: :admin})
%User{}
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %User{} <- delete_user!(user, user), do: :passed
:passed
iex> delete_user!(user, user)
%User{}
"""
@spec delete_user!(user_to_delete :: User.t(), User.t()) :: User.t()
@ -416,16 +389,26 @@ defmodule Memex.Accounts do
list_users_by_role(:admin) |> Enum.empty?()
end
@doc """
Returns an atom representing the current configured registration mode
"""
@spec registration_mode() :: :public | :invite_only
def registration_mode do
case Application.get_env(:memex, Memex.Accounts)[:registration] do
"public" -> :public
_other -> :invite_only
end
end
@doc """
Checks if user is an admin
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> is_admin?(user)
iex> is_admin?(%User{role: :admin})
true
iex> is_admin?(%User{id: Ecto.UUID.generate()})
iex> is_admin?(%User{})
false
"""
@ -439,8 +422,7 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> is_already_admin?(user)
iex> is_already_admin?(%User{role: :admin})
true
iex> is_already_admin?(%User{})
@ -458,15 +440,9 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, %{id: user_id} = user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %Oban.Job{
...> args: %{email: :welcome, user_id: ^user_id, attrs: %{url: "example url"}}
...> } <- deliver_user_confirmation_instructions(user, fn _token -> "example url" end),
...> do: :passed
:passed
iex> deliver_user_confirmation_instructions(user, fn _token -> "example url" end)
%Oban.Job{args: %{email: :welcome, user_id: ^user_id, attrs: %{url: "example url"}}}
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> user = user |> User.confirm_changeset() |> Repo.update!()
iex> deliver_user_confirmation_instructions(user, fn _token -> "example url" end)
{:error, :already_confirmed}
@ -514,12 +490,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, %{id: user_id} = user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with %Oban.Job{args: %{
...> email: :reset_password, user_id: ^user_id, attrs: %{url: "example url"}}
...> } <- deliver_user_reset_password_instructions(user, fn _token -> "example url" end),
...> do: :passed
:passed
iex> deliver_user_reset_password_instructions(user, fn _token -> "example url" end)
%Oban.Job{args: %{email: :reset_password, user_id: ^user_id, attrs: %{url: "example url"}}}
"""
@spec deliver_user_reset_password_instructions(User.t(), function()) :: Job.t()
@ -535,11 +507,8 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> {encoded_token, user_token} = UserToken.build_email_token(user, "reset_password")
iex> Repo.insert!(user_token)
iex> with %User{} <- get_user_by_reset_password_token(encoded_token), do: :passed
:passed
iex> get_user_by_reset_password_token(encoded_token)
%User{}
iex> get_user_by_reset_password_token("invalidtoken")
nil
@ -560,20 +529,14 @@ defmodule Memex.Accounts do
## Examples
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:ok, %User{}} <-
...> reset_user_password(user, %{
...> password: "new password",
...> password_confirmation: "new password"
...> }),
...> do: :passed
:passed
iex> reset_user_password(user, %{
...> password: "new password",
...> password_confirmation: "new password"
...> })
{:ok, %User{}}
iex> {:ok, user} = register_user(%{email: "foo@example.com", password: "valid_password"})
iex> with {:error, %Changeset{}} <-
...> reset_user_password(user, %{password: "valid", password_confirmation: "not the same"}),
...> do: :passed
:passed
iex> reset_user_password(user, %{password: "valid", password_confirmation: "not the same"})
{:error, %Changeset{}}
"""
@spec reset_user_password(User.t(), attrs :: map()) ::

View File

@ -100,13 +100,23 @@ defmodule Memex.Accounts.Invites do
end
end
@spec get_use_count(Invite.t(), User.t()) :: non_neg_integer()
def get_use_count(%Invite{id: invite_id}, %User{role: :admin}) do
Repo.one(
@spec get_use_count(Invite.t(), User.t()) :: non_neg_integer() | nil
def get_use_count(%Invite{id: invite_id} = invite, user) do
[invite] |> get_use_counts(user) |> Map.get(invite_id)
end
@spec get_use_counts([Invite.t()], User.t()) ::
%{optional(Invite.id()) => non_neg_integer()}
def get_use_counts(invites, %User{role: :admin}) do
invite_ids = invites |> Enum.map(fn %{id: invite_id} -> invite_id end)
Repo.all(
from u in User,
where: u.invite_id == ^invite_id,
select: count(u.id)
where: u.invite_id in ^invite_ids,
group_by: u.invite_id,
select: {u.invite_id, count(u.id)}
)
|> Map.new()
end
@spec decrement_invite_changeset(Invite.t()) :: Invite.changeset()

View File

@ -1,77 +0,0 @@
defmodule Memex.Accounts.UserNotifier do
@moduledoc """
Contains templates and messages for user messages
"""
# For simplicity, this module simply logs messages to the terminal.
# You should replace it by a proper email or notification tool, such as:
#
# * Swoosh - https://hexdocs.pm/swoosh
# * Bamboo - https://hexdocs.pm/bamboo
#
defp deliver(to, body) do
require Logger
Logger.debug(body)
{:ok, %{to: to, body: body}}
end
@doc """
Deliver instructions to confirm account.
"""
def deliver_confirmation_instructions(user, url) do
deliver(user.email, """
==============================
Hi #{user.email},
You can confirm your account by visiting the URL below:
#{url}
If you didn't create an account with us, please ignore this.
==============================
""")
end
@doc """
Deliver instructions to reset a user password.
"""
def deliver_reset_password_instructions(user, url) do
deliver(user.email, """
==============================
Hi #{user.email},
You can reset your password by visiting the URL below:
#{url}
If you didn't request this change, please ignore this.
==============================
""")
end
@doc """
Deliver instructions to update a user email.
"""
def deliver_update_email_instructions(user, url) do
deliver(user.email, """
==============================
Hi #{user.email},
You can change your email by visiting the URL below:
#{url}
If you didn't request this change, please ignore this.
==============================
""")
end
end

View File

@ -4,7 +4,7 @@ defmodule Memex.Application do
@moduledoc false
use Application
alias Memex.ErrorReporter
alias Memex.Logger
@impl true
def start(_type, _args) do
@ -33,7 +33,7 @@ defmodule Memex.Application do
[:oban, :job, :start],
[:oban, :job, :stop]
],
&ErrorReporter.handle_event/4,
&Logger.handle_event/4,
[]
)

View File

@ -27,7 +27,7 @@ defmodule Memex.Contexts.Context do
field :tags_string, :string, virtual: true
field :visibility, Ecto.Enum, values: [:public, :private, :unlisted]
belongs_to :user, User
field :user_id, :binary_id
timestamps()
end
@ -38,7 +38,6 @@ defmodule Memex.Contexts.Context do
tags: [String.t()] | nil,
tags_string: String.t() | nil,
visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(),
inserted_at: NaiveDateTime.t(),
updated_at: NaiveDateTime.t()

View File

@ -1,4 +1,4 @@
defmodule Memex.ErrorReporter do
defmodule Memex.Logger do
@moduledoc """
Custom logger for telemetry events
@ -12,41 +12,47 @@ defmodule Memex.ErrorReporter do
data =
get_oban_job_data(meta, measure)
|> Map.put(:stacktrace, Exception.format_stacktrace(stacktrace))
|> pretty_encode()
Logger.error(meta.reason, data: pretty_encode(data))
Logger.error(meta.reason, data: data)
end
def handle_event([:oban, :job, :start], measure, meta, _config) do
Logger.info("Started oban job", data: get_oban_job_data(meta, measure) |> pretty_encode())
data = get_oban_job_data(meta, measure) |> pretty_encode()
Logger.info("Started oban job", data: data)
end
def handle_event([:oban, :job, :stop], measure, meta, _config) do
Logger.info("Finished oban job", data: get_oban_job_data(meta, measure) |> pretty_encode())
data = get_oban_job_data(meta, measure) |> pretty_encode()
Logger.info("Finished oban job", data: data)
end
def handle_event([:oban, :job, unhandled_event], measure, meta, _config) do
data =
get_oban_job_data(meta, measure)
|> Map.put(:event, unhandled_event)
|> pretty_encode()
Logger.warning("Unhandled oban job event", data: pretty_encode(data))
Logger.warning("Unhandled oban job event", data: data)
end
def handle_event(unhandled_event, measure, meta, config) do
data = %{
event: unhandled_event,
meta: meta,
measurements: measure,
config: config
}
data =
pretty_encode(%{
event: unhandled_event,
meta: meta,
measurements: measure,
config: config
})
Logger.warning("Unhandled telemetry event", data: pretty_encode(data))
Logger.warning("Unhandled telemetry event", data: data)
end
defp get_oban_job_data(%{job: job}, measure) do
job
|> Map.take([:id, :args, :meta, :queue, :worker])
|> Map.merge(measure)
%{
job: job |> Map.take([:id, :args, :meta, :queue, :worker]),
measurements: measure
}
end
defp pretty_encode(data) do

View File

@ -26,7 +26,7 @@ defmodule Memex.Notes.Note do
field :tags_string, :string, virtual: true
field :visibility, Ecto.Enum, values: [:public, :private, :unlisted]
belongs_to :user, User
field :user_id, :binary_id
timestamps()
end
@ -37,7 +37,6 @@ defmodule Memex.Notes.Note do
tags: [String.t()] | nil,
tags_string: String.t() | nil,
visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(),
inserted_at: NaiveDateTime.t(),
updated_at: NaiveDateTime.t()

View File

@ -27,7 +27,7 @@ defmodule Memex.Pipelines.Pipeline do
field :tags_string, :string, virtual: true
field :visibility, Ecto.Enum, values: [:public, :private, :unlisted]
belongs_to :user, User
field :user_id, :binary_id
has_many :steps, Step, preload_order: [asc: :position]
@ -40,7 +40,6 @@ defmodule Memex.Pipelines.Pipeline do
tags: [String.t()] | nil,
tags_string: String.t() | nil,
visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(),
inserted_at: NaiveDateTime.t(),
updated_at: NaiveDateTime.t()

View File

@ -23,7 +23,7 @@ defmodule Memex.Pipelines.Steps.Step do
field :position, :integer
belongs_to :pipeline, Pipeline
belongs_to :user, User
field :user_id, :binary_id
timestamps()
end
@ -34,7 +34,6 @@ defmodule Memex.Pipelines.Steps.Step do
position: non_neg_integer(),
pipeline: Pipeline.t() | Ecto.Association.NotLoaded.t(),
pipeline_id: Pipeline.id(),
user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(),
inserted_at: NaiveDateTime.t(),
updated_at: NaiveDateTime.t()

View File

@ -45,8 +45,7 @@ defmodule MemexWeb do
def live_view do
quote do
use Phoenix.LiveView,
layout: {MemexWeb.LayoutView, "live.html"}
use Phoenix.LiveView, layout: {MemexWeb.LayoutView, :live}
on_mount MemexWeb.InitAssigns
unquote(view_helpers())
@ -93,10 +92,10 @@ defmodule MemexWeb do
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
use Phoenix.HTML
# Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc)
# Import LiveView and .heex helpers (live_render, link, <.form>, etc)
# Import basic rendering functionality (render, render_layout, etc)
import Phoenix.{Component, View}
import MemexWeb.{ErrorHelpers, Gettext, LiveHelpers, ViewHelpers}
import MemexWeb.{ErrorHelpers, Gettext, CoreComponents, ViewHelpers}
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
alias MemexWeb.Endpoint

View File

@ -1,44 +0,0 @@
defmodule MemexWeb.Components.ContextContent do
@moduledoc """
Display the content for a context
"""
use MemexWeb, :component
alias Memex.Contexts.Context
alias Phoenix.HTML
attr :context, Context, required: true
def context_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@context.content) %></p></div>
"""
end
defp add_links_to_content(content) do
Regex.replace(
~r/\[\[([\p{L}\p{N}\-]+)\]\]/,
content,
fn _whole_match, slug ->
link =
HTML.Link.link(
"[[#{slug}]]",
to: Routes.note_show_path(Endpoint, :show, slug),
class: "link inline",
data: [qa: "context-note-#{slug}"]
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">"
end
)
|> HTML.raw()
end
end

View File

@ -92,11 +92,7 @@ defmodule MemexWeb.Components.ContextsTableComponent do
assigns = %{slug: slug}
slug_block = ~H"""
<.link
navigate={Routes.context_show_path(Endpoint, :show, @slug)}
class="link"
data-qa={"context-show-#{@slug}"}
>
<.link navigate={Routes.context_show_path(Endpoint, :show, @slug)} class="link">
<%= @slug %>
</.link>
"""

View File

@ -0,0 +1,187 @@
defmodule MemexWeb.CoreComponents do
@moduledoc """
Provides core UI components.
"""
use Phoenix.Component
import MemexWeb.{Gettext, ViewHelpers}
alias Memex.{Accounts, Accounts.Invite, Accounts.User}
alias Memex.Contexts.Context
alias Memex.Notes.Note
alias Memex.Pipelines.Steps.Step
alias MemexWeb.{Endpoint, HomeLive}
alias MemexWeb.Router.Helpers, as: Routes
alias Phoenix.HTML
alias Phoenix.LiveView.JS
embed_templates("core_components/*")
attr :title_content, :string, default: nil
attr :current_user, User, default: nil
def topbar(assigns)
attr :return_to, :string, required: true
slot(:inner_block)
@doc """
Renders a live component inside a modal.
The rendered modal receives a `:return_to` option to properly update
the URL when the modal is closed.
## Examples
<.modal return_to={Routes.<%= schema.singular %>_index_path(Endpoint, :index)}>
<.live_component
module={<%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent}
id={@<%= schema.singular %>.id || :new}
title={@page_title}
action={@live_action}
return_to={Routes.<%= schema.singular %>_index_path(Endpoint, :index)}
<%= schema.singular %>: @<%= schema.singular %>
/>
</.modal>
"""
def modal(assigns)
defp hide_modal(js \\ %JS{}) do
js
|> JS.hide(to: "#modal", transition: "fade-out")
|> JS.hide(to: "#modal-bg", transition: "fade-out")
|> JS.hide(to: "#modal-content", transition: "fade-out-scale")
end
attr :action, :string, required: true
attr :value, :boolean, required: true
attr :id, :string, default: nil
slot(:inner_block)
@doc """
A toggle button element that can be directed to a liveview or a
live_component's `handle_event/3`.
## Examples
<.toggle_button action="my_liveview_action" value={@some_value}>
<span>Toggle me!</span>
</.toggle_button>
<.toggle_button action="my_live_component_action" target={@myself} value={@some_value}>
<span>Whatever you want</span>
</.toggle_button>
"""
def toggle_button(assigns)
attr :user, User, required: true
slot(:inner_block, required: true)
def user_card(assigns)
attr :invite, Invite, required: true
attr :use_count, :integer, default: nil
attr :current_user, User, required: true
slot(:inner_block)
slot(:code_actions)
def invite_card(assigns)
attr :id, :string, required: true
attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil"
@doc """
Phoenix.Component for a <time> element that renders the naivedatetime in the
user's local timezone
"""
def datetime(assigns)
@spec cast_datetime(NaiveDateTime.t() | nil) :: String.t()
defp cast_datetime(%NaiveDateTime{} = datetime) do
datetime |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(:extended)
end
defp cast_datetime(_datetime), do: ""
attr :id, :string, required: true
attr :date, :any, required: true, doc: "A `Date` struct or nil"
@doc """
Phoenix.Component for a <date> element that renders the Date in the user's
local timezone
"""
def date(assigns)
attr :content, :string, required: true
attr :filename, :string, default: "qrcode", doc: "filename without .png extension"
attr :image_class, :string, default: "w-64 h-max"
attr :width, :integer, default: 384, doc: "width of png to generate"
@doc """
Creates a downloadable QR Code element
"""
def qr_code(assigns)
attr :note, Note, required: true
def note_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@note.content, "note-link") %></p></div>
"""
end
attr :context, Context, required: true
def context_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@context.content, "context-note") %></p></div>
"""
end
attr :step, Step, required: true
def step_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@step.content, "step-context") %></p></div>
"""
end
defp add_links_to_content(content, data_qa_prefix) do
Regex.replace(
~r/\[\[([\p{L}\p{N}\-]+)\]\]/,
content,
fn _whole_match, slug ->
link =
HTML.Link.link(
"[[#{slug}]]",
to: Routes.note_show_path(Endpoint, :show, slug),
class: "link inline",
data: [qa: "#{data_qa_prefix}-#{slug}"]
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">"
end
)
|> HTML.raw()
end
end

View File

@ -0,0 +1,3 @@
<time :if={@date} id={@id} datetime={Date.to_iso8601(@date, :extended)} phx-hook="Date">
<%= Date.to_iso8601(@date, :extended) %>
</time>

View File

@ -0,0 +1,3 @@
<time :if={@datetime} id={@id} datetime={cast_datetime(@datetime)} phx-hook="DateTime">
<%= cast_datetime(@datetime) %>
</time>

View File

@ -0,0 +1,48 @@
<div class="px-8 py-4 flex flex-col justify-center items-center space-y-4
bg-primary-900
border border-gray-400 rounded-lg shadow-lg hover:shadow-md
transition-all duration-300 ease-in-out">
<h1 class="title text-xl">
<%= @invite.name %>
</h1>
<%= if @invite.disabled_at |> is_nil() do %>
<h2 class="title text-md">
<%= if @invite.uses_left do %>
<%= gettext(
"uses left: %{uses_left_count}",
uses_left_count: @invite.uses_left
) %>
<% else %>
<%= gettext("uses left: unlimited") %>
<% end %>
</h2>
<% else %>
<h2 class="title text-md">
<%= gettext("invite disabled") %>
</h2>
<% end %>
<.qr_code
content={Routes.user_registration_url(Endpoint, :new, invite: @invite.token)}
filename={@invite.name}
/>
<h2 :if={@use_count && @use_count != 0} class="title text-md">
<%= gettext("uses: %{uses_count}", uses_count: @use_count) %>
</h2>
<div class="flex flex-row flex-wrap justify-center items-center">
<code
id={"code-#{@invite.id}"}
class="mx-2 my-1 text-xs px-4 py-2 rounded-lg text-center break-all
text-primary-400 bg-primary-800"
phx-no-format
><%= Routes.user_registration_url(Endpoint, :new, invite: @invite.token) %></code>
<%= if @code_actions, do: render_slot(@code_actions) %>
</div>
<div :if={@inner_block} class="flex space-x-4 justify-center items-center">
<%= render_slot(@inner_block) %>
</div>
</div>

View File

@ -0,0 +1,41 @@
<.link
id="modal-bg"
patch={@return_to}
class="fade-in fixed z-10 left-0 top-0
w-full h-full overflow-hidden
p-8 flex flex-col justify-center items-center cursor-auto"
style="background-color: rgba(0,0,0,0.4);"
phx-remove={hide_modal()}
>
<span class="hidden"></span>
</.link>
<div
id="modal"
class="fixed z-10 left-0 top-0 pointer-events-none
w-full h-full overflow-hidden
p-4 sm:p-8 flex flex-col justify-center items-center"
>
<div
id="modal-content"
class="fade-in-scale max-w-3xl max-h-3xl relative w-full
pointer-events-auto overflow-hidden
px-8 py-4 sm:py-8 flex flex-col justify-start items-stretch
bg-primary-800 text-primary-400 border-primary-900 border-2 rounded-lg"
>
<.link
patch={@return_to}
id="close"
class="absolute top-8 right-10
text-gray-500 hover:text-gray-800
transition-all duration-500 ease-in-out"
phx-remove={hide_modal()}
>
<i class="fa-fw fa-lg fas fa-times"></i>
</.link>
<div class="overflow-x-hidden overflow-y-auto w-full p-8 flex flex-col space-y-4 justify-start items-stretch">
<%= render_slot(@inner_block) %>
</div>
</div>
</div>

View File

@ -0,0 +1,3 @@
<a href={qr_code_image(@content)} download={@filename <> ".png"}>
<img class={@image_class} alt={@filename} src={qr_code_image(@content)} />
</a>

View File

@ -0,0 +1,30 @@
<label for={@id || @action} class="inline-flex relative items-center cursor-pointer">
<input
id={@id || @action}
type="checkbox"
value={@value}
checked={@value}
class="sr-only peer"
aria-labelledby={"#{@id || @action}-label"}
{
if assigns |> Map.has_key?(:target),
do: %{"phx-click": @action, "phx-value-value": @value, "phx-target": @target},
else: %{"phx-click": @action, "phx-value-value": @value}
}
/>
<div class="w-11 h-6 bg-gray-300 rounded-full peer
peer-focus:ring-4 peer-focus:ring-teal-300 dark:peer-focus:ring-teal-800
peer-checked:bg-gray-600
peer-checked:after:translate-x-full peer-checked:after:border-white
after:content-[''] after:absolute after:top-1 after:left-[2px] after:bg-white after:border-gray-300
after:border after:rounded-full after:h-5 after:w-5
after:transition-all after:duration-250 after:ease-in-out
transition-colors duration-250 ease-in-out">
</div>
<span
id={"#{@id || @action}-label"}
class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300"
>
<%= render_slot(@inner_block) %>
</span>
</label>

View File

@ -0,0 +1,113 @@
<nav role="navigation" class="mb-8 px-8 py-4 w-full bg-primary-900 text-primary-400">
<div class="flex flex-col sm:flex-row justify-between items-center">
<div class="mb-4 sm:mb-0 sm:mr-8 flex flex-row justify-start items-center space-x-2">
<.link
navigate={Routes.live_path(Endpoint, HomeLive)}
class="mx-2 my-1 leading-5 text-xl text-primary-400 hover:underline"
>
<%= gettext("memEx") %>
</.link>
<%= if @title_content do %>
<span class="mx-2 my-1">
|
</span>
<%= @title_content %>
<% end %>
</div>
<hr class="mb-2 sm:hidden hr-light" />
<ul class="flex flex-row flex-wrap justify-center items-center
text-lg text-primary-400 text-ellipsis">
<li class="mx-2 my-1">
<.link
navigate={Routes.note_index_path(Endpoint, :index)}
class="text-primary-400 hover:underline truncate"
>
<%= gettext("notes") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.context_index_path(Endpoint, :index)}
class="text-primary-400 hover:underline truncate"
>
<%= gettext("contexts") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.pipeline_index_path(Endpoint, :index)}
class="text-primary-400 hover:underline truncate"
>
<%= gettext("pipelines") %>
</.link>
</li>
<li class="mx-2 my-1 border-left border border-primary-700"></li>
<%= if @current_user do %>
<li :if={@current_user |> Accounts.is_already_admin?()} class="mx-2 my-1">
<.link
navigate={Routes.invite_index_path(Endpoint, :index)}
class="text-primary-400 hover:underline"
>
<%= gettext("invites") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.user_settings_path(Endpoint, :edit)}
class="text-primary-400 hover:underline truncate"
>
<%= @current_user.email %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
href={Routes.user_session_path(Endpoint, :delete)}
method="delete"
data-confirm={dgettext("prompts", "are you sure you want to log out?")}
>
<i class="fas fa-sign-out-alt"></i>
</.link>
</li>
<li
:if={
@current_user.role == :admin and function_exported?(Routes, :live_dashboard_path, 2)
}
class="mx-2 my-1"
>
<.link
navigate={Routes.live_dashboard_path(Endpoint, :home)}
class="text-primary-400 hover:underline"
>
<i class="fas fa-gauge"></i>
</.link>
</li>
<% else %>
<li :if={Accounts.allow_registration?()} class="mx-2 my-1">
<.link
href={Routes.user_registration_path(Endpoint, :new)}
class="text-primary-400 hover:underline truncate"
>
<%= dgettext("actions", "register") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
href={Routes.user_session_path(Endpoint, :new)}
class="text-primary-400 hover:underline truncate"
>
<%= dgettext("actions", "log in") %>
</.link>
</li>
<% end %>
</ul>
</div>
</nav>

View File

@ -0,0 +1,37 @@
<div
id={"user-#{@user.id}"}
class="px-8 py-4 flex flex-col justify-center items-center text-center
bg-primary-900
border border-gray-400 rounded-lg shadow-lg hover:shadow-md
transition-all duration-300 ease-in-out"
>
<h1 class="px-4 py-2 rounded-lg title text-xl break-all">
<%= @user.email %>
</h1>
<h3 class="px-4 py-2 rounded-lg title text-lg">
<p>
<%= if @user.confirmed_at do %>
<%= gettext(
"user confirmed on%{confirmed_datetime}",
confirmed_datetime: ""
) %>
<.datetime id={"#{@user.id}-confirmed-at"} datetime={@user.confirmed_at} />
<% else %>
<%= gettext("email unconfirmed") %>
<% end %>
</p>
<p>
<%= gettext(
"user registered on%{registered_datetime}",
registered_datetime: ""
) %>
<.datetime id={"#{@user.id}-inserted-at"} datetime={@user.inserted_at} />
</p>
</h3>
<div :if={@inner_block} class="px-4 py-2 flex space-x-4 justify-center items-center">
<%= render_slot(@inner_block) %>
</div>
</div>

View File

@ -1,70 +0,0 @@
defmodule MemexWeb.Components.InviteCard do
@moduledoc """
Display card for an invite
"""
use MemexWeb, :component
alias Memex.Accounts.{Invite, Invites, User}
alias MemexWeb.Endpoint
attr :invite, Invite, required: true
attr :current_user, User, required: true
slot(:inner_block)
slot(:code_actions)
def invite_card(%{invite: invite, current_user: current_user} = assigns) do
assigns =
assigns
|> assign(:use_count, Invites.get_use_count(invite, current_user))
|> assign_new(:code_actions, fn -> [] end)
~H"""
<div class="mx-4 my-2 px-8 py-4 flex flex-col justify-center items-center space-y-4
border border-gray-400 rounded-lg shadow-lg hover:shadow-md
transition-all duration-300 ease-in-out">
<h1 class="title text-xl">
<%= @invite.name %>
</h1>
<%= if @invite.disabled_at |> is_nil() do %>
<h2 class="title text-md">
<%= if @invite.uses_left do %>
<%= gettext(
"uses left: %{uses_left_count}",
uses_left_count: @invite.uses_left
) %>
<% else %>
<%= gettext("uses left: unlimited") %>
<% end %>
</h2>
<% else %>
<h2 class="title text-md">
<%= gettext("invite disabled") %>
</h2>
<% end %>
<.qr_code
content={Routes.user_registration_url(Endpoint, :new, invite: @invite.token)}
filename={@invite.name}
/>
<h2 :if={@use_count != 0} class="title text-md">
<%= gettext("uses: %{uses_count}", uses_count: @use_count) %>
</h2>
<div class="flex flex-row flex-wrap justify-center items-center">
<code
id={"code-#{@invite.id}"}
class="mx-2 my-1 text-xs px-4 py-2 rounded-lg text-center break-all text-gray-100 bg-primary-800"
phx-no-format
><%= Routes.user_registration_url(Endpoint, :new, invite: @invite.token) %></code>
<%= render_slot(@code_actions) %>
</div>
<div :if={@inner_block} class="flex space-x-4 justify-center items-center">
<%= render_slot(@inner_block) %>
</div>
</div>
"""
end
end

View File

@ -1,44 +0,0 @@
defmodule MemexWeb.Components.NoteContent do
@moduledoc """
Display the content for a note
"""
use MemexWeb, :component
alias Memex.Notes.Note
alias Phoenix.HTML
attr :note, Note, required: true
def note_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@note.content) %></p></div>
"""
end
defp add_links_to_content(content) do
Regex.replace(
~r/\[\[([\p{L}\p{N}\-]+)\]\]/,
content,
fn _whole_match, slug ->
link =
HTML.Link.link(
"[[#{slug}]]",
to: Routes.note_show_path(Endpoint, :show, slug),
class: "link inline",
data: [qa: "note-link-#{slug}"]
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">"
end
)
|> HTML.raw()
end
end

View File

@ -92,11 +92,7 @@ defmodule MemexWeb.Components.NotesTableComponent do
assigns = %{slug: slug}
slug_block = ~H"""
<.link
navigate={Routes.note_show_path(Endpoint, :show, @slug)}
class="link"
data-qa={"note-show-#{@slug}"}
>
<.link navigate={Routes.note_show_path(Endpoint, :show, @slug)} class="link">
<%= @slug %>
</.link>
"""

View File

@ -93,11 +93,7 @@ defmodule MemexWeb.Components.PipelinesTableComponent do
assigns = %{slug: slug}
slug_block = ~H"""
<.link
navigate={Routes.pipeline_show_path(Endpoint, :show, @slug)}
class="link"
data-qa={"pipeline-show-#{@slug}"}
>
<.link navigate={Routes.pipeline_show_path(Endpoint, :show, @slug)} class="link">
<%= @slug %>
</.link>
"""

View File

@ -1,44 +0,0 @@
defmodule MemexWeb.Components.StepContent do
@moduledoc """
Display the content for a step
"""
use MemexWeb, :component
alias Memex.Pipelines.Steps.Step
alias Phoenix.HTML
attr :step, Step, required: true
def step_content(assigns) do
~H"""
<div
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"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><p class="inline"><%= add_links_to_content(@step.content) %></p></div>
"""
end
defp add_links_to_content(content) do
Regex.replace(
~r/\[\[([\p{L}\p{N}\-]+)\]\]/,
content,
fn _whole_match, slug ->
link =
HTML.Link.link(
"[[#{slug}]]",
to: Routes.context_show_path(Endpoint, :show, slug),
class: "link inline",
data: [qa: "step-context-#{slug}"]
)
|> HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
"</p>#{link}<p class=\"inline\">"
end
)
|> HTML.raw()
end
end

View File

@ -33,7 +33,8 @@ defmodule MemexWeb.Components.TableComponent do
optional(:class) => String.t(),
optional(:row_class) => String.t(),
optional(:alternate_row_class) => String.t(),
optional(:sortable) => false
optional(:sortable) => false,
optional(:type) => module()
}),
required(:rows) =>
list(%{
@ -60,7 +61,8 @@ defmodule MemexWeb.Components.TableComponent do
:asc
end
rows = rows |> sort_by_custom_sort_value_or_value(initial_key, initial_sort_mode)
type = columns |> Enum.find(%{}, fn %{key: key} -> key == initial_key end) |> Map.get(:type)
rows = rows |> sort_by_custom_sort_value_or_value(initial_key, initial_sort_mode, type)
socket =
socket
@ -68,6 +70,7 @@ defmodule MemexWeb.Components.TableComponent do
|> assign(
columns: columns,
rows: rows,
key: initial_key,
last_sort_key: initial_key,
sort_mode: initial_sort_mode
)
@ -81,7 +84,14 @@ defmodule MemexWeb.Components.TableComponent do
def handle_event(
"sort_by",
%{"sort-key" => key},
%{assigns: %{rows: rows, last_sort_key: last_sort_key, sort_mode: sort_mode}} = socket
%{
assigns: %{
columns: columns,
rows: rows,
last_sort_key: last_sort_key,
sort_mode: sort_mode
}
} = socket
) do
key = key |> String.to_existing_atom()
@ -92,11 +102,28 @@ defmodule MemexWeb.Components.TableComponent do
{_new_sort_key, _last_sort_mode} -> :asc
end
rows = rows |> sort_by_custom_sort_value_or_value(key, sort_mode)
type =
columns |> Enum.find(%{}, fn %{key: column_key} -> column_key == key end) |> Map.get(:type)
rows = rows |> sort_by_custom_sort_value_or_value(key, sort_mode, type)
{:noreply, socket |> assign(last_sort_key: key, sort_mode: sort_mode, rows: rows)}
end
defp sort_by_custom_sort_value_or_value(rows, key, sort_mode) do
defp sort_by_custom_sort_value_or_value(rows, key, sort_mode, type)
when type in [Date, DateTime] do
rows
|> Enum.sort_by(
fn row ->
case row |> Map.get(key) do
{custom_sort_key, _value} -> custom_sort_key
value -> value
end
end,
{sort_mode, type}
)
end
defp sort_by_custom_sort_value_or_value(rows, key, sort_mode, _type) do
rows
|> Enum.sort_by(
fn row ->

View File

@ -11,7 +11,8 @@
phx-value-sort-key={key}
phx-target={@myself}
>
<span><%= label %></span>
<i class="w-0 float-right fas fa-sm fa-chevron-up opacity-0"></i>
<span class={if @last_sort_key == key, do: "underline"}><%= label %></span>
<%= if @last_sort_key == key do %>
<%= case @sort_mode do %>
<% :asc -> %>
@ -25,7 +26,7 @@
</span>
</th>
<% else %>
<th class={["p-2", column[:class]]}>
<th class={["p-2 cursor-not-allowed", column[:class]]}>
<%= label %>
</th>
<% end %>

View File

@ -1,133 +0,0 @@
defmodule MemexWeb.Components.Topbar do
@moduledoc """
Component that renders a topbar with user functions/links
"""
use MemexWeb, :component
alias Memex.Accounts
alias MemexWeb.HomeLive
def topbar(assigns) do
assigns =
%{results: [], title_content: nil, flash: nil, current_user: nil} |> Map.merge(assigns)
~H"""
<nav role="navigation" class="mb-8 px-8 py-4 w-full bg-primary-900 text-primary-400">
<div class="flex flex-col sm:flex-row justify-between items-center">
<div class="mb-4 sm:mb-0 sm:mr-8 flex flex-row justify-start items-center space-x-2">
<.link
navigate={Routes.live_path(Endpoint, HomeLive)}
class="mx-2 my-1 leading-5 text-xl text-primary-400 hover:underline"
>
<%= gettext("memEx") %>
</.link>
<%= if @title_content do %>
<span class="mx-2 my-1">
|
</span>
<%= @title_content %>
<% end %>
</div>
<hr class="mb-2 sm:hidden hr-light" />
<ul class="flex flex-row flex-wrap justify-center items-center
text-lg text-primary-400 text-ellipsis">
<li class="mx-2 my-1">
<.link
navigate={Routes.note_index_path(Endpoint, :index)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= gettext("notes") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.context_index_path(Endpoint, :index)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= gettext("contexts") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.pipeline_index_path(Endpoint, :index)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= gettext("pipelines") %>
</.link>
</li>
<li class="mx-2 my-1 border-left border border-primary-700"></li>
<%= if @current_user do %>
<li :if={@current_user |> Accounts.is_already_admin?()} class="mx-2 my-1">
<.link
navigate={Routes.invite_index_path(Endpoint, :index)}
class="text-primary-400 text-primary-400 hover:underline"
>
<%= gettext("invites") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.user_settings_path(Endpoint, :edit)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= @current_user.email %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
href={Routes.user_session_path(Endpoint, :delete)}
method="delete"
data-confirm={dgettext("prompts", "are you sure you want to log out?")}
>
<i class="fas fa-sign-out-alt"></i>
</.link>
</li>
<li
:if={
@current_user.role == :admin and function_exported?(Routes, :live_dashboard_path, 2)
}
class="mx-2 my-1"
>
<.link
navigate={Routes.live_dashboard_path(Endpoint, :home)}
class="text-primary-400 text-primary-400 hover:underline"
>
<i class="fas fa-gauge"></i>
</.link>
</li>
<% else %>
<li :if={Accounts.allow_registration?()} class="mx-2 my-1">
<.link
navigate={Routes.user_registration_path(Endpoint, :new)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= dgettext("actions", "register") %>
</.link>
</li>
<li class="mx-2 my-1">
<.link
navigate={Routes.user_session_path(Endpoint, :new)}
class="text-primary-400 text-primary-400 hover:underline truncate"
>
<%= dgettext("actions", "log in") %>
</.link>
</li>
<% end %>
</ul>
</div>
</nav>
"""
end
end

View File

@ -1,48 +0,0 @@
defmodule MemexWeb.Components.UserCard do
@moduledoc """
Display card for a user
"""
use MemexWeb, :component
def user_card(assigns) do
~H"""
<div
id={"user-#{@user.id}"}
class="mx-4 my-2 px-8 py-4 flex flex-col justify-center items-center text-center
border border-gray-400 rounded-lg shadow-lg hover:shadow-md
transition-all duration-300 ease-in-out"
>
<h1 class="px-4 py-2 rounded-lg title text-xl break-all">
<%= @user.email %>
</h1>
<h3 class="px-4 py-2 rounded-lg title text-lg">
<p>
<%= if @user.confirmed_at do %>
<%= gettext(
"user confirmed on%{confirmed_datetime}",
confirmed_datetime: ""
) %>
<.datetime datetime={@user.confirmed_at} />
<% else %>
<%= gettext("email unconfirmed") %>
<% end %>
</p>
<p>
<%= gettext(
"user registered on%{registered_datetime}",
registered_datetime: ""
) %>
<.datetime datetime={@user.inserted_at} />
</p>
</h3>
<div :if={@inner_block} class="px-4 py-2 flex space-x-4 justify-center items-center">
<%= render_slot(@inner_block) %>
</div>
</div>
"""
end
end

View File

@ -2,7 +2,7 @@ defmodule MemexWeb.UserRegistrationController do
use MemexWeb, :controller
import MemexWeb.Gettext
alias Memex.{Accounts, Accounts.Invites}
alias MemexWeb.{Endpoint, HomeLive}
alias MemexWeb.HomeLive
def new(conn, %{"invite" => invite_token}) do
if Invites.valid_invite_token?(invite_token) do

View File

@ -59,7 +59,6 @@ defmodule MemexWeb.ContextLive.Index do
{:noreply, socket}
end
@impl true
def handle_event("search", %{"search" => %{"search_term" => ""}}, socket) do
{:noreply, socket |> push_patch(to: Routes.context_index_path(Endpoint, :index))}
end

View File

@ -5,7 +5,8 @@
<.form
:let={f}
for={:search}
for={%{}}
as={:search}
phx-change="search"
phx-submit="search"
class="self-stretch flex flex-col items-stretch"
@ -33,7 +34,7 @@
<.link
:if={is_owner?(context, @current_user)}
patch={Routes.context_index_path(@socket, :edit, context.slug)}
data-qa={"context-edit-#{context.id}"}
aria-label={dgettext("actions", "edit %{context_slug}", context_slug: context.slug)}
>
<%= dgettext("actions", "edit") %>
</.link>
@ -43,7 +44,7 @@
phx-click="delete"
phx-value-id={context.id}
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-context-#{context.id}"}
aria-label={dgettext("actions", "delete %{context_slug}", context_slug: context.slug)}
>
<%= dgettext("actions", "delete") %>
</.link>

View File

@ -1,6 +1,5 @@
defmodule MemexWeb.ContextLive.Show do
use MemexWeb, :live_view
import MemexWeb.Components.ContextContent
alias Memex.{Accounts.User, Contexts, Contexts.Context}
@impl true

View File

@ -36,7 +36,7 @@
class="btn btn-primary"
phx-click="delete"
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-context-#{@context.id}"}
aria-label={dgettext("actions", "delete %{context_slug}", context_slug: @context.slug)}
>
<%= dgettext("actions", "delete") %>
</button>

View File

@ -1,5 +1,5 @@
<div class="mx-auto flex flex-col justify-center items-stretch space-y-8 text-center max-w-3xl">
<h1 class="title text-primary-400 text-2xl">
<h1 class="title text-primary-400 text-xl text-left">
<%= gettext("faq") %>
</h1>
@ -7,16 +7,13 @@
<ul class="flex flex-col justify-center items-stretch space-y-8">
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("what is this?") %>
</b>
<p>
<%= gettext(
"this is a memex, used to document not just your notes, but also your perspectives and processes."
) %>
</p>
<p>
<%= gettext("some things that this memex is very loosely inspired by:") %>
</p>
@ -55,20 +52,16 @@
</li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("why split up into notes, contexts and pipelines?") %>
</b>
<p>
<%= gettext(
"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."
) %>
</p>
<p>
<%= gettext(
"i wanted to separate between a personal dictionary of concepts and then my thought processes that are built off of my experiences and life lessons. these are notes, and contexts, respectively."
) %>
</p>
<p>
<%= gettext(
"finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
) %>
@ -76,15 +69,13 @@
</li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("what should my notes be like?") %>
</b>
<p>
<%= gettext(
"in my opinion, notes should be written by any of the discrete objects or concepts that are meaningful to you in your life."
) %>
</p>
<p>
<%= gettext(
"spoons? probably not. a particular brand of spoons that you really like? why not :)"
) %>
@ -92,13 +83,11 @@
</li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("what should my contexts be like?") %>
</b>
<p>
<%= gettext("in my opinion, contexts should be like single-topic blog posts.") %>
</p>
<p>
<%= 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."
) %>
@ -106,15 +95,13 @@
</li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("what should my pipelines be like?") %>
</b>
<p>
<%= gettext(
"in my opinion, pipelines should be pretty lightweight, and just backlink to contexts to provide most of the heavy lifting."
) %>
</p>
<p>
<%= 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."
) %>
@ -122,20 +109,16 @@
</li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<b class="whitespace-nowrap text-left">
<%= gettext("how many people should i invite?") %>
</b>
<p>
<%= gettext(
"while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
) %>
</p>
<p>
<%= gettext(
"note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
) %>
</p>
<p>
<%= 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 :)"
) %>

View File

@ -5,7 +5,7 @@ defmodule MemexWeb.HomeLive do
use MemexWeb, :live_view
alias Memex.Accounts
alias MemexWeb.{Endpoint, FaqLive}
alias MemexWeb.FaqLive
@version Mix.Project.config()[:version]

View File

@ -1,11 +1,9 @@
<div class="mx-auto flex flex-col justify-center items-stretch space-y-4 max-w-3xl">
<h1 class="title text-primary-400 text-2xl text-center">
<div class="mx-auto flex flex-col justify-center items-stretch space-y-4 max-w-lg">
<h1 class="title text-primary-400 text-xl">
<%= gettext("memEx") %>
</h1>
<hr class="hr" />
<ul class="flex flex-col space-y-4 text-center">
<ul class="flex flex-col space-y-4">
<li class="flex flex-col justify-center items-center space-y-2">
<b class="whitespace-nowrap">
<%= gettext("notes:") %>
@ -33,11 +31,8 @@
</p>
</li>
<li class="flex flex-col justify-center items-center space-y-2">
<.link
navigate={Routes.live_path(Endpoint, FaqLive)}
class="link title text-primary-400 text-lg"
>
<li class="flex flex-col justify-center items-center text-right space-y-2">
<.link navigate={Routes.live_path(Endpoint, FaqLive)} class="btn btn-primary">
<%= gettext("read more on how to use memEx") %>
</.link>
</li>
@ -45,7 +40,7 @@
<hr class="hr" />
<ul class="flex flex-col space-y-4 text-center">
<ul class="flex flex-col space-y-4">
<h2 class="title text-primary-400 text-lg">
<%= gettext("features") %>
</h2>
@ -80,41 +75,39 @@
<hr class="hr" />
<ul class="flex flex-col space-y-4 text-center">
<ul class="flex flex-col justify-center space-y-4">
<h2 class="title text-primary-400 text-lg">
<%= gettext("instance information") %>
</h2>
<li class="flex flex-col justify-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<b>
<%= gettext("admins:") %>
</b>
<p>
<p class="flex flex-col justify-center items-center space-y-2">
<%= if @admins |> Enum.empty?() do %>
<.link href={Routes.user_registration_path(Endpoint, :new)} class="link">
<%= dgettext("prompts", "register to setup memEx") %>
</.link>
<% else %>
<div class="flex flex-wrap justify-center space-x-2">
<a :for={%{email: email} <- @admins} class="link" href={"mailto:#{email}"}>
<%= email %>
</a>
</div>
<.link :for={%{email: email} <- @admins} class="link" href={"mailto:#{email}"}>
<%= email %>
</.link>
<% end %>
</p>
</li>
<li class="flex flex-row justify-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<b><%= gettext("registration:") %></b>
<p>
<%= case Application.get_env(:memex, Memex.Accounts)[:registration] do
"public" -> gettext("public signups")
_ -> gettext("invite only")
<%= case Accounts.registration_mode() do
:public -> gettext("public signups")
:invite_only -> gettext("invite only")
end %>
</p>
</li>
<li class="flex flex-row justify-center items-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<b><%= gettext("version:") %></b>
<.link
href="https://gitea.bubbletea.dev/shibao/memEx/src/branch/stable/changelog.md"
@ -130,12 +123,12 @@
<hr class="hr" />
<ul class="flex flex-col space-y-2 text-center justify-center">
<ul class="flex flex-col space-y-2">
<h2 class="title text-primary-400 text-lg">
<%= gettext("get involved!") %>
<%= gettext("get involved") %>
</h2>
<li class="flex flex-col justify-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<.link
href="https://gitea.bubbletea.dev/shibao/memEx"
class="flex flex-row justify-center items-center space-x-2 link"
@ -146,7 +139,7 @@
<i class="fas fa-md fa-code"></i>
</.link>
</li>
<li class="flex flex-col justify-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<.link
href="https://weblate.bubbletea.dev/engage/memEx"
class="flex flex-row justify-center items-center space-x-2 link"
@ -157,7 +150,7 @@
<i class="fas fa-md fa-language"></i>
</.link>
</li>
<li class="flex flex-col justify-center space-x-2">
<li class="flex flex-col justify-center items-center space-y-2">
<.link
href="https://gitea.bubbletea.dev/shibao/memEx/issues/new"
class="flex flex-row justify-center items-center space-x-2 link"

View File

@ -18,13 +18,16 @@
<%= changeset_errors(@changeset) %>
</div>
<%= label(f, :name, gettext("Name"), class: "title text-lg text-primary-400") %>
<%= label(f, :name, gettext("name"), class: "title text-lg text-primary-400") %>
<%= text_input(f, :name, class: "input input-primary col-span-2") %>
<%= error_tag(f, :name, "col-span-3") %>
<%= label(f, :uses_left, gettext("Uses left"), class: "title text-lg text-primary-400") %>
<%= label(f, :uses_left, gettext("uses left"), class: "title text-lg text-primary-400") %>
<%= number_input(f, :uses_left, min: 0, class: "input input-primary col-span-2") %>
<%= error_tag(f, :uses_left, "col-span-3") %>
<span class="col-span-3 text-primary-500 italic text-center">
<%= gettext(~s/Leave "Uses left" blank to make invite unlimited/) %>
</span>
<%= submit(dgettext("actions", "Save"),
class: "mx-auto btn btn-primary col-span-3",

View File

@ -4,10 +4,9 @@ defmodule MemexWeb.InviteLive.Index do
"""
use MemexWeb, :live_view
import MemexWeb.Components.{InviteCard, UserCard}
alias Memex.Accounts
alias Memex.Accounts.{Invite, Invites}
alias MemexWeb.{Endpoint, HomeLive}
alias MemexWeb.HomeLive
alias Phoenix.LiveView.JS
@impl true
@ -123,13 +122,11 @@ defmodule MemexWeb.InviteLive.Index do
{:noreply, socket}
end
@impl true
def handle_event("copy_to_clipboard", _params, socket) do
prompt = dgettext("prompts", "copied to clipboard")
{:noreply, socket |> put_flash(:info, prompt)}
end
@impl true
def handle_event(
"delete_user",
%{"id" => id},
@ -151,7 +148,9 @@ defmodule MemexWeb.InviteLive.Index do
|> Map.get(:admin, [])
|> Enum.reject(fn %{id: user_id} -> user_id == current_user.id end)
use_counts = invites |> Invites.get_use_counts(current_user)
users = all_users |> Map.get(:user, [])
socket |> assign(invites: invites, admins: admins, users: users)
socket |> assign(invites: invites, use_counts: use_counts, admins: admins, users: users)
end
end

View File

@ -1,5 +1,5 @@
<div class="w-full flex flex-col space-y-8 justify-center items-center">
<h1 class="title text-2xl title-primary-500">
<div class="mx-auto flex flex-col justify-center items-stretch space-y-4 max-w-3xl">
<h1 class="title text-xl title-primary-500">
<%= gettext("invites") %>
</h1>
@ -11,29 +11,35 @@
<.link patch={Routes.invite_index_path(Endpoint, :new)} class="btn btn-primary">
<%= dgettext("actions", "invite someone new!") %>
</.link>
<% else %>
<.link patch={Routes.invite_index_path(Endpoint, :new)} class="btn btn-primary">
<%= dgettext("actions", "create invite") %>
</.link>
<% end %>
<div class="w-full flex flex-row flex-wrap justify-center items-center">
<.invite_card :for={invite <- @invites} invite={invite} current_user={@current_user}>
<div class="flex flex-col justify-center items-stretch space-y-4">
<.invite_card
:for={invite <- @invites}
invite={invite}
current_user={@current_user}
use_count={Map.get(@use_counts, invite.id)}
>
<:code_actions>
<form phx-submit="copy_to_clipboard">
<button
type="submit"
class="mx-2 my-1 btn btn-primary"
class="mx-2 my-1 btn btn-secondary"
phx-click={JS.dispatch("memex:clipcopy", to: "#code-#{invite.id}")}
aria-label={
dgettext("actions", "copy invite link for %{invite_name}", invite_name: invite.name)
}
>
<%= dgettext("actions", "Copy to clipboard") %>
<%= dgettext("actions", "copy") %>
</button>
</form>
</:code_actions>
<.link
patch={Routes.invite_index_path(Endpoint, :edit, invite)}
class="text-primary-400 link"
data-qa={"edit-#{invite.id}"}
aria-label={
dgettext("actions", "edit invite for %{invite_name}", invite_name: invite.name)
}
>
<i class="fa-fw fa-lg fas fa-edit"></i>
</.link>
@ -48,24 +54,26 @@
invite_name: invite.name
)
}
data-qa={"delete-#{invite.id}"}
aria-label={
dgettext("actions", "delete invite for %{invite_name}", invite_name: invite.name)
}
>
<i class="fa-fw fa-lg fas fa-trash"></i>
</.link>
<a
<.link
href="#"
class="btn btn-primary"
class="btn btn-secondary"
phx-click={if invite.disabled_at, do: "enable_invite", else: "disable_invite"}
phx-value-id={invite.id}
>
<%= if invite.disabled_at, do: gettext("enable"), else: gettext("disable") %>
</a>
</.link>
<a
<.link
:if={invite.disabled_at |> is_nil() and not (invite.uses_left |> is_nil())}
href="#"
class="btn btn-primary"
class="btn btn-secondary"
phx-click="set_unlimited"
phx-value-id={invite.id}
data-confirm={
@ -75,18 +83,26 @@
}
>
<%= gettext("set unlimited") %>
</a>
</.link>
</.invite_card>
<.link
:if={@invites != []}
patch={Routes.invite_index_path(Endpoint, :new)}
class="btn btn-primary ml-auto"
>
<%= dgettext("actions", "create invite") %>
</.link>
</div>
<%= unless @admins |> Enum.empty?() do %>
<hr class="hr" />
<h1 class="title text-2xl text-primary-400">
<%= gettext("Admins") %>
<h1 class="title text-xl text-primary-400">
<%= gettext("admins") %>
</h1>
<div class="w-full flex flex-row flex-wrap justify-center items-center">
<div class="flex flex-col justify-center items-stretch space-y-4">
<.user_card :for={admin <- @admins} user={admin}>
<.link
href="#"
@ -96,7 +112,7 @@
data-confirm={
dgettext(
"prompts",
"are you sure you want to delete %{email}? This action is permanent!",
"are you sure you want to delete %{email}? this action is permanent!",
email: admin.email
)
}
@ -110,11 +126,11 @@
<%= unless @users |> Enum.empty?() do %>
<hr class="hr" />
<h1 class="title text-2xl text-primary-400">
<h1 class="title text-xl text-primary-400">
<%= gettext("users") %>
</h1>
<div class="w-full flex flex-row flex-wrap justify-center items-center">
<div class="flex flex-col justify-center items-stretch space-y-4">
<.user_card :for={user <- @users} user={user}>
<.link
href="#"
@ -124,7 +140,7 @@
data-confirm={
dgettext(
"prompts",
"are you sure you want to delete %{email}? This action is permanent!",
"are you sure you want to delete %{email}? this action is permanent!",
email: user.email
)
}

View File

@ -1,127 +0,0 @@
defmodule MemexWeb.LiveHelpers do
@moduledoc """
Contains common helper functions for liveviews
"""
import Phoenix.Component
alias Phoenix.LiveView.JS
@doc """
Renders a live component inside a modal.
The rendered modal receives a `:return_to` option to properly update
the URL when the modal is closed.
## Examples
<.modal return_to={Routes.<%= schema.singular %>_index_path(Endpoint, :index)}>
<.live_component
module={<%= inspect context.web_module %>.<%= inspect Module.concat(schema.web_namespace, schema.alias) %>Live.FormComponent}
id={@<%= schema.singular %>.id || :new}
title={@page_title}
action={@live_action}
return_to={Routes.<%= schema.singular %>_index_path(Endpoint, :index)}
<%= schema.singular %>: @<%= schema.singular %>
/>
</.modal>
"""
def modal(assigns) do
~H"""
<.link
patch={@return_to}
id="modal-bg"
class="fade-in fixed z-10 left-0 top-0
w-full h-full overflow-hidden
p-8 flex flex-col justify-center items-center cursor-auto"
style="background-color: rgba(0,0,0,0.4);"
phx-remove={hide_modal()}
>
<span class="hidden"></span>
</.link>
<div
id="modal"
class="fixed z-10 left-0 top-0 pointer-events-none
w-screen h-screen overflow-hidden
p-4 sm:p-8 flex flex-col justify-center items-center"
>
<div
id="modal-content"
class="fade-in-scale max-w-3xl max-h-3xl relative w-full
pointer-events-auto overflow-hidden
px-8 py-4 sm:py-8 flex flex-col justify-start items-stretch
bg-primary-800 text-primary-400 border-primary-900 border-2 rounded-lg"
>
<.link
patch={@return_to}
id="close"
class="absolute top-8 right-10
text-gray-500 hover:text-gray-800
transition-all duration-500 ease-in-out"
phx-remove={hide_modal()}
>
<i class="fa-fw fa-lg fas fa-times"></i>
</.link>
<div class="overflow-x-hidden overflow-y-auto w-full p-8 flex flex-col space-y-4 justify-start items-stretch">
<%= render_slot(@inner_block) %>
</div>
</div>
</div>
"""
end
defp hide_modal(js \\ %JS{}) do
js
|> JS.hide(to: "#modal", transition: "fade-out")
|> JS.hide(to: "#modal-bg", transition: "fade-out")
|> JS.hide(to: "#modal-content", transition: "fade-out-scale")
end
@doc """
A toggle button element that can be directed to a liveview or a
live_component's `handle_event/3`.
## Examples
<.toggle_button action="my_liveview_action" value={@some_value}>
<span>Toggle me!</span>
</.toggle_button>
<.toggle_button action="my_live_component_action" target={@myself} value={@some_value}>
<span>Whatever you want</span>
</.toggle_button>
"""
def toggle_button(assigns) do
assigns = assigns |> assign_new(:id, fn -> assigns.action end)
~H"""
<label for={@id} class="inline-flex relative items-center cursor-pointer">
<input
id={@id}
type="checkbox"
value={@value}
checked={@value}
class="sr-only peer"
data-qa={@id}
{
if assigns |> Map.has_key?(:target),
do: %{"phx-click": @action, "phx-value-value": @value, "phx-target": @target},
else: %{"phx-click": @action, "phx-value-value": @value}
}
/>
<div class="w-11 h-6 bg-gray-300 rounded-full peer
peer-focus:ring-4 peer-focus:ring-teal-300 dark:peer-focus:ring-teal-800
peer-checked:bg-gray-600
peer-checked:after:translate-x-full peer-checked:after:border-white
after:content-[''] after:absolute after:top-1 after:left-[2px] after:bg-white after:border-gray-300
after:border after:rounded-full after:h-5 after:w-5
after:transition-all after:duration-250 after:ease-in-out
transition-colors duration-250 ease-in-out">
</div>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">
<%= render_slot(@inner_block) %>
</span>
</label>
"""
end
end

View File

@ -59,7 +59,6 @@ defmodule MemexWeb.NoteLive.Index do
{:noreply, socket}
end
@impl true
def handle_event("search", %{"search" => %{"search_term" => ""}}, socket) do
{:noreply, socket |> push_patch(to: Routes.note_index_path(Endpoint, :index))}
end

View File

@ -5,7 +5,8 @@
<.form
:let={f}
for={:search}
for={%{}}
as={:search}
phx-change="search"
phx-submit="search"
class="self-stretch flex flex-col items-stretch"
@ -33,7 +34,7 @@
<.link
:if={is_owner?(note, @current_user)}
patch={Routes.note_index_path(@socket, :edit, note.slug)}
data-qa={"note-edit-#{note.id}"}
aria-label={dgettext("actions", "edit %{note_slug}", note_slug: note.slug)}
>
<%= dgettext("actions", "edit") %>
</.link>
@ -43,7 +44,7 @@
phx-click="delete"
phx-value-id={note.id}
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-note-#{note.id}"}
aria-label={dgettext("actions", "delete %{note_slug}", note_slug: note.slug)}
>
<%= dgettext("actions", "delete") %>
</.link>

View File

@ -1,6 +1,5 @@
defmodule MemexWeb.NoteLive.Show do
use MemexWeb, :live_view
import MemexWeb.Components.NoteContent
alias Memex.{Accounts.User, Notes, Notes.Note}
@impl true

View File

@ -36,7 +36,7 @@
class="btn btn-primary"
phx-click="delete"
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-note-#{@note.id}"}
aria-label={dgettext("actions", "delete %{note_slug}", note_slug: @note.slug)}
>
<%= dgettext("actions", "delete") %>
</button>

View File

@ -59,7 +59,6 @@ defmodule MemexWeb.PipelineLive.Index do
{:noreply, socket}
end
@impl true
def handle_event("search", %{"search" => %{"search_term" => ""}}, socket) do
{:noreply, socket |> push_patch(to: Routes.pipeline_index_path(Endpoint, :index))}
end

View File

@ -5,7 +5,8 @@
<.form
:let={f}
for={:search}
for={%{}}
as={:search}
phx-change="search"
phx-submit="search"
class="self-stretch flex flex-col items-stretch"
@ -33,7 +34,7 @@
<.link
:if={is_owner?(pipeline, @current_user)}
patch={Routes.pipeline_index_path(@socket, :edit, pipeline.slug)}
data-qa={"pipeline-edit-#{pipeline.id}"}
aria-label={dgettext("actions", "edit %{pipeline_slug}", pipeline_slug: pipeline.slug)}
>
<%= dgettext("actions", "edit") %>
</.link>
@ -43,7 +44,9 @@
phx-click="delete"
phx-value-id={pipeline.id}
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-pipeline-#{pipeline.id}"}
aria-label={
dgettext("actions", "delete %{pipeline_slug}", pipeline_slug: pipeline.slug)
}
>
<%= dgettext("actions", "delete") %>
</.link>

View File

@ -1,6 +1,5 @@
defmodule MemexWeb.PipelineLive.Show do
use MemexWeb, :live_view
import MemexWeb.Components.StepContent
alias Memex.{Accounts.User, Pipelines}
alias Memex.Pipelines.{Pipeline, Steps, Steps.Step}
@ -80,7 +79,6 @@ defmodule MemexWeb.PipelineLive.Show do
{:noreply, socket}
end
@impl true
def handle_event(
"delete_step",
%{"step-id" => step_id},
@ -99,7 +97,6 @@ defmodule MemexWeb.PipelineLive.Show do
{:noreply, socket}
end
@impl true
def handle_event(
"reorder_step",
%{"step-id" => step_id, "direction" => direction},

View File

@ -44,7 +44,7 @@
class="btn btn-primary"
phx-click="delete"
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-pipeline-#{@pipeline.id}"}
aria-label={dgettext("actions", "delete %{pipeline_slug}", pipeline_slug: @pipeline.slug)}
>
<%= dgettext("actions", "delete") %>
</button>
@ -78,7 +78,7 @@
phx-click="reorder_step"
phx-value-direction="up"
phx-value-step-id={step_id}
data-qa={"move-step-up-#{step_id}"}
aria-label={dgettext("actions", "move %{step_title} up", step_title: step.title)}
>
<i class="fas text-xl fa-chevron-up"></i>
</button>
@ -93,7 +93,9 @@
phx-click="reorder_step"
phx-value-direction="down"
phx-value-step-id={step_id}
data-qa={"move-step-down-#{step_id}"}
aria-label={
dgettext("actions", "move %{step_title} down", step_title: step.title)
}
>
<i class="fas text-xl fa-chevron-down"></i>
</button>
@ -102,7 +104,7 @@
<.link
class="self-end btn btn-primary"
patch={Routes.pipeline_show_path(@socket, :edit_step, @pipeline.slug, step_id)}
data-qa={"edit-step-#{step_id}"}
aria-label={dgettext("actions", "edit %{step_title}", step_title: step.title)}
>
<%= dgettext("actions", "edit") %>
</.link>
@ -113,7 +115,7 @@
phx-click="delete_step"
phx-value-step-id={step_id}
data-confirm={dgettext("prompts", "are you sure?")}
data-qa={"delete-step-#{step_id}"}
aria-label={dgettext("actions", "delete %{step_title}", step_title: step.title)}
>
<%= dgettext("actions", "delete") %>
</button>
@ -129,7 +131,6 @@
:if={is_owner?(@pipeline, @current_user)}
class="self-end btn btn-primary"
patch={Routes.pipeline_show_path(@socket, :add_step, @pipeline.slug)}
data-qa={"add-step-#{@pipeline.id}"}
>
<%= dgettext("actions", "add step") %>
</.link>

View File

@ -11,9 +11,9 @@
<script defer type="text/javascript" src="/js/app.js">
</script>
</head>
<body class="m-0 p-0 w-full h-full bg-primary-800 text-primary-400 subpixel-antialiased">
<body class="pb-8 m-0 p-0 w-full h-full bg-primary-800 text-primary-400 subpixel-antialiased">
<header>
<.topbar current_user={assigns[:current_user]}></.topbar>
<.topbar current_user={assigns[:current_user]} />
</header>
<div class="pb-8 w-full flex flex-col justify-center items-center text-center">
@ -24,9 +24,12 @@
<hr class="w-full hr" />
<a href={Routes.live_path(Endpoint, HomeLive)} class="link title text-primary-400 text-lg">
<.link
href={Routes.live_path(Endpoint, HomeLive)}
class="link title text-primary-400 text-lg"
>
<%= dgettext("errors", "go back home") %>
</a>
</.link>
</div>
</div>
</body>

View File

@ -1,6 +1,6 @@
<main role="main" class="min-h-full min-w-full">
<header>
<.topbar current_user={assigns[:current_user]}></.topbar>
<.topbar current_user={assigns[:current_user]} />
<div class="mx-8 my-2 flex flex-col space-y-4 text-center">
<p :if={get_flash(@conn, :info)} class="alert alert-info" role="alert">

View File

@ -1,6 +1,6 @@
<main class="pb-8 min-w-full">
<header>
<.topbar current_user={assigns[:current_user]}></.topbar>
<.topbar current_user={assigns[:current_user]} />
<div class="mx-8 my-2 flex flex-col space-y-4 text-center">
<p
@ -33,7 +33,7 @@
<div
id="disconnect"
class="z-50 fixed opacity-0 bottom-12 right-12 px-8 py-4 w-max h-max
border border-primary-400 shadow-lg rounded-lg bg-primary-800 text-primary-400
border border-primary-400 shadow-lg rounded-lg bg-primary-900 text-primary-400
flex justify-center items-center space-x-4
transition-opacity ease-in-out duration-500 delay-[2000ms]"
>

View File

@ -5,11 +5,12 @@
<.form
:let={f}
for={:user}
for={%{}}
as={:user}
action={Routes.user_confirmation_path(@conn, :create)}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
>
<%= label(f, :email, class: "title text-lg text-primary-400") %>
<%= label(f, :email, gettext("Email"), class: "title text-lg text-primary-400") %>
<%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %>
<%= submit(dgettext("actions", "Resend confirmation instructions"),

View File

@ -17,11 +17,11 @@
<%= hidden_input(f, :invite_token, value: @invite_token) %>
<% end %>
<%= label(f, :email, class: "title text-lg text-primary-400") %>
<%= label(f, :email, gettext("email"), class: "title text-lg text-primary-400") %>
<%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %>
<%= error_tag(f, :email, "col-span-3") %>
<%= label(f, :password, class: "title text-lg text-primary-400") %>
<%= label(f, :password, gettext("password"), class: "title text-lg text-primary-400") %>
<%= password_input(f, :password, required: true, class: "input input-primary col-span-2") %>
<%= error_tag(f, :password, "col-span-3") %>

View File

@ -9,17 +9,15 @@
action={Routes.user_reset_password_path(@conn, :update, @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"
>
<div :if={@changeset.action && not @changeset.valid?()} class="alert alert-danger col-span-3">
<p>
<%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %>
</p>
</div>
<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.") %>
</p>
<%= label(f, :password, "new password", class: "title text-lg text-primary-400") %>
<%= label(f, :password, gettext("new password"), class: "title text-lg text-primary-400") %>
<%= password_input(f, :password, required: true, class: "input input-primary col-span-2") %>
<%= error_tag(f, :password, "col-span-3") %>
<%= label(f, :password_confirmation, "Confirm new password",
<%= label(f, :password_confirmation, gettext("confirm new password"),
class: "title text-lg text-primary-400"
) %>
<%= password_input(f, :password_confirmation,

View File

@ -5,11 +5,12 @@
<.form
:let={f}
for={:user}
for={%{}}
as={:user}
action={Routes.user_reset_password_path(@conn, :create)}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
>
<%= label(f, :email, class: "title text-lg text-primary-400") %>
<%= label(f, :email, gettext("email"), class: "title text-lg text-primary-400") %>
<%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %>
<%= submit(dgettext("actions", "send instructions to reset password"),

View File

@ -10,19 +10,17 @@
as="user"
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
>
<div :if={@error_message} class="alert alert-danger col-span-3">
<p>
<%= @error_message %>
</p>
</div>
<p :if={@error_message} class="alert alert-danger col-span-3">
<%= @error_message %>
</p>
<%= label(f, :email, class: "title text-lg text-primary-400") %>
<%= label(f, :email, gettext("email"), class: "title text-lg text-primary-400") %>
<%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %>
<%= label(f, :password, class: "title text-lg text-primary-400") %>
<%= label(f, :password, gettext("password"), class: "title text-lg text-primary-400") %>
<%= password_input(f, :password, required: true, class: "input input-primary col-span-2") %>
<%= label(f, :remember_me, gettext("Keep me logged in for 60 days"),
<%= label(f, :remember_me, gettext("keep me logged in for 60 days"),
class: "title text-lg text-primary-400"
) %>
<%= checkbox(f, :remember_me, class: "checkbox col-span-2") %>

View File

@ -1,5 +1,5 @@
<div class="mx-auto pb-8 max-w-2xl flex flex-col justify-center items-center text-center space-y-4">
<h1 class="pb-4 title text-primary-400 text-xl">
<div class="mx-auto pb-8 max-w-3xl flex flex-col justify-center items-stretch text-right space-y-4">
<h1 class="title text-primary-400 text-xl text-left">
<%= gettext("settings") %>
</h1>
@ -11,7 +11,7 @@
action={Routes.user_settings_path(@conn, :update)}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
>
<h3 class="title text-primary-400 text-lg col-span-3">
<h3 class="title text-primary-400 text-lg text-center col-span-3">
<%= dgettext("actions", "change email") %>
</h3>
@ -19,9 +19,7 @@
:if={@email_changeset.action && not @email_changeset.valid?()}
class="alert alert-danger col-span-3"
>
<p>
<%= dgettext("errors", "oops, something went wrong! Please check the errors below") %>
</p>
<%= dgettext("errors", "oops, something went wrong! please check the errors below") %>
</div>
<%= hidden_input(f, :action, name: "action", value: "update_email") %>
@ -55,18 +53,16 @@
action={Routes.user_settings_path(@conn, :update)}
class="flex flex-col space-y-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 justify-center items-center"
>
<h3 class="title text-primary-400 text-lg col-span-3">
<h3 class="title text-primary-400 text-lg text-center col-span-3">
<%= dgettext("actions", "change password") %>
</h3>
<div
<p
:if={@password_changeset.action && not @password_changeset.valid?()}
class="alert alert-danger col-span-3"
>
<p>
<%= dgettext("errors", "Oops, something went wrong! Please check the errors below.") %>
</p>
</div>
<%= dgettext("errors", "oops, something went wrong! please check the errors below.") %>
</p>
<%= hidden_input(f, :action, name: "action", value: "update_password") %>
@ -109,37 +105,35 @@
:let={f}
for={@locale_changeset}
action={Routes.user_settings_path(@conn, :update)}
class="flex flex-col space-y-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"
>
<h3 class="title text-primary-400 text-lg">
<h3 class="title text-primary-400 text-lg text-center col-span-3">
<%= dgettext("actions", "change language") %>
</h3>
<div
:if={@locale_changeset.action && not @locale_changeset.valid?()}
class="alert alert-danger"
class="alert alert-danger col-span-3"
>
<p>
<%= dgettext("errors", "oops, something went wrong! Please check the errors below") %>
</p>
<%= dgettext("errors", "oops, something went wrong! please check the errors below") %>
</div>
<%= hidden_input(f, :action, name: "action", value: "update_locale") %>
<%= select(f, :locale, [{gettext("english"), "en_US"}, {"spanish", "es"}],
class: "mx-2 my-1 min-w-md input input-primary"
class: "mx-2 my-1 min-w-md input input-primary col-start-2"
) %>
<%= error_tag(f, :locale) %>
<%= error_tag(f, :locale, "col-span-3") %>
<%= submit(dgettext("actions", "change language"),
class: "whitespace-nowrap mx-auto btn btn-primary",
class: "whitespace-nowrap mx-auto btn btn-primary col-span-3",
data: [qa: dgettext("prompts", "are you sure you want to change your language?")]
) %>
</.form>
<hr class="hr" />
<div class="flex justify-center items-center">
<div class="flex justify-end items-center">
<.link
href={Routes.export_path(@conn, :export, :json)}
class="mx-4 my-2 btn btn-primary"

View File

@ -1,6 +1,5 @@
defmodule MemexWeb.ErrorView do
use MemexWeb, :view
import MemexWeb.Components.Topbar
alias MemexWeb.HomeLive
def template_not_found(error_path, _assigns) do

View File

@ -1,13 +1,12 @@
defmodule MemexWeb.LayoutView do
use MemexWeb, :view
import MemexWeb.{Components.Topbar, Gettext}
alias MemexWeb.HomeLive
# Phoenix LiveDashboard is available only in development by default,
# so we instruct Elixir to not warn if the dashboard route is missing.
@compile {:no_warn_undefined, {Routes, :live_dashboard_path, 2}}
def get_title(%{assigns: %{title: title}}) do
def get_title(%{assigns: %{title: title}}) when title not in [nil, ""] do
gettext("memEx | %{title}", title: title)
end

View File

@ -7,61 +7,6 @@ defmodule MemexWeb.ViewHelpers do
use Phoenix.Component
@doc """
Phoenix.Component for a <time> element that renders the naivedatetime in the
user's local timezone with Alpine.js
"""
attr :datetime, :any, required: true, doc: "A `DateTime` struct or nil"
def datetime(assigns) do
~H"""
<time
:if={@datetime}
datetime={cast_datetime(@datetime)}
x-data={"{
datetime:
Intl.DateTimeFormat([], {dateStyle: 'short', timeStyle: 'long'})
.format(new Date(\"#{cast_datetime(@datetime)}\"))
}"}
x-text="datetime"
>
<%= cast_datetime(@datetime) %>
</time>
"""
end
@spec cast_datetime(NaiveDateTime.t() | nil) :: String.t()
defp cast_datetime(%NaiveDateTime{} = datetime) do
datetime |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(:extended)
end
defp cast_datetime(_datetime), do: ""
@doc """
Phoenix.Component for a <date> element that renders the Date in the user's
local timezone with Alpine.js
"""
attr :date, :any, required: true, doc: "A `Date` struct or nil"
def date(assigns) do
~H"""
<time
:if={@date}
datetime={@date |> Date.to_iso8601(:extended)}
x-data={"{
date:
Intl.DateTimeFormat([], {timeZone: 'Etc/UTC', dateStyle: 'short'})
.format(new Date(\"#{@date |> Date.to_iso8601(:extended)}\"))
}"}
x-text="date"
>
<%= @date |> Date.to_iso8601(:extended) %>
</time>
"""
end
@doc """
Displays content in a QR code as a base64 encoded PNG
"""
@ -71,26 +16,9 @@ defmodule MemexWeb.ViewHelpers do
img_data =
content
|> EQRCode.encode()
|> EQRCode.png(width: width, background_color: <<39, 39, 42>>, color: <<255, 255, 255>>)
|> EQRCode.png(width: width, background_color: <<24, 24, 27>>, color: <<255, 255, 255>>)
|> Base.encode64()
"data:image/png;base64," <> img_data
end
@doc """
Creates a downloadable QR Code element
"""
attr :content, :string, required: true
attr :filename, :string, default: "qrcode", doc: "filename without .png extension"
attr :image_class, :string, default: "w-64 h-max"
attr :width, :integer, default: 384, doc: "width of png to generate"
def qr_code(assigns) do
~H"""
<a href={qr_code_image(@content)} download={@filename <> ".png"}>
<img class={@image_class} alt={@filename} src={qr_code_image(@content)} />
</a>
"""
end
end

View File

@ -4,8 +4,8 @@ defmodule Memex.MixProject do
def project do
[
app: :memex,
version: "0.1.8",
elixir: "~> 1.14",
version: "0.1.10",
elixir: "1.14.1",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: Mix.compilers(),
start_permanent: Mix.env() == :prod,
@ -47,13 +47,13 @@ defmodule Memex.MixProject do
# Type `mix help deps` for examples and options.
defp deps do
[
{:bcrypt_elixir, "~> 2.0"},
{:bcrypt_elixir, "~> 3.0"},
{:phoenix, "~> 1.6.0"},
{:phoenix_ecto, "~> 4.4"},
{:phoenix_html, "~> 3.0"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:phoenix_live_view, "~> 0.18.0"},
{:phoenix_view, "~> 1.1"},
{:phoenix_view, "~> 2.0"},
{:phoenix_live_dashboard, "~> 0.6"},
{:ecto_sql, "~> 3.6"},
{:postgrex, ">= 0.0.0"},

View File

@ -1,5 +1,5 @@
%{
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.0.1", "9be815469e6bfefec40fa74658ecbbe6897acfb57614df1416eeccd4903f602c", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "486bb95efb645d1efc6794c1ddd776a186a9a713abf06f45708a6ce324fb96cf"},
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
"castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"},
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
@ -11,38 +11,39 @@
"db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"},
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
"earmark_parser": {:hex, :earmark_parser, "1.4.31", "a93921cdc6b9b869f519213d5bc79d9e218ba768d7270d46fdcf1c01bacff9e2", [:mix], [], "hexpm", "317d367ee0335ef037a87e46c91a2269fef6306413f731e8ec11fc45a7efd059"},
"ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [: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", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"},
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.10", "e14d400930f401ca9f541b3349212634e44027d7f919bbb71224d7ac0d0e8acd", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.15.7 or ~> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "505e8cd81e4f17c090be0f99e92b1b3f0fd915f98e76965130b8ccfb891e7088"},
"ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"},
"elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"},
"elixir_make": {:hex, :elixir_make, "0.7.5", "784cc00f5fa24239067cc04d449437dcc5f59353c44eb08f188b2b146568738a", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "c3d63e8d5c92fa3880d89ecd41de59473fa2e83eeb68148155e25e8b95aa2887"},
"eqrcode": {:hex, :eqrcode, "0.1.10", "6294fece9d68ad64eef1c3c92cf111cfd6469f4fbf230a2d4cc905a682178f3f", [:mix], [], "hexpm", "da30e373c36a0fd37ab6f58664b16029919896d6c45a68a95cc4d713e81076f1"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"},
"expo": {:hex, :expo, "0.3.0", "13127c1d5f653b2927f2616a4c9ace5ae372efd67c7c2693b87fd0fdc30c6feb", [:mix], [], "hexpm", "fb3cd4bf012a77bc1608915497dae2ff684a06f0fa633c7afa90c4d72b881823"},
"ex_doc": {:hex, :ex_doc, "0.29.2", "dfa97532ba66910b2a3016a4bbd796f41a86fc71dd5227e96f4c8581fdf0fdf0", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "6b5d7139eda18a753e3250e27e4a929f8d2c880dd0d460cb9986305dea3e03af"},
"expo": {:hex, :expo, "0.4.0", "bbe4bf455e2eb2ebd2f1e7d83530ce50fb9990eb88fc47855c515bfdf1c6626f", [:mix], [], "hexpm", "a8ed1683ec8b7c7fa53fd7a41b2c6935f539168a6bb0616d7fd6b58a36f3abf2"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"floki": {:hex, :floki, "0.34.0", "002d0cc194b48794d74711731db004fafeb328fe676976f160685262d43706a8", [:mix], [], "hexpm", "9c3a9f43f40dde00332a589bd9d389b90c1f518aef500364d00636acc5ebc99c"},
"floki": {:hex, :floki, "0.34.2", "5fad07ef153b3b8ec110b6b155ec3780c4b2c4906297d0b4be1a7162d04a7e02", [:mix], [], "hexpm", "26b9d50f0f01796bc6be611ca815c5e0de034d2128e39cc9702eee6b66a4d1c8"},
"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.22.0", "a25d71ec21b1848957d9207b81fd61cb25161688d282d58bdafef74c2270bdc4", [:mix], [{:expo, "~> 0.3.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "cb0675141576f73720c8e49b4f0fd3f2c69f0cd8c218202724d4aebab8c70ace"},
"gettext": {:hex, :gettext, "0.22.1", "e7942988383c3d9eed4bdc22fc63e712b655ae94a672a27e4900e3d4a2c43581", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "ad105b8dab668ee3f90c0d3d94ba75e9aead27a62495c101d94f2657a190ac5d"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"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_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
"oban": {:hex, :oban, "2.13.6", "a0cb1bce3bd393770512231fb5a3695fa19fd3af10d7575bf73f837aee7abf43", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c1c5eb16f377b3cbbf2ea14be24d20e3d91285af9d1ac86260b7c2af5464887"},
"phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"},
"oban": {:hex, :oban, "2.14.2", "ae925d9a33e110addaa59ff7ec1b2fd84270ac7eb00fbb4b4a179d74c407bba3", [: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", "32bf30127c8c44ac42f05f229a50fadc2177b3e799c29499f5daf90d5e5b5d3c"},
"phoenix": {:hex, :phoenix, "1.6.16", "e5bdd18c7a06da5852a25c7befb72246de4ddc289182285f8685a40b7b5f5451", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e15989ff34f670a96b95ef6d1d25bad0d9c50df5df40b671d8f4a669e050ac39"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
"phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.1", "b0bf8f3348dec4910907a2ad1453e642f6fe4d444376c1c9b26222d63c73cf97", [: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]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "b6c5d744bf4b40692b1b361d3608bdfd05aeab83e17c7bc217d730f007f31abf"},
"phoenix_html": {:hex, :phoenix_html, "3.3.1", "4788757e804a30baac6b3fc9695bf5562465dd3f1da8eb8460ad5b404d9a2178", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bed1906edd4906a15fd7b412b85b05e521e1f67c9a85418c55999277e553d0d3"},
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [: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]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"},
"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_view": {:hex, :phoenix_live_view, "0.18.2", "635cf07de947235deb030cd6b776c71a3b790ab04cebf526aa8c879fe17c7784", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "da287a77327e996cc166e4c440c3ad5ab33ccdb151b91c793209b39ebbce5b75"},
"phoenix_live_view": {:hex, :phoenix_live_view, "0.18.18", "1f38fbd7c363723f19aad1a04b5490ff3a178e37daaf6999594d5f34796c47fc", [: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]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a5810d0472f3189ede6d2a95bda7f31c6113156b91784a3426cb0ab6a6d85214"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
"phoenix_swoosh": {:hex, :phoenix_swoosh, "1.1.0", "f8e4780705c9f254cc853f7a40e25f7198ba4d91102bcfad2226669b69766b35", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "aa82f10afd9a4b6080fdf3274dbb9432b25b210d42b4b6b55308f6e59cd87c3d"},
"phoenix_view": {:hex, :phoenix_view, "1.1.2", "1b82764a065fb41051637872c7bd07ed2fdb6f5c3bd89684d4dca6e10115c95a", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "7ae90ad27b09091266f6adbb61e1d2516a7c3d7062c6789d46a7554ec40f3a56"},
"phoenix_swoosh": {:hex, :phoenix_swoosh, "1.2.0", "a544d83fde4a767efb78f45404a74c9e37b2a9c5ea3339692e65a6966731f935", [:mix], [{:finch, "~> 0.8", [hex: :finch, repo: "hexpm", optional: true]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.5", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "e88d117251e89a16b92222415a6d87b99a96747ddf674fc5c7631de734811dba"},
"phoenix_template": {:hex, :phoenix_template, "1.0.1", "85f79e3ad1b0180abb43f9725973e3b8c2c3354a87245f91431eec60553ed3ef", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "157dc078f6226334c91cb32c1865bf3911686f8bcd6bcff86736f6253e6993ee"},
"phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"},
"plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"},
"plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [: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", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"},
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
"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_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
"postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {: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", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"swoosh": {:hex, :swoosh, "1.9.1", "0a5d7bf9954eb41d7e55525bc0940379982b090abbaef67cd8e1fd2ed7f8ca1a", [: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_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", "76dffff3ffcab80f249d5937a592eaef7cc49ac6f4cdd27e622868326ed6371e"},

View File

@ -10,74 +10,69 @@
msgid ""
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:29
#, elixir-autogen, elixir-format
msgid "Copy to clipboard"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:3
#: lib/memex_web/templates/user_confirmation/new.html.heex:15
#: lib/memex_web/templates/user_confirmation/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "Resend confirmation instructions"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:3
#: lib/memex_web/templates/user_reset_password/edit.html.heex:31
#: lib/memex_web/templates/user_reset_password/edit.html.heex:29
#, elixir-autogen, elixir-format
msgid "Reset password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:29
#: lib/memex_web/live/invite_live/form_component.html.heex:32
#, elixir-autogen, elixir-format
msgid "Save"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:45
#: lib/memex_web/templates/user_settings/edit.html.heex:43
#, elixir-autogen, elixir-format
msgid "change email"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:115
#: lib/memex_web/templates/user_settings/edit.html.heex:134
#: lib/memex_web/templates/user_settings/edit.html.heex:111
#: lib/memex_web/templates/user_settings/edit.html.heex:128
#, elixir-autogen, elixir-format
msgid "change language"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:59
#: lib/memex_web/templates/user_settings/edit.html.heex:101
#: lib/memex_web/templates/user_settings/edit.html.heex:57
#: lib/memex_web/templates/user_settings/edit.html.heex:97
#, elixir-autogen, elixir-format
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:16
#: lib/memex_web/live/invite_live/index.html.heex:94
#, elixir-autogen, elixir-format
msgid "create invite"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:48
#: lib/memex_web/live/context_live/index.html.heex:49
#: lib/memex_web/live/context_live/show.html.heex:41
#: lib/memex_web/live/note_live/index.html.heex:48
#: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:41
#: lib/memex_web/live/pipeline_live/index.html.heex:48
#: lib/memex_web/live/pipeline_live/index.html.heex:51
#: lib/memex_web/live/pipeline_live/show.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:118
#: lib/memex_web/live/pipeline_live/show.html.heex:120
#, elixir-autogen, elixir-format
msgid "delete"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:157
#: lib/memex_web/templates/user_settings/edit.html.heex:151
#, elixir-autogen, elixir-format
msgid "delete user"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:38
#: lib/memex_web/live/context_live/index.html.heex:39
#: lib/memex_web/live/context_live/show.html.heex:31
#: lib/memex_web/live/note_live/index.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:39
#: lib/memex_web/live/note_live/show.html.heex:31
#: lib/memex_web/live/pipeline_live/index.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:107
#: lib/memex_web/live/pipeline_live/show.html.heex:109
#, elixir-autogen, elixir-format
msgid "edit"
msgstr ""
@ -87,39 +82,39 @@ msgstr ""
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/topbar.ex:124
#: lib/memex_web/templates/user_confirmation/new.html.heex:31
#: lib/memex_web/components/core_components/topbar.html.heex:107
#: lib/memex_web/templates/user_confirmation/new.html.heex:32
#: lib/memex_web/templates/user_registration/new.html.heex:44
#: lib/memex_web/templates/user_reset_password/edit.html.heex:47
#: lib/memex_web/templates/user_reset_password/new.html.heex:31
#: lib/memex_web/templates/user_reset_password/edit.html.heex:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:32
#: lib/memex_web/templates/user_session/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:30
#: lib/memex_web/templates/user_session/new.html.heex:28
#, elixir-autogen, elixir-format
msgid "log in"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:59
#: lib/memex_web/live/context_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new context"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:59
#: lib/memex_web/live/note_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new note"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:59
#: lib/memex_web/live/pipeline_live/index.html.heex:62
#, elixir-autogen, elixir-format
msgid "new pipeline"
msgstr ""
#: lib/memex_web/components/topbar.ex:115
#: lib/memex_web/templates/user_confirmation/new.html.heex:28
#: lib/memex_web/components/core_components/topbar.html.heex:98
#: lib/memex_web/templates/user_confirmation/new.html.heex:29
#: lib/memex_web/templates/user_registration/new.html.heex:3
#: lib/memex_web/templates/user_registration/new.html.heex:37
#: lib/memex_web/templates/user_reset_password/edit.html.heex:44
#: lib/memex_web/templates/user_reset_password/new.html.heex:28
#: lib/memex_web/templates/user_session/new.html.heex:41
#: lib/memex_web/templates/user_reset_password/edit.html.heex:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:29
#: lib/memex_web/templates/user_session/new.html.heex:39
#, elixir-autogen, elixir-format
msgid "register"
msgstr ""
@ -139,24 +134,97 @@ msgstr ""
msgid "back"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:134
#: lib/memex_web/live/pipeline_live/show.html.heex:135
#, elixir-autogen, elixir-format
msgid "add step"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:47
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#: lib/memex_web/templates/user_session/new.html.heex:42
#, elixir-autogen, elixir-format
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#: lib/memex_web/templates/user_reset_password/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:148
#: lib/memex_web/templates/user_settings/edit.html.heex:142
#, elixir-autogen, elixir-format
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:33
#, elixir-autogen, elixir-format
msgid "copy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:30
#, elixir-autogen, elixir-format
msgid "copy invite link for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:47
#: lib/memex_web/live/context_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:47
#: lib/memex_web/live/note_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:48
#: lib/memex_web/live/pipeline_live/show.html.heex:47
#, elixir-autogen, elixir-format
msgid "delete %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:118
#, elixir-autogen, elixir-format
msgid "delete %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#, elixir-autogen, elixir-format
msgid "delete invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:107
#, elixir-autogen, elixir-format
msgid "edit %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:41
#, elixir-autogen, elixir-format
msgid "edit invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:97
#, elixir-autogen, elixir-format
msgid "move %{step_title} down"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:81
#, elixir-autogen, elixir-format
msgid "move %{step_title} up"
msgstr ""

View File

@ -10,74 +10,69 @@ msgid ""
msgstr ""
"Language: de\n"
#: lib/memex_web/live/invite_live/index.html.heex:29
#, elixir-autogen, elixir-format
msgid "Copy to clipboard"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:3
#: lib/memex_web/templates/user_confirmation/new.html.heex:15
#: lib/memex_web/templates/user_confirmation/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "Resend confirmation instructions"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:3
#: lib/memex_web/templates/user_reset_password/edit.html.heex:31
#: lib/memex_web/templates/user_reset_password/edit.html.heex:29
#, elixir-autogen, elixir-format
msgid "Reset password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:29
#: lib/memex_web/live/invite_live/form_component.html.heex:32
#, elixir-autogen, elixir-format
msgid "Save"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:45
#: lib/memex_web/templates/user_settings/edit.html.heex:43
#, elixir-autogen, elixir-format
msgid "change email"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:115
#: lib/memex_web/templates/user_settings/edit.html.heex:134
#: lib/memex_web/templates/user_settings/edit.html.heex:111
#: lib/memex_web/templates/user_settings/edit.html.heex:128
#, elixir-autogen, elixir-format
msgid "change language"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:59
#: lib/memex_web/templates/user_settings/edit.html.heex:101
#: lib/memex_web/templates/user_settings/edit.html.heex:57
#: lib/memex_web/templates/user_settings/edit.html.heex:97
#, elixir-autogen, elixir-format
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:16
#: lib/memex_web/live/invite_live/index.html.heex:94
#, elixir-autogen, elixir-format
msgid "create invite"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:48
#: lib/memex_web/live/context_live/index.html.heex:49
#: lib/memex_web/live/context_live/show.html.heex:41
#: lib/memex_web/live/note_live/index.html.heex:48
#: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:41
#: lib/memex_web/live/pipeline_live/index.html.heex:48
#: lib/memex_web/live/pipeline_live/index.html.heex:51
#: lib/memex_web/live/pipeline_live/show.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:118
#: lib/memex_web/live/pipeline_live/show.html.heex:120
#, elixir-autogen, elixir-format
msgid "delete"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:157
#: lib/memex_web/templates/user_settings/edit.html.heex:151
#, elixir-autogen, elixir-format
msgid "delete user"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:38
#: lib/memex_web/live/context_live/index.html.heex:39
#: lib/memex_web/live/context_live/show.html.heex:31
#: lib/memex_web/live/note_live/index.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:39
#: lib/memex_web/live/note_live/show.html.heex:31
#: lib/memex_web/live/pipeline_live/index.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:107
#: lib/memex_web/live/pipeline_live/show.html.heex:109
#, elixir-autogen, elixir-format
msgid "edit"
msgstr ""
@ -87,39 +82,39 @@ msgstr ""
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/topbar.ex:124
#: lib/memex_web/templates/user_confirmation/new.html.heex:31
#: lib/memex_web/components/core_components/topbar.html.heex:107
#: lib/memex_web/templates/user_confirmation/new.html.heex:32
#: lib/memex_web/templates/user_registration/new.html.heex:44
#: lib/memex_web/templates/user_reset_password/edit.html.heex:47
#: lib/memex_web/templates/user_reset_password/new.html.heex:31
#: lib/memex_web/templates/user_reset_password/edit.html.heex:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:32
#: lib/memex_web/templates/user_session/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:30
#: lib/memex_web/templates/user_session/new.html.heex:28
#, elixir-autogen, elixir-format
msgid "log in"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:59
#: lib/memex_web/live/context_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new context"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:59
#: lib/memex_web/live/note_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new note"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:59
#: lib/memex_web/live/pipeline_live/index.html.heex:62
#, elixir-autogen, elixir-format
msgid "new pipeline"
msgstr ""
#: lib/memex_web/components/topbar.ex:115
#: lib/memex_web/templates/user_confirmation/new.html.heex:28
#: lib/memex_web/components/core_components/topbar.html.heex:98
#: lib/memex_web/templates/user_confirmation/new.html.heex:29
#: lib/memex_web/templates/user_registration/new.html.heex:3
#: lib/memex_web/templates/user_registration/new.html.heex:37
#: lib/memex_web/templates/user_reset_password/edit.html.heex:44
#: lib/memex_web/templates/user_reset_password/new.html.heex:28
#: lib/memex_web/templates/user_session/new.html.heex:41
#: lib/memex_web/templates/user_reset_password/edit.html.heex:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:29
#: lib/memex_web/templates/user_session/new.html.heex:39
#, elixir-autogen, elixir-format
msgid "register"
msgstr ""
@ -139,24 +134,97 @@ msgstr ""
msgid "back"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:134
#: lib/memex_web/live/pipeline_live/show.html.heex:135
#, elixir-autogen, elixir-format
msgid "add step"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:47
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#: lib/memex_web/templates/user_session/new.html.heex:42
#, elixir-autogen, elixir-format, fuzzy
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#: lib/memex_web/templates/user_reset_password/new.html.heex:16
#, elixir-autogen, elixir-format, fuzzy
msgid "send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:148
#: lib/memex_web/templates/user_settings/edit.html.heex:142
#, elixir-autogen, elixir-format
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:33
#, elixir-autogen, elixir-format
msgid "copy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:30
#, elixir-autogen, elixir-format
msgid "copy invite link for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:47
#: lib/memex_web/live/context_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:47
#: lib/memex_web/live/note_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:48
#: lib/memex_web/live/pipeline_live/show.html.heex:47
#, elixir-autogen, elixir-format
msgid "delete %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:118
#, elixir-autogen, elixir-format
msgid "delete %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#, elixir-autogen, elixir-format
msgid "delete invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:107
#, elixir-autogen, elixir-format
msgid "edit %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:41
#, elixir-autogen, elixir-format
msgid "edit invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:97
#, elixir-autogen, elixir-format
msgid "move %{step_title} down"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:81
#, elixir-autogen, elixir-format
msgid "move %{step_title} up"
msgstr ""

View File

@ -12,35 +12,11 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Translate Toolkit 3.7.4\n"
## This file is a PO Template file.
##
## "msgid"s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here has no
## effect: edit them in PO (.po) files instead.
#: lib/memex_web/live/invite_live/index.html.heex:86
#, elixir-autogen, elixir-format
msgid "Admins"
msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:8
#, elixir-autogen, elixir-format
msgid "Confirm your account"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:25
#, elixir-autogen, elixir-format
msgid "Keep me logged in for 60 days"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:21
#, elixir-autogen, elixir-format
msgid "Name"
msgstr ""
#: lib/memex_web/templates/layout/live.html.heex:43
#, elixir-autogen, elixir-format
msgid "Reconnecting..."
@ -51,11 +27,6 @@ msgstr ""
msgid "Reset your password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:25
#, elixir-autogen, elixir-format
msgid "Uses left"
msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:19
#: lib/memex_web/live/note_live/show.html.heex:19
#: lib/memex_web/live/pipeline_live/show.html.heex:27
@ -63,22 +34,23 @@ msgstr ""
msgid "Visibility: %{visibility}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:76
#: lib/memex_web/live/home_live.html.heex:71
#, elixir-autogen, elixir-format
msgid "accessible from any internet-capable device"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:90
#: lib/memex_web/live/home_live.html.heex:85
#, elixir-autogen, elixir-format
msgid "admins:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:58
#: lib/memex_web/live/home_live.html.heex:53
#, elixir-autogen, elixir-format
msgid "built with sharing and collaboration in mind"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:80
#: lib/memex_web/templates/user_reset_password/edit.html.heex:20
#: lib/memex_web/templates/user_settings/edit.html.heex:76
#, elixir-autogen, elixir-format
msgid "confirm new password"
msgstr ""
@ -88,7 +60,7 @@ msgstr ""
msgid "content"
msgstr ""
#: lib/memex_web/components/topbar.ex:52
#: lib/memex_web/components/core_components/topbar.html.heex:37
#: lib/memex_web/live/context_live/index.ex:35
#: lib/memex_web/live/context_live/index.ex:43
#: lib/memex_web/live/context_live/index.html.heex:3
@ -96,95 +68,93 @@ msgstr ""
msgid "contexts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:20
#: lib/memex_web/live/home_live.html.heex:18
#, elixir-autogen, elixir-format
msgid "contexts:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:73
#: lib/memex_web/live/home_live.html.heex:68
#, elixir-autogen, elixir-format
msgid "convenient:"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:33
#: lib/memex_web/templates/user_settings/edit.html.heex:89
#: lib/memex_web/templates/user_settings/edit.html.heex:31
#: lib/memex_web/templates/user_settings/edit.html.heex:85
#, elixir-autogen, elixir-format
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:62
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:14
#: lib/memex_web/live/home_live.html.heex:12
#, elixir-autogen, elixir-format
msgid "document notes about individual items or concepts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:32
#: lib/memex_web/live/home_live.html.heex:30
#, elixir-autogen, elixir-format
msgid "document your processes, attaching contexts to each step"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:34
#: lib/memex_web/live/invite_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "edit invite"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:29
#: lib/memex_web/templates/user_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:13
#: lib/memex_web/templates/user_session/new.html.heex:17
#: lib/memex_web/templates/user_settings/edit.html.heex:27
#, elixir-autogen, elixir-format
msgid "email"
msgstr ""
#: lib/memex_web/components/user_card.ex:29
#: lib/memex_web/components/core_components/user_card.html.heex:21
#, elixir-autogen, elixir-format
msgid "email unconfirmed"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:62
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:32
#: lib/memex_web/templates/user_settings/edit.html.heex:129
#: lib/memex_web/templates/user_settings/edit.html.heex:123
#, elixir-autogen, elixir-format
msgid "english"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:50
#: lib/memex_web/live/home_live.html.heex:45
#, elixir-autogen, elixir-format
msgid "features"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:135
#, elixir-autogen, elixir-format
msgid "get involved!"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:156
#: lib/memex_web/live/home_live.html.heex:149
#, elixir-autogen, elixir-format
msgid "help translate"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:85
#: lib/memex_web/live/home_live.html.heex:80
#, elixir-autogen, elixir-format
msgid "instance information"
msgstr ""
#: lib/memex_web/components/invite_card.ex:42
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:112
#: lib/memex_web/live/home_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "invite only"
msgstr ""
#: lib/memex_web/components/topbar.ex:73
#: lib/memex_web/live/invite_live/index.ex:42
#: lib/memex_web/components/core_components/topbar.html.heex:58
#: lib/memex_web/live/invite_live/index.ex:41
#: lib/memex_web/live/invite_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "invites"
@ -195,17 +165,18 @@ msgstr ""
msgid "log in"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:55
#: lib/memex_web/live/home_live.html.heex:50
#, elixir-autogen, elixir-format
msgid "multi-user:"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:38
#: lib/memex_web/live/invite_live/index.ex:37
#, elixir-autogen, elixir-format
msgid "new invite"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:73
#: lib/memex_web/templates/user_reset_password/edit.html.heex:16
#: lib/memex_web/templates/user_settings/edit.html.heex:69
#, elixir-autogen, elixir-format
msgid "new password"
msgstr ""
@ -215,12 +186,12 @@ msgstr ""
msgid "no invites 😔"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:23
#: lib/memex_web/live/note_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no notes found"
msgstr ""
#: lib/memex_web/components/topbar.ex:43
#: lib/memex_web/components/core_components/topbar.html.heex:28
#: lib/memex_web/live/note_live/index.ex:35
#: lib/memex_web/live/note_live/index.ex:43
#: lib/memex_web/live/note_live/index.html.heex:3
@ -228,12 +199,12 @@ msgstr ""
msgid "notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:11
#: lib/memex_web/live/home_live.html.heex:9
#, elixir-autogen, elixir-format
msgid "notes:"
msgstr ""
#: lib/memex_web/components/topbar.ex:61
#: lib/memex_web/components/core_components/topbar.html.heex:46
#: lib/memex_web/live/pipeline_live/index.ex:35
#: lib/memex_web/live/pipeline_live/index.ex:43
#: lib/memex_web/live/pipeline_live/index.html.heex:3
@ -241,27 +212,27 @@ msgstr ""
msgid "pipelines"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:29
#: lib/memex_web/live/home_live.html.heex:27
#, elixir-autogen, elixir-format
msgid "pipelines:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:67
#: lib/memex_web/live/home_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "privacy controls on a per-note, context or pipeline basis"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:64
#: lib/memex_web/live/home_live.html.heex:59
#, elixir-autogen, elixir-format
msgid "privacy:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:23
#: lib/memex_web/live/home_live.html.heex:21
#, elixir-autogen, elixir-format
msgid "provide context around a single topic and hotlink to your notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:111
#: lib/memex_web/live/home_live.html.heex:104
#, elixir-autogen, elixir-format
msgid "public signups"
msgstr ""
@ -271,12 +242,12 @@ msgstr ""
msgid "register"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:108
#: lib/memex_web/live/home_live.html.heex:101
#, elixir-autogen, elixir-format
msgid "registration:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:167
#: lib/memex_web/live/home_live.html.heex:160
#, elixir-autogen, elixir-format
msgid "report bugs or request features"
msgstr ""
@ -296,7 +267,7 @@ msgstr ""
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:77
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
@ -321,17 +292,17 @@ msgstr ""
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:114
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:118
#: lib/memex_web/live/home_live.html.heex:111
#, elixir-autogen, elixir-format
msgid "version:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:145
#: lib/memex_web/live/home_live.html.heex:138
#, elixir-autogen, elixir-format
msgid "view the source code"
msgstr ""
@ -348,9 +319,9 @@ msgstr ""
msgid "new note"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:17
#: lib/memex_web/live/note_live/index.html.heex:17
#: lib/memex_web/live/pipeline_live/index.html.heex:17
#: lib/memex_web/live/context_live/index.html.heex:18
#: lib/memex_web/live/note_live/index.html.heex:18
#: lib/memex_web/live/pipeline_live/index.html.heex:18
#, elixir-autogen, elixir-format
msgid "search"
msgstr ""
@ -360,7 +331,7 @@ msgstr ""
msgid "new context"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:23
#: lib/memex_web/live/context_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no contexts found"
msgstr ""
@ -376,7 +347,7 @@ msgstr ""
msgid "new pipeline"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:23
#: lib/memex_web/live/pipeline_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no pipelines found"
msgstr ""
@ -389,11 +360,11 @@ msgid "%{slug} created"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:57
#: lib/memex_web/live/context_live/show.ex:41
#: lib/memex_web/live/context_live/show.ex:40
#: lib/memex_web/live/note_live/index.ex:57
#: lib/memex_web/live/note_live/show.ex:41
#: lib/memex_web/live/note_live/show.ex:40
#: lib/memex_web/live/pipeline_live/index.ex:57
#: lib/memex_web/live/pipeline_live/show.ex:77
#: lib/memex_web/live/pipeline_live/show.ex:76
#, elixir-autogen, elixir-format
msgid "%{slug} deleted"
msgstr ""
@ -406,11 +377,11 @@ msgid "%{slug} saved"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:23
#: lib/memex_web/live/context_live/show.ex:48
#: lib/memex_web/live/context_live/show.ex:47
#: lib/memex_web/live/note_live/index.ex:23
#: lib/memex_web/live/note_live/show.ex:48
#: lib/memex_web/live/note_live/show.ex:47
#: lib/memex_web/live/pipeline_live/index.ex:23
#: lib/memex_web/live/pipeline_live/show.ex:125
#: lib/memex_web/live/pipeline_live/show.ex:122
#, elixir-autogen, elixir-format
msgid "edit %{slug}"
msgstr ""
@ -425,9 +396,9 @@ msgstr ""
msgid "slug"
msgstr ""
#: lib/memex_web/live/context_live/show.ex:19
#: lib/memex_web/live/note_live/show.ex:19
#: lib/memex_web/live/pipeline_live/show.ex:20
#: lib/memex_web/live/context_live/show.ex:18
#: lib/memex_web/live/note_live/show.ex:18
#: lib/memex_web/live/pipeline_live/show.ex:19
#, elixir-autogen, elixir-format
msgid "%{slug} could not be found"
msgstr ""
@ -448,12 +419,12 @@ msgstr ""
msgid "faq"
msgstr ""
#: lib/memex_web/components/topbar.ex:23
#: lib/memex_web/components/core_components/topbar.html.heex:8
#: lib/memex_web/live/home_live.html.heex:3
#: lib/memex_web/templates/error/error.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:9
#: lib/memex_web/views/layout_view.ex:15
#: lib/memex_web/views/layout_view.ex:14
#, elixir-autogen, elixir-format
msgid "memEx"
msgstr ""
@ -473,7 +444,7 @@ msgstr ""
msgid "%{title} created"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:96
#: lib/memex_web/live/pipeline_live/show.ex:94
#, elixir-autogen, elixir-format
msgid "%{title} deleted"
msgstr ""
@ -483,7 +454,7 @@ msgstr ""
msgid "%{title} saved"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:127
#: lib/memex_web/live/pipeline_live/show.ex:124
#, elixir-autogen, elixir-format
msgid "add step to %{slug}"
msgstr ""
@ -508,62 +479,62 @@ msgstr ""
msgid "use [[context-slug]] to link to a context"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:72
#: lib/memex_web/live/faq_live.html.heex:65
#, elixir-autogen, elixir-format
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#: 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:118
#: 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:62
#: lib/memex_web/live/faq_live.html.heex:59
#, 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."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:67
#: lib/memex_web/live/faq_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "i wanted to separate between a personal dictionary of concepts and then my thought processes that are built off of my experiences and life lessons. these are notes, and contexts, respectively."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:99
#: lib/memex_web/live/faq_live.html.heex:90
#, elixir-autogen, elixir-format
msgid "in my opinion, contexts should be like single-topic blog posts."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:83
#: lib/memex_web/live/faq_live.html.heex:76
#, elixir-autogen, elixir-format
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 ""
#: lib/memex_web/live/faq_live.html.heex:113
#: 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:31
#: lib/memex_web/live/faq_live.html.heex:28
#, elixir-autogen, elixir-format
msgid "memex"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:51
#: lib/memex_web/live/faq_live.html.heex:48
#, elixir-autogen, elixir-format
msgid "org-mode"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:20
#: lib/memex_web/live/faq_live.html.heex:17
#, elixir-autogen, elixir-format
msgid "some things that this memex is very loosely inspired by:"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:88
#: lib/memex_web/live/faq_live.html.heex:79
#, elixir-autogen, elixir-format
msgid "spoons? probably not. a particular brand of spoons that you really like? why not :)"
msgstr ""
@ -573,32 +544,32 @@ msgstr ""
msgid "this is a memex, used to document not just your notes, but also your perspectives and processes."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:96
#: lib/memex_web/live/faq_live.html.heex:87
#, elixir-autogen, elixir-format
msgid "what should my contexts be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:80
#: lib/memex_web/live/faq_live.html.heex:73
#, elixir-autogen, elixir-format
msgid "what should my notes be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:110
#: lib/memex_web/live/faq_live.html.heex:99
#, elixir-autogen, elixir-format
msgid "what should my pipelines be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:59
#: lib/memex_web/live/faq_live.html.heex:56
#, elixir-autogen, elixir-format
msgid "why split up into notes, contexts and pipelines?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:41
#: lib/memex_web/live/faq_live.html.heex:38
#, elixir-autogen, elixir-format
msgid "zettelkasten"
msgstr ""
#: lib/memex_web/views/layout_view.ex:11
#: lib/memex_web/views/layout_view.ex:10
#, elixir-autogen, elixir-format
msgid "memEx | %{title}"
msgstr ""
@ -608,22 +579,22 @@ msgstr ""
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:126
#: lib/memex_web/live/faq_live.html.heex:113
#, elixir-autogen, elixir-format
msgid "how many people should i invite?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:134
#: 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:139
#: lib/memex_web/live/faq_live.html.heex:122
#, 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 :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:129
#: lib/memex_web/live/faq_live.html.heex:116
#, elixir-autogen, elixir-format
msgid "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
msgstr ""
@ -633,32 +604,73 @@ msgstr ""
msgid "language"
msgstr ""
#: lib/memex_web/components/user_card.ex:23
#: lib/memex_web/components/core_components/user_card.html.heex:15
#, elixir-autogen, elixir-format, fuzzy
msgid "user confirmed on%{confirmed_datetime}"
msgstr ""
#: lib/memex_web/components/user_card.ex:34
#: lib/memex_web/components/core_components/user_card.html.heex:26
#, elixir-autogen, elixir-format, fuzzy
msgid "user registered on%{registered_datetime}"
msgstr ""
#: lib/memex_web/components/invite_card.ex:37
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:41
#: lib/memex_web/live/home_live.html.heex:36
#, elixir-autogen, elixir-format, fuzzy
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/invite_card.ex:32
#: lib/memex_web/components/core_components/invite_card.html.heex:12
#, elixir-autogen, elixir-format, fuzzy
msgid "uses left: %{uses_left_count}"
msgstr ""
#: lib/memex_web/components/invite_card.ex:52
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:128
#, elixir-autogen, elixir-format, fuzzy
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format, fuzzy
msgid "Email"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:29
#, elixir-autogen, elixir-format
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format, fuzzy
msgid "admins"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:23
#, elixir-autogen, elixir-format, fuzzy
msgid "keep me logged in for 60 days"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:21
#, elixir-autogen, elixir-format, fuzzy
msgid "name"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:24
#: lib/memex_web/templates/user_session/new.html.heex:20
#, elixir-autogen, elixir-format, fuzzy
msgid "password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:25
#, elixir-autogen, elixir-format, fuzzy
msgid "uses left"
msgstr ""

View File

@ -20,12 +20,6 @@ msgstr ""
msgid "Invalid email or password"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:14
#: lib/memex_web/templates/user_settings/edit.html.heex:67
#, elixir-autogen, elixir-format
msgid "Oops, something went wrong! Please check the errors below."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:63
#, elixir-autogen, elixir-format
msgid "Reset password link is invalid or it has expired."
@ -79,50 +73,46 @@ msgstr ""
msgid "must have the @ sign and no spaces"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:23
#: lib/memex_web/templates/user_settings/edit.html.heex:123
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! Please check the errors below"
msgstr ""
#: lib/memex/contexts/context.ex:58
#: lib/memex/contexts/context.ex:71
#: lib/memex/notes/note.ex:57
#: lib/memex/notes/note.ex:70
#: lib/memex/pipelines/pipeline.ex:60
#: lib/memex/pipelines/pipeline.ex:73
#: lib/memex/contexts/context.ex:57
#: lib/memex/contexts/context.ex:70
#: lib/memex/notes/note.ex:56
#: lib/memex/notes/note.ex:69
#: lib/memex/pipelines/pipeline.ex:59
#: lib/memex/pipelines/pipeline.ex:72
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted"
msgstr ""
#: lib/memex_web/templates/error/error.html.heex:28
#: lib/memex_web/templates/error/error.html.heex:31
#, elixir-autogen, elixir-format
msgid "go back home"
msgstr ""
#: lib/memex_web/views/error_view.ex:11
#: lib/memex_web/views/error_view.ex:10
#, elixir-autogen, elixir-format
msgid "internal server error"
msgstr ""
#: lib/memex_web/views/error_view.ex:9
#: lib/memex_web/views/error_view.ex:8
#, elixir-autogen, elixir-format
msgid "not found"
msgstr ""
#: lib/memex_web/views/error_view.ex:10
#: lib/memex_web/views/error_view.ex:9
#, elixir-autogen, elixir-format
msgid "unauthorized"
msgstr ""
#: lib/memex/contexts/context.ex:84
#: lib/memex/notes/note.ex:83
#: lib/memex/pipelines/pipeline.ex:86
#: lib/memex/contexts/context.ex:83
#: lib/memex/notes/note.ex:82
#: lib/memex/pipelines/pipeline.ex:85
#, elixir-autogen, elixir-format, fuzzy
msgid "invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:13
#: lib/memex_web/templates/user_reset_password/edit.html.heex:13
#: lib/memex_web/templates/user_settings/edit.html.heex:64
#, elixir-autogen, elixir-format, fuzzy
msgid "oops, something went wrong! please check the errors below."
msgstr ""
@ -132,7 +122,7 @@ msgstr ""
msgid "sorry, this invite was not found or expired"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:19
#: lib/memex_web/live/invite_live/index.ex:18
#, elixir-autogen, elixir-format, fuzzy
msgid "you are not authorized to view this page"
msgstr ""
@ -146,3 +136,9 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy
msgid "unable to delete user"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:22
#: lib/memex_web/templates/user_settings/edit.html.heex:118
#, elixir-autogen, elixir-format, fuzzy
msgid "oops, something went wrong! please check the errors below"
msgstr ""

View File

@ -15,27 +15,27 @@ msgstr ""
msgid "%{email} confirmed successfully."
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:54
#: lib/memex_web/live/invite_live/index.ex:53
#, elixir-autogen, elixir-format
msgid "%{invite_name} deleted succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:115
#: lib/memex_web/live/invite_live/index.ex:114
#, elixir-autogen, elixir-format
msgid "%{invite_name} disabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:91
#: lib/memex_web/live/invite_live/index.ex:90
#, elixir-autogen, elixir-format
msgid "%{invite_name} enabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:69
#: lib/memex_web/live/invite_live/index.ex:68
#, elixir-autogen, elixir-format
msgid "%{invite_name} updated succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:140
#: lib/memex_web/live/invite_live/index.ex:137
#, elixir-autogen, elixir-format
msgid "%{user_email} deleted succesfully"
msgstr ""
@ -55,49 +55,43 @@ msgstr ""
msgid "Password reset successfully."
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:31
#: lib/memex_web/live/invite_live/form_component.html.heex:34
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:136
#: lib/memex_web/templates/user_settings/edit.html.heex:130
#, elixir-autogen, elixir-format
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:97
#: lib/memex_web/live/invite_live/index.html.heex:125
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete %{email}? This action is permanent!"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:47
#: lib/memex_web/live/invite_live/index.html.heex:53
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete the invite for %{invite_name}?"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:155
#: lib/memex_web/templates/user_settings/edit.html.heex:149
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/topbar.ex:90
#: lib/memex_web/components/core_components/topbar.html.heex:74
#, elixir-autogen, elixir-format
msgid "are you sure you want to log out?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:72
#: lib/memex_web/live/invite_live/index.html.heex:80
#, elixir-autogen, elixir-format
msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:45
#: lib/memex_web/live/context_live/index.html.heex:46
#: lib/memex_web/live/context_live/show.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:45
#: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:45
#: lib/memex_web/live/pipeline_live/index.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:115
#: lib/memex_web/live/pipeline_live/show.html.heex:117
#, elixir-autogen, elixir-format
msgid "are you sure?"
msgstr ""
@ -112,7 +106,7 @@ msgstr ""
msgid "language updated successfully."
msgstr ""
#: lib/memex_web/live/home_live.html.heex:95
#: lib/memex_web/live/home_live.html.heex:90
#, elixir-autogen, elixir-format, fuzzy
msgid "register to setup memEx"
msgstr ""
@ -127,7 +121,7 @@ msgstr ""
msgid "%{name} updated successfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:128
#: lib/memex_web/live/invite_live/index.ex:126
#, elixir-autogen, elixir-format, fuzzy
msgid "copied to clipboard"
msgstr ""
@ -156,3 +150,9 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:113
#: lib/memex_web/live/invite_live/index.html.heex:141
#, elixir-autogen, elixir-format, fuzzy
msgid "are you sure you want to delete %{email}? this action is permanent!"
msgstr ""

View File

@ -10,26 +10,11 @@
msgid ""
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:86
#, elixir-autogen, elixir-format
msgid "Admins"
msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:8
#, elixir-autogen, elixir-format
msgid "Confirm your account"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:25
#, elixir-autogen, elixir-format
msgid "Keep me logged in for 60 days"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:21
#, elixir-autogen, elixir-format
msgid "Name"
msgstr ""
#: lib/memex_web/templates/layout/live.html.heex:43
#, elixir-autogen, elixir-format
msgid "Reconnecting..."
@ -40,11 +25,6 @@ msgstr ""
msgid "Reset your password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:25
#, elixir-autogen, elixir-format
msgid "Uses left"
msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:19
#: lib/memex_web/live/note_live/show.html.heex:19
#: lib/memex_web/live/pipeline_live/show.html.heex:27
@ -52,22 +32,23 @@ msgstr ""
msgid "Visibility: %{visibility}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:76
#: lib/memex_web/live/home_live.html.heex:71
#, elixir-autogen, elixir-format
msgid "accessible from any internet-capable device"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:90
#: lib/memex_web/live/home_live.html.heex:85
#, elixir-autogen, elixir-format
msgid "admins:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:58
#: lib/memex_web/live/home_live.html.heex:53
#, elixir-autogen, elixir-format
msgid "built with sharing and collaboration in mind"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:80
#: lib/memex_web/templates/user_reset_password/edit.html.heex:20
#: lib/memex_web/templates/user_settings/edit.html.heex:76
#, elixir-autogen, elixir-format
msgid "confirm new password"
msgstr ""
@ -77,7 +58,7 @@ msgstr ""
msgid "content"
msgstr ""
#: lib/memex_web/components/topbar.ex:52
#: lib/memex_web/components/core_components/topbar.html.heex:37
#: lib/memex_web/live/context_live/index.ex:35
#: lib/memex_web/live/context_live/index.ex:43
#: lib/memex_web/live/context_live/index.html.heex:3
@ -85,95 +66,93 @@ msgstr ""
msgid "contexts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:20
#: lib/memex_web/live/home_live.html.heex:18
#, elixir-autogen, elixir-format
msgid "contexts:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:73
#: lib/memex_web/live/home_live.html.heex:68
#, elixir-autogen, elixir-format
msgid "convenient:"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:33
#: lib/memex_web/templates/user_settings/edit.html.heex:89
#: lib/memex_web/templates/user_settings/edit.html.heex:31
#: lib/memex_web/templates/user_settings/edit.html.heex:85
#, elixir-autogen, elixir-format
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:62
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:14
#: lib/memex_web/live/home_live.html.heex:12
#, elixir-autogen, elixir-format
msgid "document notes about individual items or concepts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:32
#: lib/memex_web/live/home_live.html.heex:30
#, elixir-autogen, elixir-format
msgid "document your processes, attaching contexts to each step"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:34
#: lib/memex_web/live/invite_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "edit invite"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:29
#: lib/memex_web/templates/user_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:13
#: lib/memex_web/templates/user_session/new.html.heex:17
#: lib/memex_web/templates/user_settings/edit.html.heex:27
#, elixir-autogen, elixir-format
msgid "email"
msgstr ""
#: lib/memex_web/components/user_card.ex:29
#: lib/memex_web/components/core_components/user_card.html.heex:21
#, elixir-autogen, elixir-format
msgid "email unconfirmed"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:62
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:32
#: lib/memex_web/templates/user_settings/edit.html.heex:129
#: lib/memex_web/templates/user_settings/edit.html.heex:123
#, elixir-autogen, elixir-format
msgid "english"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:50
#: lib/memex_web/live/home_live.html.heex:45
#, elixir-autogen, elixir-format
msgid "features"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:135
#, elixir-autogen, elixir-format
msgid "get involved!"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:156
#: lib/memex_web/live/home_live.html.heex:149
#, elixir-autogen, elixir-format
msgid "help translate"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:85
#: lib/memex_web/live/home_live.html.heex:80
#, elixir-autogen, elixir-format
msgid "instance information"
msgstr ""
#: lib/memex_web/components/invite_card.ex:42
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:112
#: lib/memex_web/live/home_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "invite only"
msgstr ""
#: lib/memex_web/components/topbar.ex:73
#: lib/memex_web/live/invite_live/index.ex:42
#: lib/memex_web/components/core_components/topbar.html.heex:58
#: lib/memex_web/live/invite_live/index.ex:41
#: lib/memex_web/live/invite_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "invites"
@ -184,17 +163,18 @@ msgstr ""
msgid "log in"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:55
#: lib/memex_web/live/home_live.html.heex:50
#, elixir-autogen, elixir-format
msgid "multi-user:"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:38
#: lib/memex_web/live/invite_live/index.ex:37
#, elixir-autogen, elixir-format
msgid "new invite"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:73
#: lib/memex_web/templates/user_reset_password/edit.html.heex:16
#: lib/memex_web/templates/user_settings/edit.html.heex:69
#, elixir-autogen, elixir-format
msgid "new password"
msgstr ""
@ -204,12 +184,12 @@ msgstr ""
msgid "no invites 😔"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:23
#: lib/memex_web/live/note_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no notes found"
msgstr ""
#: lib/memex_web/components/topbar.ex:43
#: lib/memex_web/components/core_components/topbar.html.heex:28
#: lib/memex_web/live/note_live/index.ex:35
#: lib/memex_web/live/note_live/index.ex:43
#: lib/memex_web/live/note_live/index.html.heex:3
@ -217,12 +197,12 @@ msgstr ""
msgid "notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:11
#: lib/memex_web/live/home_live.html.heex:9
#, elixir-autogen, elixir-format
msgid "notes:"
msgstr ""
#: lib/memex_web/components/topbar.ex:61
#: lib/memex_web/components/core_components/topbar.html.heex:46
#: lib/memex_web/live/pipeline_live/index.ex:35
#: lib/memex_web/live/pipeline_live/index.ex:43
#: lib/memex_web/live/pipeline_live/index.html.heex:3
@ -230,27 +210,27 @@ msgstr ""
msgid "pipelines"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:29
#: lib/memex_web/live/home_live.html.heex:27
#, elixir-autogen, elixir-format
msgid "pipelines:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:67
#: lib/memex_web/live/home_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "privacy controls on a per-note, context or pipeline basis"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:64
#: lib/memex_web/live/home_live.html.heex:59
#, elixir-autogen, elixir-format
msgid "privacy:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:23
#: lib/memex_web/live/home_live.html.heex:21
#, elixir-autogen, elixir-format
msgid "provide context around a single topic and hotlink to your notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:111
#: lib/memex_web/live/home_live.html.heex:104
#, elixir-autogen, elixir-format
msgid "public signups"
msgstr ""
@ -260,12 +240,12 @@ msgstr ""
msgid "register"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:108
#: lib/memex_web/live/home_live.html.heex:101
#, elixir-autogen, elixir-format
msgid "registration:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:167
#: lib/memex_web/live/home_live.html.heex:160
#, elixir-autogen, elixir-format
msgid "report bugs or request features"
msgstr ""
@ -285,7 +265,7 @@ msgstr ""
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:77
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
@ -310,17 +290,17 @@ msgstr ""
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:114
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:118
#: lib/memex_web/live/home_live.html.heex:111
#, elixir-autogen, elixir-format
msgid "version:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:145
#: lib/memex_web/live/home_live.html.heex:138
#, elixir-autogen, elixir-format
msgid "view the source code"
msgstr ""
@ -337,9 +317,9 @@ msgstr ""
msgid "new note"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:17
#: lib/memex_web/live/note_live/index.html.heex:17
#: lib/memex_web/live/pipeline_live/index.html.heex:17
#: lib/memex_web/live/context_live/index.html.heex:18
#: lib/memex_web/live/note_live/index.html.heex:18
#: lib/memex_web/live/pipeline_live/index.html.heex:18
#, elixir-autogen, elixir-format
msgid "search"
msgstr ""
@ -349,7 +329,7 @@ msgstr ""
msgid "new context"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:23
#: lib/memex_web/live/context_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no contexts found"
msgstr ""
@ -365,7 +345,7 @@ msgstr ""
msgid "new pipeline"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:23
#: lib/memex_web/live/pipeline_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no pipelines found"
msgstr ""
@ -378,11 +358,11 @@ msgid "%{slug} created"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:57
#: lib/memex_web/live/context_live/show.ex:41
#: lib/memex_web/live/context_live/show.ex:40
#: lib/memex_web/live/note_live/index.ex:57
#: lib/memex_web/live/note_live/show.ex:41
#: lib/memex_web/live/note_live/show.ex:40
#: lib/memex_web/live/pipeline_live/index.ex:57
#: lib/memex_web/live/pipeline_live/show.ex:77
#: lib/memex_web/live/pipeline_live/show.ex:76
#, elixir-autogen, elixir-format
msgid "%{slug} deleted"
msgstr ""
@ -395,11 +375,11 @@ msgid "%{slug} saved"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:23
#: lib/memex_web/live/context_live/show.ex:48
#: lib/memex_web/live/context_live/show.ex:47
#: lib/memex_web/live/note_live/index.ex:23
#: lib/memex_web/live/note_live/show.ex:48
#: lib/memex_web/live/note_live/show.ex:47
#: lib/memex_web/live/pipeline_live/index.ex:23
#: lib/memex_web/live/pipeline_live/show.ex:125
#: lib/memex_web/live/pipeline_live/show.ex:122
#, elixir-autogen, elixir-format
msgid "edit %{slug}"
msgstr ""
@ -414,9 +394,9 @@ msgstr ""
msgid "slug"
msgstr ""
#: lib/memex_web/live/context_live/show.ex:19
#: lib/memex_web/live/note_live/show.ex:19
#: lib/memex_web/live/pipeline_live/show.ex:20
#: lib/memex_web/live/context_live/show.ex:18
#: lib/memex_web/live/note_live/show.ex:18
#: lib/memex_web/live/pipeline_live/show.ex:19
#, elixir-autogen, elixir-format
msgid "%{slug} could not be found"
msgstr ""
@ -437,12 +417,12 @@ msgstr ""
msgid "faq"
msgstr ""
#: lib/memex_web/components/topbar.ex:23
#: lib/memex_web/components/core_components/topbar.html.heex:8
#: lib/memex_web/live/home_live.html.heex:3
#: lib/memex_web/templates/error/error.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:9
#: lib/memex_web/views/layout_view.ex:15
#: lib/memex_web/views/layout_view.ex:14
#, elixir-autogen, elixir-format
msgid "memEx"
msgstr ""
@ -462,7 +442,7 @@ msgstr ""
msgid "%{title} created"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:96
#: lib/memex_web/live/pipeline_live/show.ex:94
#, elixir-autogen, elixir-format
msgid "%{title} deleted"
msgstr ""
@ -472,7 +452,7 @@ msgstr ""
msgid "%{title} saved"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:127
#: lib/memex_web/live/pipeline_live/show.ex:124
#, elixir-autogen, elixir-format
msgid "add step to %{slug}"
msgstr ""
@ -497,62 +477,62 @@ msgstr ""
msgid "use [[context-slug]] to link to a context"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:72
#: lib/memex_web/live/faq_live.html.heex:65
#, elixir-autogen, elixir-format
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:102
#: 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:118
#: 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:62
#: lib/memex_web/live/faq_live.html.heex:59
#, 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."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:67
#: lib/memex_web/live/faq_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "i wanted to separate between a personal dictionary of concepts and then my thought processes that are built off of my experiences and life lessons. these are notes, and contexts, respectively."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:99
#: lib/memex_web/live/faq_live.html.heex:90
#, elixir-autogen, elixir-format
msgid "in my opinion, contexts should be like single-topic blog posts."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:83
#: lib/memex_web/live/faq_live.html.heex:76
#, elixir-autogen, elixir-format
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 ""
#: lib/memex_web/live/faq_live.html.heex:113
#: 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:31
#: lib/memex_web/live/faq_live.html.heex:28
#, elixir-autogen, elixir-format
msgid "memex"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:51
#: lib/memex_web/live/faq_live.html.heex:48
#, elixir-autogen, elixir-format
msgid "org-mode"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:20
#: lib/memex_web/live/faq_live.html.heex:17
#, elixir-autogen, elixir-format
msgid "some things that this memex is very loosely inspired by:"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:88
#: lib/memex_web/live/faq_live.html.heex:79
#, elixir-autogen, elixir-format
msgid "spoons? probably not. a particular brand of spoons that you really like? why not :)"
msgstr ""
@ -562,32 +542,32 @@ msgstr ""
msgid "this is a memex, used to document not just your notes, but also your perspectives and processes."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:96
#: lib/memex_web/live/faq_live.html.heex:87
#, elixir-autogen, elixir-format
msgid "what should my contexts be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:80
#: lib/memex_web/live/faq_live.html.heex:73
#, elixir-autogen, elixir-format
msgid "what should my notes be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:110
#: lib/memex_web/live/faq_live.html.heex:99
#, elixir-autogen, elixir-format
msgid "what should my pipelines be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:59
#: lib/memex_web/live/faq_live.html.heex:56
#, elixir-autogen, elixir-format
msgid "why split up into notes, contexts and pipelines?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:41
#: lib/memex_web/live/faq_live.html.heex:38
#, elixir-autogen, elixir-format
msgid "zettelkasten"
msgstr ""
#: lib/memex_web/views/layout_view.ex:11
#: lib/memex_web/views/layout_view.ex:10
#, elixir-autogen, elixir-format
msgid "memEx | %{title}"
msgstr ""
@ -597,22 +577,22 @@ msgstr ""
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:126
#: lib/memex_web/live/faq_live.html.heex:113
#, elixir-autogen, elixir-format
msgid "how many people should i invite?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:134
#: 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:139
#: lib/memex_web/live/faq_live.html.heex:122
#, 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 :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:129
#: lib/memex_web/live/faq_live.html.heex:116
#, elixir-autogen, elixir-format
msgid "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
msgstr ""
@ -622,32 +602,73 @@ msgstr ""
msgid "language"
msgstr ""
#: lib/memex_web/components/user_card.ex:23
#: lib/memex_web/components/core_components/user_card.html.heex:15
#, elixir-autogen, elixir-format
msgid "user confirmed on%{confirmed_datetime}"
msgstr ""
#: lib/memex_web/components/user_card.ex:34
#: lib/memex_web/components/core_components/user_card.html.heex:26
#, elixir-autogen, elixir-format
msgid "user registered on%{registered_datetime}"
msgstr ""
#: lib/memex_web/components/invite_card.ex:37
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:41
#: lib/memex_web/live/home_live.html.heex:36
#, elixir-autogen, elixir-format
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/invite_card.ex:32
#: lib/memex_web/components/core_components/invite_card.html.heex:12
#, elixir-autogen, elixir-format
msgid "uses left: %{uses_left_count}"
msgstr ""
#: lib/memex_web/components/invite_card.ex:52
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:128
#, elixir-autogen, elixir-format
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:29
#, elixir-autogen, elixir-format
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format
msgid "admins"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:23
#, elixir-autogen, elixir-format
msgid "keep me logged in for 60 days"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:21
#, elixir-autogen, elixir-format
msgid "name"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:24
#: lib/memex_web/templates/user_session/new.html.heex:20
#, elixir-autogen, elixir-format
msgid "password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:25
#, elixir-autogen, elixir-format
msgid "uses left"
msgstr ""

View File

@ -0,0 +1,231 @@
## "msgid"s in this file come from POT (.pot) files.
###
### Do not add, change, or remove "msgid"s manually here as
### they're tied to the ones in the corresponding POT file
### (with the same domain).
###
### Use "mix gettext.extract --merge" or "mix gettext.merge"
### to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex_web/templates/user_confirmation/new.html.heex:3
#: lib/memex_web/templates/user_confirmation/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "Resend confirmation instructions"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:3
#: lib/memex_web/templates/user_reset_password/edit.html.heex:29
#, elixir-autogen, elixir-format
msgid "Reset password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:32
#, elixir-autogen, elixir-format
msgid "Save"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:43
#, elixir-autogen, elixir-format
msgid "change email"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:111
#: lib/memex_web/templates/user_settings/edit.html.heex:128
#, elixir-autogen, elixir-format
msgid "change language"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:57
#: lib/memex_web/templates/user_settings/edit.html.heex:97
#, elixir-autogen, elixir-format
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:94
#, elixir-autogen, elixir-format
msgid "create invite"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:49
#: lib/memex_web/live/context_live/show.html.heex:41
#: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:41
#: lib/memex_web/live/pipeline_live/index.html.heex:51
#: lib/memex_web/live/pipeline_live/show.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:120
#, elixir-autogen, elixir-format
msgid "delete"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:151
#, elixir-autogen, elixir-format
msgid "delete user"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:39
#: lib/memex_web/live/context_live/show.html.heex:31
#: lib/memex_web/live/note_live/index.html.heex:39
#: lib/memex_web/live/note_live/show.html.heex:31
#: lib/memex_web/live/pipeline_live/index.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:39
#: lib/memex_web/live/pipeline_live/show.html.heex:109
#, elixir-autogen, elixir-format
msgid "edit"
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:107
#: lib/memex_web/templates/user_confirmation/new.html.heex:32
#: lib/memex_web/templates/user_registration/new.html.heex:44
#: lib/memex_web/templates/user_reset_password/edit.html.heex:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:32
#: lib/memex_web/templates/user_session/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:28
#, elixir-autogen, elixir-format
msgid "log in"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new context"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:60
#, elixir-autogen, elixir-format
msgid "new note"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:62
#, elixir-autogen, elixir-format
msgid "new pipeline"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:98
#: lib/memex_web/templates/user_confirmation/new.html.heex:29
#: lib/memex_web/templates/user_registration/new.html.heex:3
#: lib/memex_web/templates/user_registration/new.html.heex:37
#: lib/memex_web/templates/user_reset_password/edit.html.heex:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:29
#: lib/memex_web/templates/user_session/new.html.heex:39
#, elixir-autogen, elixir-format
msgid "register"
msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:40
#: lib/memex_web/live/note_live/form_component.html.heex:40
#: lib/memex_web/live/pipeline_live/form_component.html.heex:40
#: lib/memex_web/live/step_live/form_component.html.heex:28
#, elixir-autogen, elixir-format
msgid "save"
msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:24
#: lib/memex_web/live/note_live/show.html.heex:24
#: lib/memex_web/live/pipeline_live/show.html.heex:32
#, elixir-autogen, elixir-format
msgid "back"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:135
#, elixir-autogen, elixir-format
msgid "add step"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:47
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:42
#, elixir-autogen, elixir-format
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:142
#, elixir-autogen, elixir-format
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:33
#, elixir-autogen, elixir-format
msgid "copy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:30
#, elixir-autogen, elixir-format
msgid "copy invite link for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:47
#: lib/memex_web/live/context_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:47
#: lib/memex_web/live/note_live/show.html.heex:39
#, elixir-autogen, elixir-format
msgid "delete %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:48
#: lib/memex_web/live/pipeline_live/show.html.heex:47
#, elixir-autogen, elixir-format
msgid "delete %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:118
#, elixir-autogen, elixir-format
msgid "delete %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#, elixir-autogen, elixir-format
msgid "delete invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{context_slug}"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{note_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:37
#, elixir-autogen, elixir-format
msgid "edit %{pipeline_slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:107
#, elixir-autogen, elixir-format
msgid "edit %{step_title}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:41
#, elixir-autogen, elixir-format
msgid "edit invite for %{invite_name}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:97
#, elixir-autogen, elixir-format
msgid "move %{step_title} down"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:81
#, elixir-autogen, elixir-format
msgid "move %{step_title} up"
msgstr ""

View File

@ -0,0 +1,675 @@
## "msgid"s in this file come from POT (.pot) files.
###
### Do not add, change, or remove "msgid"s manually here as
### they're tied to the ones in the corresponding POT file
### (with the same domain).
###
### Use "mix gettext.extract --merge" or "mix gettext.merge"
### to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex_web/controllers/user_confirmation_controller.ex:8
#, elixir-autogen, elixir-format
msgid "Confirm your account"
msgstr ""
#: lib/memex_web/templates/layout/live.html.heex:43
#, elixir-autogen, elixir-format
msgid "Reconnecting..."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:36
#, elixir-autogen, elixir-format
msgid "Reset your password"
msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:19
#: lib/memex_web/live/note_live/show.html.heex:19
#: lib/memex_web/live/pipeline_live/show.html.heex:27
#, elixir-autogen, elixir-format
msgid "Visibility: %{visibility}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:71
#, elixir-autogen, elixir-format
msgid "accessible from any internet-capable device"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:85
#, elixir-autogen, elixir-format
msgid "admins:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:53
#, elixir-autogen, elixir-format
msgid "built with sharing and collaboration in mind"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:20
#: lib/memex_web/templates/user_settings/edit.html.heex:76
#, elixir-autogen, elixir-format
msgid "confirm new password"
msgstr ""
#: lib/memex_web/live/note_live/form_component.html.heex:23
#, elixir-autogen, elixir-format
msgid "content"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:37
#: lib/memex_web/live/context_live/index.ex:35
#: lib/memex_web/live/context_live/index.ex:43
#: lib/memex_web/live/context_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "contexts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:18
#, elixir-autogen, elixir-format
msgid "contexts:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:68
#, elixir-autogen, elixir-format
msgid "convenient:"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:31
#: lib/memex_web/templates/user_settings/edit.html.heex:85
#, elixir-autogen, elixir-format
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:12
#, elixir-autogen, elixir-format
msgid "document notes about individual items or concepts"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:30
#, elixir-autogen, elixir-format
msgid "document your processes, attaching contexts to each step"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:33
#, elixir-autogen, elixir-format
msgid "edit invite"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:13
#: lib/memex_web/templates/user_session/new.html.heex:17
#: lib/memex_web/templates/user_settings/edit.html.heex:27
#, elixir-autogen, elixir-format
msgid "email"
msgstr ""
#: lib/memex_web/components/core_components/user_card.html.heex:21
#, elixir-autogen, elixir-format
msgid "email unconfirmed"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:32
#: lib/memex_web/templates/user_settings/edit.html.heex:123
#, elixir-autogen, elixir-format
msgid "english"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:45
#, elixir-autogen, elixir-format
msgid "features"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:149
#, elixir-autogen, elixir-format
msgid "help translate"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:80
#, elixir-autogen, elixir-format
msgid "instance information"
msgstr ""
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:105
#, elixir-autogen, elixir-format
msgid "invite only"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:58
#: lib/memex_web/live/invite_live/index.ex:41
#: lib/memex_web/live/invite_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "invites"
msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:8
#, elixir-autogen, elixir-format
msgid "log in"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:50
#, elixir-autogen, elixir-format
msgid "multi-user:"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:37
#, elixir-autogen, elixir-format
msgid "new invite"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:16
#: lib/memex_web/templates/user_settings/edit.html.heex:69
#, elixir-autogen, elixir-format
msgid "new password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:8
#, elixir-autogen, elixir-format
msgid "no invites 😔"
msgstr ""
#: lib/memex_web/live/note_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no notes found"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:28
#: lib/memex_web/live/note_live/index.ex:35
#: lib/memex_web/live/note_live/index.ex:43
#: lib/memex_web/live/note_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:9
#, elixir-autogen, elixir-format
msgid "notes:"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:46
#: lib/memex_web/live/pipeline_live/index.ex:35
#: lib/memex_web/live/pipeline_live/index.ex:43
#: lib/memex_web/live/pipeline_live/index.html.heex:3
#, elixir-autogen, elixir-format
msgid "pipelines"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:27
#, elixir-autogen, elixir-format
msgid "pipelines:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "privacy controls on a per-note, context or pipeline basis"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:59
#, elixir-autogen, elixir-format
msgid "privacy:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:21
#, elixir-autogen, elixir-format
msgid "provide context around a single topic and hotlink to your notes"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:104
#, elixir-autogen, elixir-format
msgid "public signups"
msgstr ""
#: lib/memex_web/controllers/user_registration_controller.ex:32
#, elixir-autogen, elixir-format
msgid "register"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:101
#, elixir-autogen, elixir-format
msgid "registration:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:160
#, elixir-autogen, elixir-format
msgid "report bugs or request features"
msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:41
#: lib/memex_web/live/note_live/form_component.html.heex:41
#: lib/memex_web/live/pipeline_live/form_component.html.heex:41
#: lib/memex_web/live/step_live/form_component.html.heex:29
#, elixir-autogen, elixir-format
msgid "saving..."
msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:37
#: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:37
#, elixir-autogen, elixir-format
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:10
#: lib/memex_web/templates/user_settings/edit.html.heex:3
#, elixir-autogen, elixir-format
msgid "settings"
msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:30
#: lib/memex_web/live/note_live/form_component.html.heex:30
#: lib/memex_web/live/pipeline_live/form_component.html.heex:30
#, elixir-autogen, elixir-format
msgid "tag1,tag2"
msgstr ""
#: lib/memex_web/components/contexts_table_component.ex:48
#: lib/memex_web/components/notes_table_component.ex:48
#: lib/memex_web/components/pipelines_table_component.ex:49
#, elixir-autogen, elixir-format
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:111
#, elixir-autogen, elixir-format
msgid "version:"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:138
#, elixir-autogen, elixir-format
msgid "view the source code"
msgstr ""
#: lib/memex_web/components/contexts_table_component.ex:49
#: lib/memex_web/components/notes_table_component.ex:49
#: lib/memex_web/components/pipelines_table_component.ex:50
#, elixir-autogen, elixir-format
msgid "visibility"
msgstr ""
#: lib/memex_web/live/note_live/index.ex:29
#, elixir-autogen, elixir-format
msgid "new note"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:18
#: lib/memex_web/live/note_live/index.html.heex:18
#: lib/memex_web/live/pipeline_live/index.html.heex:18
#, elixir-autogen, elixir-format
msgid "search"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:29
#, elixir-autogen, elixir-format
msgid "new context"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no contexts found"
msgstr ""
#: lib/memex_web/components/pipelines_table_component.ex:48
#: lib/memex_web/live/pipeline_live/form_component.html.heex:23
#, elixir-autogen, elixir-format
msgid "description"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.ex:29
#, elixir-autogen, elixir-format
msgid "new pipeline"
msgstr ""
#: lib/memex_web/live/pipeline_live/index.html.heex:24
#, elixir-autogen, elixir-format
msgid "no pipelines found"
msgstr ""
#: lib/memex_web/live/context_live/form_component.ex:61
#: lib/memex_web/live/note_live/form_component.ex:60
#: lib/memex_web/live/pipeline_live/form_component.ex:65
#, elixir-autogen, elixir-format
msgid "%{slug} created"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:57
#: lib/memex_web/live/context_live/show.ex:40
#: lib/memex_web/live/note_live/index.ex:57
#: lib/memex_web/live/note_live/show.ex:40
#: lib/memex_web/live/pipeline_live/index.ex:57
#: lib/memex_web/live/pipeline_live/show.ex:76
#, elixir-autogen, elixir-format
msgid "%{slug} deleted"
msgstr ""
#: lib/memex_web/live/context_live/form_component.ex:44
#: lib/memex_web/live/note_live/form_component.ex:43
#: lib/memex_web/live/pipeline_live/form_component.ex:48
#, elixir-autogen, elixir-format
msgid "%{slug} saved"
msgstr ""
#: lib/memex_web/live/context_live/index.ex:23
#: lib/memex_web/live/context_live/show.ex:47
#: lib/memex_web/live/note_live/index.ex:23
#: lib/memex_web/live/note_live/show.ex:47
#: lib/memex_web/live/pipeline_live/index.ex:23
#: lib/memex_web/live/pipeline_live/show.ex:122
#, elixir-autogen, elixir-format
msgid "edit %{slug}"
msgstr ""
#: lib/memex_web/components/contexts_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/live/context_live/form_component.html.heex:14
#: lib/memex_web/live/note_live/form_component.html.heex:14
#: lib/memex_web/live/pipeline_live/form_component.html.heex:14
#, elixir-autogen, elixir-format
msgid "slug"
msgstr ""
#: lib/memex_web/live/context_live/show.ex:18
#: lib/memex_web/live/note_live/show.ex:18
#: lib/memex_web/live/pipeline_live/show.ex:19
#, elixir-autogen, elixir-format
msgid "%{slug} could not be found"
msgstr ""
#: lib/memex_web/live/home_live.ex:15
#, elixir-autogen, elixir-format
msgid "home"
msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:23
#, elixir-autogen, elixir-format
msgid "use [[note-slug]] to link to a note"
msgstr ""
#: lib/memex_web/live/faq_live.ex:10
#: lib/memex_web/live/faq_live.html.heex:3
#, elixir-autogen, elixir-format
msgid "faq"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:8
#: lib/memex_web/live/home_live.html.heex:3
#: lib/memex_web/templates/error/error.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:8
#: lib/memex_web/templates/layout/root.html.heex:9
#: lib/memex_web/views/layout_view.ex:14
#, elixir-autogen, elixir-format
msgid "memEx"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:11
#, elixir-autogen, elixir-format
msgid "what is this?"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:67
#, elixir-autogen, elixir-format
msgid "%{position}. %{title}"
msgstr ""
#: lib/memex_web/live/step_live/form_component.ex:67
#, elixir-autogen, elixir-format
msgid "%{title} created"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:94
#, elixir-autogen, elixir-format
msgid "%{title} deleted"
msgstr ""
#: lib/memex_web/live/step_live/form_component.ex:43
#, elixir-autogen, elixir-format
msgid "%{title} saved"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.ex:124
#, elixir-autogen, elixir-format
msgid "add step to %{slug}"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:61
#, elixir-autogen, elixir-format
msgid "no steps"
msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:56
#, elixir-autogen, elixir-format
msgid "steps:"
msgstr ""
#: lib/memex_web/live/step_live/form_component.html.heex:14
#, elixir-autogen, elixir-format
msgid "title"
msgstr ""
#: lib/memex_web/live/step_live/form_component.html.heex:23
#, elixir-autogen, elixir-format
msgid "use [[context-slug]] to link to a context"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:65
#, elixir-autogen, elixir-format
msgid "finally, i wanted to externalize the processes for common situations that use these thought processes at discrete steps. these are pipelines!"
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
#, 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."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:62
#, elixir-autogen, elixir-format
msgid "i wanted to separate between a personal dictionary of concepts and then my thought processes that are built off of my experiences and life lessons. these are notes, and contexts, respectively."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:90
#, elixir-autogen, elixir-format
msgid "in my opinion, contexts should be like single-topic blog posts."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:76
#, elixir-autogen, elixir-format
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 ""
#: 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
#, elixir-autogen, elixir-format
msgid "memex"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:48
#, elixir-autogen, elixir-format
msgid "org-mode"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:17
#, elixir-autogen, elixir-format
msgid "some things that this memex is very loosely inspired by:"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:79
#, elixir-autogen, elixir-format
msgid "spoons? probably not. a particular brand of spoons that you really like? why not :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:14
#, elixir-autogen, elixir-format
msgid "this is a memex, used to document not just your notes, but also your perspectives and processes."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:87
#, elixir-autogen, elixir-format
msgid "what should my contexts be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:73
#, elixir-autogen, elixir-format
msgid "what should my notes be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:99
#, elixir-autogen, elixir-format
msgid "what should my pipelines be like?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:56
#, elixir-autogen, elixir-format
msgid "why split up into notes, contexts and pipelines?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:38
#, elixir-autogen, elixir-format
msgid "zettelkasten"
msgstr ""
#: lib/memex_web/views/layout_view.ex:10
#, elixir-autogen, elixir-format
msgid "memEx | %{title}"
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:9
#, elixir-autogen, elixir-format
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:113
#, elixir-autogen, elixir-format
msgid "how many people should i invite?"
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
#, 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 :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:116
#, elixir-autogen, elixir-format
msgid "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:28
#, elixir-autogen, elixir-format
msgid "language"
msgstr ""
#: lib/memex_web/components/core_components/user_card.html.heex:15
#, elixir-autogen, elixir-format
msgid "user confirmed on%{confirmed_datetime}"
msgstr ""
#: lib/memex_web/components/core_components/user_card.html.heex:26
#, elixir-autogen, elixir-format
msgid "user registered on%{registered_datetime}"
msgstr ""
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:36
#, elixir-autogen, elixir-format
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/core_components/invite_card.html.heex:12
#, elixir-autogen, elixir-format
msgid "uses left: %{uses_left_count}"
msgstr ""
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
#: lib/memex_web/live/home_live.html.heex:128
#, elixir-autogen, elixir-format
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:29
#, elixir-autogen, elixir-format
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format
msgid "admins"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:23
#, elixir-autogen, elixir-format
msgid "keep me logged in for 60 days"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:21
#, elixir-autogen, elixir-format
msgid "name"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:24
#: lib/memex_web/templates/user_session/new.html.heex:20
#, elixir-autogen, elixir-format
msgid "password"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:25
#, elixir-autogen, elixir-format
msgid "uses left"
msgstr ""

View File

@ -0,0 +1,93 @@
## "msgid"s in this file come from POT (.pot) files.
###
### Do not add, change, or remove "msgid"s manually here as
### they're tied to the ones in the corresponding POT file
### (with the same domain).
###
### Use "mix gettext.extract --merge" or "mix gettext.merge"
### to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex/accounts/email.ex:30
#, elixir-autogen, elixir-format
msgid "Confirm your Memex account"
msgstr ""
#: lib/memex_web/templates/email/confirm_email.html.heex:3
#: lib/memex_web/templates/email/confirm_email.txt.eex:2
#: lib/memex_web/templates/email/reset_password.html.heex:3
#: lib/memex_web/templates/email/reset_password.txt.eex:2
#: lib/memex_web/templates/email/update_email.html.heex:3
#: lib/memex_web/templates/email/update_email.txt.eex:2
#, elixir-autogen, elixir-format
msgid "Hi %{email},"
msgstr ""
#: lib/memex_web/templates/email/confirm_email.txt.eex:10
#, elixir-autogen, elixir-format
msgid "If you didn't create an account at %{url}, please ignore this."
msgstr ""
#: lib/memex_web/templates/email/reset_password.txt.eex:8
#: lib/memex_web/templates/email/update_email.txt.eex:8
#, elixir-autogen, elixir-format
msgid "If you didn't request this change from %{url}, please ignore this."
msgstr ""
#: lib/memex/accounts/email.ex:37
#, elixir-autogen, elixir-format
msgid "Reset your Memex password"
msgstr ""
#: lib/memex/accounts/email.ex:44
#, elixir-autogen, elixir-format
msgid "Update your Memex email"
msgstr ""
#: lib/memex_web/templates/email/update_email.html.heex:8
#: lib/memex_web/templates/email/update_email.txt.eex:4
#, elixir-autogen, elixir-format
msgid "You can change your email by visiting the URL below:"
msgstr ""
#: lib/memex_web/templates/email/confirm_email.html.heex:14
#: lib/memex_web/templates/email/confirm_email.txt.eex:6
#, elixir-autogen, elixir-format
msgid "You can confirm your account by visiting the URL below:"
msgstr ""
#: lib/memex_web/templates/email/reset_password.html.heex:8
#: lib/memex_web/templates/email/reset_password.txt.eex:4
#, elixir-autogen, elixir-format
msgid "You can reset your password by visiting the URL below:"
msgstr ""
#: lib/memex_web/templates/layout/email.html.heex:13
#, elixir-autogen, elixir-format
msgid "This email was sent from memEx"
msgstr ""
#: lib/memex_web/templates/layout/email.txt.eex:9
#, elixir-autogen, elixir-format
msgid "This email was sent from memEx at %{url}"
msgstr ""
#: lib/memex_web/templates/email/confirm_email.html.heex:22
#, elixir-autogen, elixir-format
msgid "If you didn't create an account at memEx, please ignore this."
msgstr ""
#: lib/memex_web/templates/email/reset_password.html.heex:16
#: lib/memex_web/templates/email/update_email.html.heex:16
#, elixir-autogen, elixir-format
msgid "If you didn't request this change from memEx, please ignore this."
msgstr ""
#: lib/memex_web/templates/email/confirm_email.html.heex:9
#: lib/memex_web/templates/email/confirm_email.txt.eex:4
#, elixir-autogen, elixir-format
msgid "Welcome to memEx"
msgstr ""

View File

@ -0,0 +1,145 @@
## "msgid"s in this file come from POT (.pot) files.
###
### Do not add, change, or remove "msgid"s manually here as
### they're tied to the ones in the corresponding POT file
### (with the same domain).
###
### Use "mix gettext.extract --merge" or "mix gettext.merge"
### to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex_web/templates/error/error.html.heex:8
#, elixir-autogen, elixir-format
msgid "Error"
msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:17
#, elixir-autogen, elixir-format
msgid "Invalid email or password"
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:63
#, elixir-autogen, elixir-format
msgid "Reset password link is invalid or it has expired."
msgstr ""
#: lib/memex_web/controllers/user_registration_controller.ex:22
#: lib/memex_web/controllers/user_registration_controller.ex:51
#, elixir-autogen, elixir-format
msgid "Sorry, public registration is disabled"
msgstr ""
#: lib/memex_web/controllers/user_registration_controller.ex:12
#: lib/memex_web/controllers/user_registration_controller.ex:41
#, elixir-autogen, elixir-format
msgid "Sorry, this invite was not found or expired"
msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:54
#, elixir-autogen, elixir-format
msgid "User confirmation link is invalid or it has expired."
msgstr ""
#: lib/memex_web/controllers/user_auth.ex:177
#, elixir-autogen, elixir-format
msgid "You are not authorized to view this page."
msgstr ""
#: lib/memex_web/controllers/user_auth.ex:39
#: lib/memex_web/controllers/user_auth.ex:161
#, elixir-autogen, elixir-format
msgid "You must confirm your account and log in to access this page."
msgstr ""
#: lib/memex/accounts/user.ex:144
#, elixir-autogen, elixir-format
msgid "did not change"
msgstr ""
#: lib/memex/accounts/user.ex:165
#, elixir-autogen, elixir-format
msgid "does not match password"
msgstr ""
#: lib/memex/accounts/user.ex:202
#, elixir-autogen, elixir-format
msgid "is not valid"
msgstr ""
#: lib/memex/accounts/user.ex:99
#, elixir-autogen, elixir-format
msgid "must have the @ sign and no spaces"
msgstr ""
#: lib/memex/contexts/context.ex:57
#: lib/memex/contexts/context.ex:70
#: lib/memex/notes/note.ex:56
#: lib/memex/notes/note.ex:69
#: lib/memex/pipelines/pipeline.ex:59
#: lib/memex/pipelines/pipeline.ex:72
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted"
msgstr ""
#: lib/memex_web/templates/error/error.html.heex:31
#, elixir-autogen, elixir-format
msgid "go back home"
msgstr ""
#: lib/memex_web/views/error_view.ex:10
#, elixir-autogen, elixir-format
msgid "internal server error"
msgstr ""
#: lib/memex_web/views/error_view.ex:8
#, elixir-autogen, elixir-format
msgid "not found"
msgstr ""
#: lib/memex_web/views/error_view.ex:9
#, elixir-autogen, elixir-format
msgid "unauthorized"
msgstr ""
#: lib/memex/contexts/context.ex:83
#: lib/memex/notes/note.ex:82
#: lib/memex/pipelines/pipeline.ex:85
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:13
#: lib/memex_web/templates/user_reset_password/edit.html.heex:13
#: lib/memex_web/templates/user_settings/edit.html.heex:64
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! please check the errors below."
msgstr ""
#: lib/memex_web/controllers/user_registration_controller.ex:70
#, elixir-autogen, elixir-format
msgid "sorry, this invite was not found or expired"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:18
#, elixir-autogen, elixir-format
msgid "you are not authorized to view this page"
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:84
#, elixir-autogen, elixir-format
msgid "email change link is invalid or it has expired."
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:99
#, elixir-autogen, elixir-format
msgid "unable to delete user"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:22
#: lib/memex_web/templates/user_settings/edit.html.heex:118
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! please check the errors below"
msgstr ""

View File

@ -0,0 +1,159 @@
## "msgid"s in this file come from POT (.pot) files.
###
### Do not add, change, or remove "msgid"s manually here as
### they're tied to the ones in the corresponding POT file
### (with the same domain).
###
### Use "mix gettext.extract --merge" or "mix gettext.merge"
### to merge POT files into PO files.
msgid ""
msgstr ""
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/memex_web/controllers/user_confirmation_controller.ex:38
#, elixir-autogen, elixir-format
msgid "%{email} confirmed successfully."
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:53
#, elixir-autogen, elixir-format
msgid "%{invite_name} deleted succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:114
#, elixir-autogen, elixir-format
msgid "%{invite_name} disabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:90
#, elixir-autogen, elixir-format
msgid "%{invite_name} enabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:68
#, elixir-autogen, elixir-format
msgid "%{invite_name} updated succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:137
#, elixir-autogen, elixir-format
msgid "%{user_email} deleted succesfully"
msgstr ""
#: lib/memex_web/controllers/user_confirmation_controller.ex:23
#, 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."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:24
#, elixir-autogen, elixir-format
msgid "If your email is in our system, you will receive instructions to reset your password shortly."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:46
#, elixir-autogen, elixir-format
msgid "Password reset successfully."
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:34
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:130
#, elixir-autogen, elixir-format
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:53
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete the invite for %{invite_name}?"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:149
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/core_components/topbar.html.heex:74
#, elixir-autogen, elixir-format
msgid "are you sure you want to log out?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:80
#, elixir-autogen, elixir-format
msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:46
#: lib/memex_web/live/context_live/show.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:117
#, elixir-autogen, elixir-format
msgid "are you sure?"
msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:23
#, elixir-autogen, elixir-format
msgid "logged out successfully."
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:65
#, elixir-autogen, elixir-format
msgid "language updated successfully."
msgstr ""
#: lib/memex_web/live/home_live.html.heex:90
#, elixir-autogen, elixir-format
msgid "register to setup memEx"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.ex:80
#, elixir-autogen, elixir-format
msgid "%{name} created successfully"
msgstr ""
#: lib/memex_web/live/invite_live/form_component.ex:62
#, elixir-autogen, elixir-format
msgid "%{name} updated successfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:126
#, elixir-autogen, elixir-format
msgid "copied to clipboard"
msgstr ""
#: lib/memex_web/controllers/user_registration_controller.ex:65
#, elixir-autogen, elixir-format
msgid "please check your email to verify your account"
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:29
#, elixir-autogen, elixir-format
msgid "a link to confirm your email change has been sent to the new address."
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:77
#, elixir-autogen, elixir-format
msgid "email changed successfully."
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:49
#, elixir-autogen, elixir-format
msgid "password updated successfully."
msgstr ""
#: lib/memex_web/controllers/user_settings_controller.ex:95
#, elixir-autogen, elixir-format
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:113
#: lib/memex_web/live/invite_live/index.html.heex:141
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete %{email}? this action is permanent!"
msgstr ""

View File

@ -20,12 +20,6 @@ msgstr ""
msgid "Invalid email or password"
msgstr ""
#: lib/memex_web/templates/user_reset_password/edit.html.heex:14
#: lib/memex_web/templates/user_settings/edit.html.heex:67
#, elixir-autogen, elixir-format
msgid "Oops, something went wrong! Please check the errors below."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:63
#, elixir-autogen, elixir-format
msgid "Reset password link is invalid or it has expired."
@ -79,50 +73,46 @@ msgstr ""
msgid "must have the @ sign and no spaces"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:23
#: lib/memex_web/templates/user_settings/edit.html.heex:123
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! Please check the errors below"
msgstr ""
#: lib/memex/contexts/context.ex:58
#: lib/memex/contexts/context.ex:71
#: lib/memex/notes/note.ex:57
#: lib/memex/notes/note.ex:70
#: lib/memex/pipelines/pipeline.ex:60
#: lib/memex/pipelines/pipeline.ex:73
#: lib/memex/contexts/context.ex:57
#: lib/memex/contexts/context.ex:70
#: lib/memex/notes/note.ex:56
#: lib/memex/notes/note.ex:69
#: lib/memex/pipelines/pipeline.ex:59
#: lib/memex/pipelines/pipeline.ex:72
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted"
msgstr ""
#: lib/memex_web/templates/error/error.html.heex:28
#: lib/memex_web/templates/error/error.html.heex:31
#, elixir-autogen, elixir-format
msgid "go back home"
msgstr ""
#: lib/memex_web/views/error_view.ex:11
#: lib/memex_web/views/error_view.ex:10
#, elixir-autogen, elixir-format
msgid "internal server error"
msgstr ""
#: lib/memex_web/views/error_view.ex:9
#: lib/memex_web/views/error_view.ex:8
#, elixir-autogen, elixir-format
msgid "not found"
msgstr ""
#: lib/memex_web/views/error_view.ex:10
#: lib/memex_web/views/error_view.ex:9
#, elixir-autogen, elixir-format
msgid "unauthorized"
msgstr ""
#: lib/memex/contexts/context.ex:84
#: lib/memex/notes/note.ex:83
#: lib/memex/pipelines/pipeline.ex:86
#: lib/memex/contexts/context.ex:83
#: lib/memex/notes/note.ex:82
#: lib/memex/pipelines/pipeline.ex:85
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:13
#: lib/memex_web/templates/user_reset_password/edit.html.heex:13
#: lib/memex_web/templates/user_settings/edit.html.heex:64
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! please check the errors below."
msgstr ""
@ -132,7 +122,7 @@ msgstr ""
msgid "sorry, this invite was not found or expired"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:19
#: lib/memex_web/live/invite_live/index.ex:18
#, elixir-autogen, elixir-format
msgid "you are not authorized to view this page"
msgstr ""
@ -146,3 +136,9 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "unable to delete user"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:22
#: lib/memex_web/templates/user_settings/edit.html.heex:118
#, elixir-autogen, elixir-format
msgid "oops, something went wrong! please check the errors below"
msgstr ""

View File

@ -15,27 +15,27 @@ msgstr ""
msgid "%{email} confirmed successfully."
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:54
#: lib/memex_web/live/invite_live/index.ex:53
#, elixir-autogen, elixir-format
msgid "%{invite_name} deleted succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:115
#: lib/memex_web/live/invite_live/index.ex:114
#, elixir-autogen, elixir-format
msgid "%{invite_name} disabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:91
#: lib/memex_web/live/invite_live/index.ex:90
#, elixir-autogen, elixir-format
msgid "%{invite_name} enabled succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:69
#: lib/memex_web/live/invite_live/index.ex:68
#, elixir-autogen, elixir-format
msgid "%{invite_name} updated succesfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:140
#: lib/memex_web/live/invite_live/index.ex:137
#, elixir-autogen, elixir-format
msgid "%{user_email} deleted succesfully"
msgstr ""
@ -55,49 +55,43 @@ msgstr ""
msgid "Password reset successfully."
msgstr ""
#: lib/memex_web/live/invite_live/form_component.html.heex:31
#: lib/memex_web/live/invite_live/form_component.html.heex:34
#, elixir-autogen, elixir-format
msgid "Saving..."
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:136
#: lib/memex_web/templates/user_settings/edit.html.heex:130
#, elixir-autogen, elixir-format
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:97
#: lib/memex_web/live/invite_live/index.html.heex:125
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete %{email}? This action is permanent!"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:47
#: lib/memex_web/live/invite_live/index.html.heex:53
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete the invite for %{invite_name}?"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:155
#: lib/memex_web/templates/user_settings/edit.html.heex:149
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/topbar.ex:90
#: lib/memex_web/components/core_components/topbar.html.heex:74
#, elixir-autogen, elixir-format
msgid "are you sure you want to log out?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:72
#: lib/memex_web/live/invite_live/index.html.heex:80
#, elixir-autogen, elixir-format
msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:45
#: lib/memex_web/live/context_live/index.html.heex:46
#: lib/memex_web/live/context_live/show.html.heex:38
#: lib/memex_web/live/note_live/index.html.heex:45
#: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/index.html.heex:45
#: lib/memex_web/live/pipeline_live/index.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:115
#: lib/memex_web/live/pipeline_live/show.html.heex:117
#, elixir-autogen, elixir-format
msgid "are you sure?"
msgstr ""
@ -112,7 +106,7 @@ msgstr ""
msgid "language updated successfully."
msgstr ""
#: lib/memex_web/live/home_live.html.heex:95
#: lib/memex_web/live/home_live.html.heex:90
#, elixir-autogen, elixir-format
msgid "register to setup memEx"
msgstr ""
@ -127,7 +121,7 @@ msgstr ""
msgid "%{name} updated successfully"
msgstr ""
#: lib/memex_web/live/invite_live/index.ex:128
#: lib/memex_web/live/invite_live/index.ex:126
#, elixir-autogen, elixir-format
msgid "copied to clipboard"
msgstr ""
@ -156,3 +150,9 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:113
#: lib/memex_web/live/invite_live/index.html.heex:141
#, elixir-autogen, elixir-format
msgid "are you sure you want to delete %{email}? this action is permanent!"
msgstr ""

View File

@ -53,7 +53,7 @@ defmodule Memex.InvitesTest do
test "get_use_count/2 returns the correct invite usage",
%{invite: %{token: token} = invite, current_user: current_user} do
assert 0 == Invites.get_use_count(invite, current_user)
assert Invites.get_use_count(invite, current_user) |> is_nil()
assert {:ok, _user} =
Accounts.register_user(
@ -72,6 +72,40 @@ defmodule Memex.InvitesTest do
assert 2 == Invites.get_use_count(invite, current_user)
end
test "get_use_counts/2 returns the correct invite usage",
%{invite: %{id: invite_id, token: token} = invite, current_user: current_user} do
{:ok, %{id: another_invite_id, token: another_token} = another_invite} =
Invites.create_invite(current_user, @valid_attrs)
assert [invite, another_invite] |> Invites.get_use_counts(current_user) == %{}
assert {:ok, _user} =
Accounts.register_user(
%{"email" => unique_user_email(), "password" => valid_user_password()},
token
)
assert {:ok, _user} =
Accounts.register_user(
%{"email" => unique_user_email(), "password" => valid_user_password()},
another_token
)
use_counts = [invite, another_invite] |> Invites.get_use_counts(current_user)
assert %{^invite_id => 1} = use_counts
assert %{^another_invite_id => 1} = use_counts
assert {:ok, _user} =
Accounts.register_user(
%{"email" => unique_user_email(), "password" => valid_user_password()},
token
)
use_counts = [invite, another_invite] |> Invites.get_use_counts(current_user)
assert %{^invite_id => 2} = use_counts
assert %{^another_invite_id => 1} = use_counts
end
test "use_invite/1 successfully uses an unlimited invite",
%{invite: %{token: token} = invite, current_user: current_user} do
{:ok, invite} = Invites.update_invite(invite, %{uses_left: nil}, current_user)

View File

@ -10,8 +10,6 @@ defmodule Memex.AccountsTest do
@moduletag :accounts_test
doctest Accounts, import: true
describe "get_user_by_email/1" do
test "does not return the user if the email does not exist" do
refute Accounts.get_user_by_email("unknown@example.com")
@ -514,7 +512,7 @@ defmodule Memex.AccountsTest do
test "deletes all tokens for the given user", %{user: user} do
_session_token = Accounts.generate_user_session_token(user)
{:ok, _} = Accounts.reset_user_password(user, %{"password" => "new valid password"})
{:ok, _user} = Accounts.reset_user_password(user, %{"password" => "new valid password"})
refute Repo.get_by(UserToken, user_id: user.id)
end
end

View File

@ -70,7 +70,7 @@ defmodule MemexWeb.ContextLiveTest do
test "updates context in listing", %{conn: conn, context: context} do
{:ok, index_live, _html} = live(conn, Routes.context_index_path(conn, :index))
assert index_live |> element("[data-qa=\"context-edit-#{context.id}\"]") |> render_click() =~
assert index_live |> element(~s/a[aria-label="edit #{context.slug}"]/) |> render_click() =~
"edit"
assert_patch(index_live, Routes.context_index_path(conn, :edit, context.slug))
@ -92,7 +92,7 @@ defmodule MemexWeb.ContextLiveTest do
test "deletes context in listing", %{conn: conn, context: context} do
{:ok, index_live, _html} = live(conn, Routes.context_index_path(conn, :index))
assert index_live |> element("[data-qa=\"delete-context-#{context.id}\"]") |> render_click()
assert index_live |> element(~s/a[aria-label="delete #{context.slug}"]/) |> render_click()
refute has_element?(index_live, "#context-#{context.id}")
end
end
@ -137,7 +137,7 @@ defmodule MemexWeb.ContextLiveTest do
{:ok, index_live, _html} =
show_live
|> element("[data-qa=\"delete-context-#{context.id}\"]")
|> element(~s/button[aria-label="delete #{context.slug}"]/)
|> render_click()
|> follow_redirect(conn, Routes.context_index_path(conn, :index))
@ -174,7 +174,7 @@ defmodule MemexWeb.ContextLiveTest do
assert html =~ "context"
assert html =~ Routes.note_show_path(Endpoint, :show, note_slug)
assert has_element?(show_live, "[data-qa=\"context-note-#{note_slug}\"]")
assert has_element?(show_live, "a", note_slug)
end
end
end

View File

@ -55,7 +55,9 @@ defmodule MemexWeb.InviteLiveTest do
test "updates invite in listing", %{conn: conn, invite: invite} do
{:ok, index_live, _html} = live(conn, Routes.invite_index_path(conn, :index))
assert index_live |> element("[data-qa=\"edit-#{invite.id}\"]") |> render_click() =~
assert index_live
|> element(~s/a[aria-label="edit invite for #{invite.name}"]/)
|> render_click() =~
gettext("edit invite")
assert_patch(index_live, Routes.invite_index_path(conn, :edit, invite))
@ -81,7 +83,10 @@ defmodule MemexWeb.InviteLiveTest do
test "deletes invite in listing", %{conn: conn, invite: invite} do
{:ok, index_live, _html} = live(conn, Routes.invite_index_path(conn, :index))
assert index_live |> element("[data-qa=\"delete-#{invite.id}\"]") |> render_click()
assert index_live
|> element(~s/a[aria-label="delete invite for #{invite.name}"]/)
|> render_click()
refute has_element?(index_live, "#invite-#{invite.id}")
end
end

View File

@ -75,7 +75,7 @@ defmodule MemexWeb.NoteLiveTest do
test "updates note in listing", %{conn: conn, note: note} do
{:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index))
assert index_live |> element("[data-qa=\"note-edit-#{note.id}\"]") |> render_click() =~
assert index_live |> element(~s/a[aria-label="edit #{note.slug}"]/) |> render_click() =~
"edit"
assert_patch(index_live, Routes.note_index_path(conn, :edit, note.slug))
@ -97,7 +97,7 @@ defmodule MemexWeb.NoteLiveTest do
test "deletes note in listing", %{conn: conn, note: note} do
{:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index))
assert index_live |> element("[data-qa=\"delete-note-#{note.id}\"]") |> render_click()
assert index_live |> element(~s/a[aria-label="delete #{note.slug}"]/) |> render_click()
refute has_element?(index_live, "#note-#{note.id}")
end
end
@ -138,7 +138,7 @@ defmodule MemexWeb.NoteLiveTest do
{:ok, index_live, _html} =
show_live
|> element("[data-qa=\"delete-note-#{note.id}\"]")
|> element(~s/button[aria-label="delete #{note.slug}"]/)
|> render_click()
|> follow_redirect(conn, Routes.note_index_path(conn, :index))
@ -177,7 +177,7 @@ defmodule MemexWeb.NoteLiveTest do
assert html =~ "context"
assert html =~ Routes.note_show_path(Endpoint, :show, note_slug)
assert has_element?(show_live, "[data-qa=\"note-link-#{note_slug}\"]")
assert has_element?(show_live, "a", note_slug)
end
end
end

View File

@ -81,7 +81,7 @@ defmodule MemexWeb.PipelineLiveTest do
test "updates pipeline in listing", %{conn: conn, pipeline: pipeline} do
{:ok, index_live, _html} = live(conn, Routes.pipeline_index_path(conn, :index))
assert index_live |> element("[data-qa=\"pipeline-edit-#{pipeline.id}\"]") |> render_click() =~
assert index_live |> element(~s/a[aria-label="edit #{pipeline.slug}"]/) |> render_click() =~
"edit"
assert_patch(index_live, Routes.pipeline_index_path(conn, :edit, pipeline.slug))
@ -104,7 +104,7 @@ defmodule MemexWeb.PipelineLiveTest do
{:ok, index_live, _html} = live(conn, Routes.pipeline_index_path(conn, :index))
assert index_live
|> element("[data-qa=\"delete-pipeline-#{pipeline.id}\"]")
|> element(~s/a[aria-label="delete #{pipeline.slug}"]/)
|> render_click()
refute has_element?(index_live, "#pipeline-#{pipeline.id}")
@ -151,7 +151,7 @@ defmodule MemexWeb.PipelineLiveTest do
{:ok, index_live, _html} =
show_live
|> element("[data-qa=\"delete-pipeline-#{pipeline.id}\"]")
|> element(~s/button[aria-label="delete #{pipeline.slug}"]/)
|> render_click()
|> follow_redirect(conn, Routes.pipeline_index_path(conn, :index))
@ -161,9 +161,7 @@ defmodule MemexWeb.PipelineLiveTest do
test "creates a step", %{conn: conn, pipeline: pipeline} do
{:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
show_live
|> element("[data-qa=\"add-step-#{pipeline.id}\"]")
|> render_click()
show_live |> element("a", "add step") |> render_click()
assert_patch(show_live, Routes.pipeline_show_path(conn, :add_step, pipeline.slug))
@ -199,7 +197,7 @@ defmodule MemexWeb.PipelineLiveTest do
{:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
show_live
|> element("[data-qa=\"edit-step-#{step.id}\"]")
|> element(~s/a[aria-label="edit #{step.title}"]/)
|> render_click()
assert_patch(show_live, Routes.pipeline_show_path(conn, :edit_step, pipeline.slug, step.id))
@ -223,7 +221,7 @@ defmodule MemexWeb.PipelineLiveTest do
html =
show_live
|> element("[data-qa=\"delete-step-#{step.id}\"]")
|> element(~s/button[aria-label="delete #{step.title}"]/)
|> render_click()
assert_patch(show_live, Routes.pipeline_show_path(conn, :show, pipeline.slug))
@ -250,25 +248,25 @@ defmodule MemexWeb.PipelineLiveTest do
html =
show_live
|> element("[data-qa=\"move-step-up-#{second_step.id}\"]")
|> element(~s/button[aria-label="move #{second_step.title} up"]/)
|> render_click()
assert html =~ "1. second step"
assert html =~ "2. first step"
assert html =~ "3. third step"
refute has_element?(show_live, "[data-qa=\"move-step-up-#{second_step.id}\"]")
refute has_element?(show_live, ~s/button[aria-label="move #{second_step.title} up"]/)
html =
show_live
|> element("[data-qa=\"move-step-down-#{first_step.id}\"]")
|> element(~s/button[aria-label="move #{first_step.title} down"]/)
|> render_click()
assert html =~ "1. second step"
assert html =~ "2. third step"
assert html =~ "3. first step"
refute has_element?(show_live, "[data-qa=\"move-step-down-#{first_step.id}\"]")
refute has_element?(show_live, ~s/button[aria-label="move #{first_step.title} down"]/)
end
end
end

View File

@ -22,13 +22,12 @@ defmodule MemexWeb.ConnCase do
using do
quote do
# Import conveniences for testing with connections
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
import Memex.Fixtures
import MemexWeb.ConnCase
# credo:disable-for-next-line Credo.Check.Consistency.MultiAliasImportRequireUse
import Phoenix.ConnTest
# Import conveniences for testing with connections
import Plug.Conn
import Phoenix.ConnTest
alias MemexWeb.Router.Helpers, as: Routes

View File

@ -2,6 +2,7 @@ defmodule Memex.Fixtures do
@moduledoc """
This module defines test helpers for creating entities
"""
alias Memex.{Accounts, Accounts.User, Email, Repo}
def unique_user_email, do: "user#{System.unique_integer()}@example.com"