16 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
74 changed files with 11291 additions and 5099 deletions

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) }
}

13982
assets/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
"license": "MIT",
"engines": {
"node": "v18.9.1",
"npm": "8.10.0"
"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,8 @@
# v0.1.10
- Improve accessibility
- Code quality improvements
- Fix dates displaying incorrectly
# v0.1.9
- Improve server log
- Style 大一點

View File

@ -389,6 +389,17 @@ 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

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

@ -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

@ -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())
@ -96,7 +95,7 @@ defmodule MemexWeb do
# 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,72 +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="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 != 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>
<%= 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

@ -1,131 +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
href={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
href={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,53 +0,0 @@
defmodule MemexWeb.Components.UserCard do
@moduledoc """
Display card for a user
"""
use MemexWeb, :component
alias Memex.Accounts.User
attr :user, User, required: true
slot(:inner_block, required: true)
def user_card(assigns) do
~H"""
<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 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

@ -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

@ -90,9 +90,9 @@
<%= dgettext("prompts", "register to setup memEx") %>
</.link>
<% else %>
<a :for={%{email: email} <- @admins} class="link" href={"mailto:#{email}"}>
<.link :for={%{email: email} <- @admins} class="link" href={"mailto:#{email}"}>
<%= email %>
</a>
</.link>
<% end %>
</p>
</li>
@ -100,9 +100,9 @@
<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>

View File

@ -4,7 +4,6 @@ defmodule MemexWeb.InviteLive.Index do
"""
use MemexWeb, :live_view
import MemexWeb.Components.{InviteCard, UserCard}
alias Memex.Accounts
alias Memex.Accounts.{Invite, Invites}
alias MemexWeb.HomeLive
@ -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

@ -14,13 +14,21 @@
<% end %>
<div class="flex flex-col justify-center items-stretch space-y-4">
<.invite_card :for={invite <- @invites} invite={invite} current_user={@current_user}>
<.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-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") %>
</button>
@ -29,7 +37,9 @@
<.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>
@ -44,21 +54,23 @@
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-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-secondary"
@ -71,7 +83,7 @@
}
>
<%= gettext("set unlimited") %>
</a>
</.link>
</.invite_card>
<.link

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
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>
"""
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

@ -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

@ -5,7 +5,8 @@
<.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"
>

View File

@ -5,7 +5,8 @@
<.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"
>

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,6 +1,5 @@
defmodule MemexWeb.LayoutView do
use MemexWeb, :view
import MemexWeb.Components.Topbar
alias MemexWeb.HomeLive
# Phoenix LiveDashboard is available only in development by default,

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
"""
@ -76,21 +21,4 @@ defmodule MemexWeb.ViewHelpers do
"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,7 +4,7 @@ defmodule Memex.MixProject do
def project do
[
app: :memex,
version: "0.1.9",
version: "0.1.10",
elixir: "1.14.1",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: Mix.compilers(),
@ -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

@ -11,7 +11,7 @@ msgid ""
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 ""
@ -45,18 +45,18 @@ msgstr ""
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:82
#: 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 ""
@ -66,13 +66,13 @@ msgstr ""
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 ""
@ -82,38 +82,38 @@ msgstr ""
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/topbar.ex:122
#: 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:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:31
#: 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: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:113
#: 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:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:28
#: 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"
@ -134,7 +134,7 @@ 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 ""
@ -146,7 +146,7 @@ msgstr ""
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 ""
@ -156,7 +156,75 @@ msgstr ""
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:25
#: 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

@ -11,7 +11,7 @@ msgstr ""
"Language: de\n"
#: 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 ""
@ -45,18 +45,18 @@ msgstr ""
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:82
#: 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 ""
@ -66,13 +66,13 @@ msgstr ""
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 ""
@ -82,38 +82,38 @@ msgstr ""
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/topbar.ex:122
#: 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:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:31
#: 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: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:113
#: 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:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:28
#: 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"
@ -134,7 +134,7 @@ 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 ""
@ -146,7 +146,7 @@ msgstr ""
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 ""
@ -156,7 +156,75 @@ msgstr ""
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:25
#: 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

@ -60,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
@ -84,7 +84,7 @@ msgstr ""
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
@ -99,25 +99,25 @@ msgstr ""
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_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:12
#: 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:34
#: 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:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
@ -143,7 +143,7 @@ msgstr ""
msgid "instance information"
msgstr ""
#: lib/memex_web/components/invite_card.ex:43
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
@ -153,8 +153,8 @@ msgstr ""
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"
@ -170,7 +170,7 @@ msgstr ""
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 ""
@ -186,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
@ -204,7 +204,7 @@ msgstr ""
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
@ -267,7 +267,7 @@ msgstr ""
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:73
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
@ -292,7 +292,7 @@ msgstr ""
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:118
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
@ -319,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 ""
@ -331,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 ""
@ -347,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 ""
@ -360,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 ""
@ -377,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 ""
@ -396,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 ""
@ -419,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 ""
@ -444,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 ""
@ -454,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 ""
@ -569,7 +569,7 @@ msgstr ""
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 ""
@ -604,17 +604,17 @@ msgstr ""
msgid "language"
msgstr ""
#: lib/memex_web/components/user_card.ex:28
#: 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:39
#: 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:38
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
@ -624,12 +624,12 @@ msgstr ""
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/invite_card.ex:33
#: 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:53
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
@ -639,7 +639,7 @@ msgstr ""
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:12
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format, fuzzy
msgid "Email"
msgstr ""
@ -649,7 +649,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:90
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format, fuzzy
msgid "admins"
msgstr ""

View File

@ -73,39 +73,39 @@ msgstr ""
msgid "must have the @ sign and no spaces"
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 ""
@ -122,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 ""

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 ""
@ -65,7 +65,7 @@ msgstr ""
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:43
#: 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 ""
@ -75,23 +75,23 @@ msgstr ""
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/topbar.ex:89
#: 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:68
#: 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 ""
@ -121,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 ""
@ -151,8 +151,8 @@ msgstr ""
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:101
#: lib/memex_web/live/invite_live/index.html.heex:129
#: 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

@ -58,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
@ -82,7 +82,7 @@ msgstr ""
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
@ -97,25 +97,25 @@ msgstr ""
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_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:12
#: 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:34
#: 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:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
@ -141,7 +141,7 @@ msgstr ""
msgid "instance information"
msgstr ""
#: lib/memex_web/components/invite_card.ex:43
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
@ -151,8 +151,8 @@ msgstr ""
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"
@ -168,7 +168,7 @@ msgstr ""
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 ""
@ -184,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
@ -202,7 +202,7 @@ msgstr ""
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
@ -265,7 +265,7 @@ msgstr ""
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:73
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
@ -290,7 +290,7 @@ msgstr ""
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:118
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
@ -317,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 ""
@ -329,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 ""
@ -345,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 ""
@ -358,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 ""
@ -375,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 ""
@ -394,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 ""
@ -417,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 ""
@ -442,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 ""
@ -452,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 ""
@ -567,7 +567,7 @@ msgstr ""
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 ""
@ -602,17 +602,17 @@ msgstr ""
msgid "language"
msgstr ""
#: lib/memex_web/components/user_card.ex:28
#: 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:39
#: 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:38
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
@ -622,12 +622,12 @@ msgstr ""
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/invite_card.ex:33
#: 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:53
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
@ -637,7 +637,7 @@ msgstr ""
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:12
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
@ -647,7 +647,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:90
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format
msgid "admins"
msgstr ""

View File

@ -12,7 +12,7 @@ msgstr ""
"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:15
#: lib/memex_web/templates/user_confirmation/new.html.heex:16
#, elixir-autogen, elixir-format
msgid "Resend confirmation instructions"
msgstr ""
@ -46,18 +46,18 @@ msgstr ""
msgid "change password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:82
#: 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 ""
@ -67,13 +67,13 @@ msgstr ""
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 ""
@ -83,38 +83,38 @@ msgstr ""
msgid "invite someone new!"
msgstr ""
#: lib/memex_web/components/topbar.ex:122
#: 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:45
#: lib/memex_web/templates/user_reset_password/new.html.heex:31
#: 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: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:113
#: 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:42
#: lib/memex_web/templates/user_reset_password/new.html.heex:28
#: 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"
@ -135,7 +135,7 @@ 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 ""
@ -147,7 +147,7 @@ msgstr ""
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 ""
@ -157,7 +157,75 @@ msgstr ""
msgid "export data as json"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:25
#: 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

@ -59,7 +59,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
@ -83,7 +83,7 @@ msgstr ""
msgid "current password"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "disable"
msgstr ""
@ -98,25 +98,25 @@ msgstr ""
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_registration/new.html.heex:20
#: lib/memex_web/templates/user_reset_password/new.html.heex:12
#: 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:34
#: 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:58
#: lib/memex_web/live/invite_live/index.html.heex:70
#, elixir-autogen, elixir-format
msgid "enable"
msgstr ""
@ -142,7 +142,7 @@ msgstr ""
msgid "instance information"
msgstr ""
#: lib/memex_web/components/invite_card.ex:43
#: lib/memex_web/components/core_components/invite_card.html.heex:22
#, elixir-autogen, elixir-format
msgid "invite disabled"
msgstr ""
@ -152,8 +152,8 @@ msgstr ""
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"
@ -169,7 +169,7 @@ msgstr ""
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 ""
@ -185,12 +185,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
@ -203,7 +203,7 @@ msgstr ""
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
@ -266,7 +266,7 @@ msgstr ""
msgid "select privacy"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:73
#: lib/memex_web/live/invite_live/index.html.heex:85
#, elixir-autogen, elixir-format
msgid "set unlimited"
msgstr ""
@ -291,7 +291,7 @@ msgstr ""
msgid "tags"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:118
#: lib/memex_web/live/invite_live/index.html.heex:130
#, elixir-autogen, elixir-format
msgid "users"
msgstr ""
@ -318,9 +318,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 ""
@ -330,7 +330,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 ""
@ -346,7 +346,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 ""
@ -359,11 +359,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 ""
@ -376,11 +376,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 ""
@ -395,9 +395,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 ""
@ -418,12 +418,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 ""
@ -443,7 +443,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 ""
@ -453,7 +453,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 ""
@ -568,7 +568,7 @@ msgstr ""
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 ""
@ -603,17 +603,17 @@ msgstr ""
msgid "language"
msgstr ""
#: lib/memex_web/components/user_card.ex:28
#: 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:39
#: 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:38
#: lib/memex_web/components/core_components/invite_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "uses left: unlimited"
msgstr ""
@ -623,12 +623,12 @@ msgstr ""
msgid "read more on how to use memEx"
msgstr ""
#: lib/memex_web/components/invite_card.ex:33
#: 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:53
#: lib/memex_web/components/core_components/invite_card.html.heex:32
#, elixir-autogen, elixir-format
msgid "uses: %{uses_count}"
msgstr ""
@ -638,7 +638,7 @@ msgstr ""
msgid "get involved"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:12
#: lib/memex_web/templates/user_confirmation/new.html.heex:13
#, elixir-autogen, elixir-format
msgid "Email"
msgstr ""
@ -648,7 +648,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:90
#: lib/memex_web/live/invite_live/index.html.heex:102
#, elixir-autogen, elixir-format
msgid "admins"
msgstr ""

View File

@ -74,39 +74,39 @@ msgstr ""
msgid "must have the @ sign and no spaces"
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 ""
@ -123,7 +123,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 ""

View File

@ -16,27 +16,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 ""
@ -66,7 +66,7 @@ msgstr ""
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:43
#: 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 ""
@ -76,23 +76,23 @@ msgstr ""
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/topbar.ex:89
#: 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:68
#: 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 ""
@ -122,7 +122,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 ""
@ -152,8 +152,8 @@ msgstr ""
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:101
#: lib/memex_web/live/invite_live/index.html.heex:129
#: 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

@ -73,39 +73,39 @@ msgstr ""
msgid "must have the @ sign and no spaces"
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 ""
@ -122,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 ""

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 ""
@ -65,7 +65,7 @@ msgstr ""
msgid "are you sure you want to change your language?"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:43
#: 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 ""
@ -75,23 +75,23 @@ msgstr ""
msgid "are you sure you want to delete your account?"
msgstr ""
#: lib/memex_web/components/topbar.ex:89
#: 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:68
#: 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 ""
@ -121,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 ""
@ -151,8 +151,8 @@ msgstr ""
msgid "your account has been deleted"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:101
#: lib/memex_web/live/invite_live/index.html.heex:129
#: 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

@ -1,176 +0,0 @@
defmodule Memex.InvitesTest do
@moduledoc """
This module tests the Memex.Accounts.Invites context
"""
use Memex.DataCase
alias Ecto.Changeset
alias Memex.Accounts
alias Memex.Accounts.{Invite, Invites}
@moduletag :invites_test
@valid_attrs %{
"name" => "some name"
}
@invalid_attrs %{
"name" => nil,
"token" => nil
}
describe "invites" do
setup do
current_user = admin_fixture()
{:ok, invite} = Invites.create_invite(current_user, @valid_attrs)
[invite: invite, current_user: current_user]
end
test "list_invites/0 returns all invites", %{invite: invite, current_user: current_user} do
assert Invites.list_invites(current_user) == [invite]
end
test "get_invite!/1 returns the invite with given id",
%{invite: invite, current_user: current_user} do
assert Invites.get_invite!(invite.id, current_user) == invite
end
test "valid_invite_token? returns for valid and invalid invite tokens",
%{invite: %{token: token}} do
refute Invites.valid_invite_token?(nil)
refute Invites.valid_invite_token?("")
assert Invites.valid_invite_token?(token)
end
test "valid_invite_token? does not return true for a disabled invite by token",
%{invite: %{token: token} = invite, current_user: current_user} do
assert Invites.valid_invite_token?(token)
{:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
{:ok, _invite} = Invites.use_invite(token)
refute Invites.valid_invite_token?(token)
end
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 {:ok, _user} =
Accounts.register_user(
%{"email" => unique_user_email(), "password" => valid_user_password()},
token
)
assert 1 == Invites.get_use_count(invite, current_user)
assert {:ok, _user} =
Accounts.register_user(
%{"email" => unique_user_email(), "password" => valid_user_password()},
token
)
assert 2 == Invites.get_use_count(invite, current_user)
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)
assert {:ok, ^invite} = Invites.use_invite(token)
assert {:ok, ^invite} = Invites.use_invite(token)
assert {:ok, ^invite} = Invites.use_invite(token)
end
test "use_invite/1 successfully decrements an invite",
%{invite: %{token: token} = invite, current_user: current_user} do
{:ok, _invite} = Invites.update_invite(invite, %{uses_left: 10}, current_user)
assert {:ok, %{uses_left: 9}} = Invites.use_invite(token)
assert {:ok, %{uses_left: 8}} = Invites.use_invite(token)
assert {:ok, %{uses_left: 7}} = Invites.use_invite(token)
end
test "use_invite/1 successfully disactivates an invite",
%{invite: %{token: token} = invite, current_user: current_user} do
{:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
assert {:ok, %{uses_left: 0, disabled_at: disabled_at}} = Invites.use_invite(token)
assert not is_nil(disabled_at)
end
test "use_invite/1 does not work on disactivated invite",
%{invite: %{token: token} = invite, current_user: current_user} do
{:ok, _invite} = Invites.update_invite(invite, %{uses_left: 1}, current_user)
{:ok, _invite} = Invites.use_invite(token)
assert {:error, :invalid_token} = Invites.use_invite(token)
end
test "create_invite/1 with valid data creates an unlimited invite",
%{current_user: current_user} do
assert {:ok, %Invite{} = invite} =
Invites.create_invite(current_user, %{
"name" => "some name"
})
assert invite.name == "some name"
end
test "create_invite/1 with valid data creates a limited invite",
%{current_user: current_user} do
assert {:ok, %Invite{} = invite} =
Invites.create_invite(current_user, %{
"name" => "some name",
"uses_left" => 10
})
assert invite.name == "some name"
assert invite.uses_left == 10
end
test "create_invite/1 with invalid data returns error changeset",
%{current_user: current_user} do
assert {:error, %Changeset{}} = Invites.create_invite(current_user, @invalid_attrs)
end
test "update_invite/2 can set an invite to be limited",
%{invite: invite, current_user: current_user} do
assert {:ok, %Invite{} = new_invite} =
Invites.update_invite(
invite,
%{"name" => "some updated name", "uses_left" => 5},
current_user
)
assert new_invite.name == "some updated name"
assert new_invite.uses_left == 5
end
test "update_invite/2 can set an invite to be unlimited",
%{invite: invite, current_user: current_user} do
{:ok, invite} = Invites.update_invite(invite, %{"uses_left" => 5}, current_user)
assert {:ok, %Invite{} = new_invite} =
Invites.update_invite(
invite,
%{"name" => "some updated name", "uses_left" => nil},
current_user
)
assert new_invite.name == "some updated name"
assert new_invite.uses_left |> is_nil()
end
test "update_invite/2 with invalid data returns error changeset",
%{invite: invite, current_user: current_user} do
assert {:error, %Changeset{}} = Invites.update_invite(invite, @invalid_attrs, current_user)
assert invite == Invites.get_invite!(invite.id, current_user)
end
test "delete_invite/1 deletes the invite", %{invite: invite, current_user: current_user} do
assert {:ok, %Invite{}} = Invites.delete_invite(invite, current_user)
assert_raise Ecto.NoResultsError, fn -> Invites.get_invite!(invite.id, current_user) end
end
test "delete_invite!/1 deletes the invite", %{invite: invite, current_user: current_user} do
assert %Invite{} = Invites.delete_invite!(invite, current_user)
assert_raise Ecto.NoResultsError, fn -> Invites.get_invite!(invite.id, current_user) end
end
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