13 Commits

Author SHA1 Message Date
7813738f91 add json data export
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-20 19:15:08 -05:00
c1337ebc10 fix formatting in note/context/step contents 2022-12-20 18:36:56 -05:00
59283a0217 fix overflow on note/contexts/step contents
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-19 23:16:12 -05:00
634891ee73 Added translation using Weblate (German)
Some checks are pending
continuous-integration/drone/push Build is running
2022-12-20 03:35:57 +00:00
571f6fffdb improve tagging logic
Some checks are pending
continuous-integration/drone/push Build is running
2022-12-19 22:34:00 -05:00
926805ba9b fix user invite page 2022-12-19 21:14:14 -05:00
220122dec6 add newlines to content components 2022-12-19 21:09:57 -05:00
de399b4819 fix broken docker-compose 2022-12-19 21:09:50 -05:00
c3ceb877b2 search tags when on click
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-15 22:52:42 -05:00
0b4449c8a8 backlink to other notes in notes 2022-12-15 22:45:48 -05:00
6452f64fec check for slug uniqueness before submitting
All checks were successful
continuous-integration/drone/push Build is passing
2022-11-28 00:20:57 -05:00
c0afc96b8d add to faq 2022-11-28 00:14:16 -05:00
2cfecc54a0 fix more typos 2022-11-27 22:55:23 -05:00
53 changed files with 795 additions and 312 deletions

View File

@ -1,3 +1,25 @@
# v0.1.6
- fix formatting in note/context/step contents
- add json export for data
# v0.1.5
- fix overflow on note/contexts/step contents
# v0.1.4
- fix docker-compose
- fix newlines in note/context/step contents
- fix user invite page
- improve tagging logic
# v0.1.3
- backlink to other notes in notes
- search tags on click
# v0.1.2
- fix more typos
- add to faq
- check for slug uniqueness before submitting
# v0.1.1 # v0.1.1
- improve search a whole lot - improve search a whole lot
- improve table information for notes and contexts - improve table information for notes and contexts

10
de.tbx Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!DOCTYPE martif PUBLIC "ISO 12200:1999A//DTD MARTIF core (DXFcdV04)//EN" "TBXcdv04.dtd">
<martif type="TBX">
<martifHeader>
<fileDesc>
<sourceDesc><p>Translate Toolkit</p></sourceDesc>
</fileDesc>
</martifHeader>
<text><body></body></text>
</martif>

View File

@ -2,8 +2,7 @@ version: '3'
services: services:
memex: memex:
build: image: shibaobun/memex
context: .
container_name: memex container_name: memex
restart: always restart: always
environment: environment:

View File

@ -9,6 +9,16 @@ defmodule Memex.Accounts.User do
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.Invites.Invite alias Memex.Invites.Invite
@derive {Jason.Encoder,
only: [
:id,
:email,
:confirmed_at,
:role,
:locale,
:inserted_at,
:updated_at
]}
@derive {Inspect, except: [:password]} @derive {Inspect, except: [:password]}
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id

View File

@ -4,7 +4,6 @@ defmodule Memex.Contexts do
""" """
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Ecto.Changeset
alias Memex.{Accounts.User, Contexts.Context, Repo} alias Memex.{Accounts.User, Contexts.Context, Repo}
@doc """ @doc """
@ -229,18 +228,4 @@ defmodule Memex.Contexts do
def change_context(%Context{} = context, attrs \\ %{}, user) do def change_context(%Context{} = context, attrs \\ %{}, user) do
context |> Context.update_changeset(attrs, user) context |> Context.update_changeset(attrs, user)
end end
@doc """
Gets a canonical string representation of the `:tags` field for a Note
"""
@spec get_tags_string(Context.t() | Context.changeset() | [String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
def get_tags_string(%Context{tags: tags}), do: tags |> get_tags_string()
def get_tags_string(%Changeset{} = changeset) do
changeset
|> Changeset.get_field(:tags)
|> get_tags_string()
end
end end

View File

@ -7,8 +7,17 @@ defmodule Memex.Contexts.Context do
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.Accounts.User alias Memex.{Accounts.User, Repo}
@derive {Jason.Encoder,
only: [
:slug,
:content,
:tags,
:visibility,
:inserted_at,
:updated_at
]}
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id
schema "contexts" do schema "contexts" do
@ -27,7 +36,7 @@ defmodule Memex.Contexts.Context do
slug: slug(), slug: slug(),
content: String.t(), content: String.t(),
tags: [String.t()] | nil, tags: [String.t()] | nil,
tags_string: String.t(), tags_string: String.t() | nil,
visibility: :public | :private | :unlisted, visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(), user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(), user_id: User.id(),
@ -49,6 +58,8 @@ defmodule Memex.Contexts.Context do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :user_id, :visibility]) |> validate_required([:slug, :content, :user_id, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset() @spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
@ -60,18 +71,42 @@ defmodule Memex.Contexts.Context do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :visibility]) |> validate_required([:slug, :content, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
defp cast_tags_string(changeset, %{"tags_string" => tags_string}) defp cast_tags_string(changeset, attrs) do
when tags_string |> is_binary() do changeset
tags = |> put_change(:tags_string, changeset |> get_field(:tags) |> get_tags_string())
|> cast(attrs, [:tags_string])
|> validate_format(:tags_string, ~r/^[\p{L}\p{N}\-\,]+$/,
message:
dgettext(
"errors",
"invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
)
)
|> cast_tags()
end
defp cast_tags(%{valid?: false} = changeset), do: changeset
defp cast_tags(%{valid?: true} = changeset) do
tags = changeset |> get_field(:tags_string) |> process_tags()
changeset |> put_change(:tags, tags)
end
defp process_tags(tags_string) when tags_string |> is_binary() do
tags_string tags_string
|> String.split(",", trim: true) |> String.split(",", trim: true)
|> Enum.map(fn str -> str |> String.trim() end) |> Enum.map(fn str -> str |> String.trim() end)
|> Enum.reject(fn str -> str |> is_nil() end)
|> Enum.sort() |> Enum.sort()
changeset |> change(tags: tags)
end end
defp cast_tags_string(changeset, _attrs), do: changeset defp process_tags(_other_tags_string), do: []
@spec get_tags_string([String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
end end

View File

@ -4,7 +4,6 @@ defmodule Memex.Notes do
""" """
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Ecto.Changeset
alias Memex.{Accounts.User, Notes.Note, Repo} alias Memex.{Accounts.User, Notes.Note, Repo}
@doc """ @doc """
@ -229,18 +228,4 @@ defmodule Memex.Notes do
def change_note(%Note{} = note, attrs \\ %{}, user) do def change_note(%Note{} = note, attrs \\ %{}, user) do
note |> Note.update_changeset(attrs, user) note |> Note.update_changeset(attrs, user)
end end
@doc """
Gets a canonical string representation of the `:tags` field for a Note
"""
@spec get_tags_string(Note.t() | Note.changeset() | [String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
def get_tags_string(%Note{tags: tags}), do: tags |> get_tags_string()
def get_tags_string(%Changeset{} = changeset) do
changeset
|> Changeset.get_field(:tags)
|> get_tags_string()
end
end end

View File

@ -6,8 +6,17 @@ defmodule Memex.Notes.Note do
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.Accounts.User alias Memex.{Accounts.User, Repo}
@derive {Jason.Encoder,
only: [
:slug,
:content,
:tags,
:visibility,
:inserted_at,
:updated_at
]}
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id
schema "notes" do schema "notes" do
@ -26,7 +35,7 @@ defmodule Memex.Notes.Note do
slug: slug(), slug: slug(),
content: String.t(), content: String.t(),
tags: [String.t()] | nil, tags: [String.t()] | nil,
tags_string: String.t(), tags_string: String.t() | nil,
visibility: :public | :private | :unlisted, visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(), user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(), user_id: User.id(),
@ -48,6 +57,8 @@ defmodule Memex.Notes.Note do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :user_id, :visibility]) |> validate_required([:slug, :content, :user_id, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset() @spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
@ -59,18 +70,42 @@ defmodule Memex.Notes.Note do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :content, :visibility]) |> validate_required([:slug, :content, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
defp cast_tags_string(changeset, %{"tags_string" => tags_string}) defp cast_tags_string(changeset, attrs) do
when tags_string |> is_binary() do changeset
tags = |> put_change(:tags_string, changeset |> get_field(:tags) |> get_tags_string())
|> cast(attrs, [:tags_string])
|> validate_format(:tags_string, ~r/^[\p{L}\p{N}\-\,]+$/,
message:
dgettext(
"errors",
"invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
)
)
|> cast_tags()
end
defp cast_tags(%{valid?: false} = changeset), do: changeset
defp cast_tags(%{valid?: true} = changeset) do
tags = changeset |> get_field(:tags_string) |> process_tags()
changeset |> put_change(:tags, tags)
end
defp process_tags(tags_string) when tags_string |> is_binary() do
tags_string tags_string
|> String.split(",", trim: true) |> String.split(",", trim: true)
|> Enum.map(fn str -> str |> String.trim() end) |> Enum.map(fn str -> str |> String.trim() end)
|> Enum.reject(fn str -> str |> is_nil() end)
|> Enum.sort() |> Enum.sort()
changeset |> change(tags: tags)
end end
defp cast_tags_string(changeset, _attrs), do: changeset defp process_tags(_other_tags_string), do: []
@spec get_tags_string([String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
end end

View File

@ -4,7 +4,6 @@ defmodule Memex.Pipelines do
""" """
import Ecto.Query, warn: false import Ecto.Query, warn: false
alias Ecto.Changeset
alias Memex.{Accounts.User, Pipelines.Pipeline, Repo} alias Memex.{Accounts.User, Pipelines.Pipeline, Repo}
@doc """ @doc """
@ -231,18 +230,4 @@ defmodule Memex.Pipelines do
def change_pipeline(%Pipeline{} = pipeline, attrs \\ %{}, user) do def change_pipeline(%Pipeline{} = pipeline, attrs \\ %{}, user) do
pipeline |> Pipeline.update_changeset(attrs, user) pipeline |> Pipeline.update_changeset(attrs, user)
end end
@doc """
Gets a canonical string representation of the `:tags` field for a Pipeline
"""
@spec get_tags_string(Pipeline.t() | Pipeline.changeset() | [String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
def get_tags_string(%Pipeline{tags: tags}), do: tags |> get_tags_string()
def get_tags_string(%Changeset{} = changeset) do
changeset
|> Changeset.get_field(:tags)
|> get_tags_string()
end
end end

View File

@ -6,8 +6,18 @@ defmodule Memex.Pipelines.Pipeline do
import Ecto.Changeset import Ecto.Changeset
import MemexWeb.Gettext import MemexWeb.Gettext
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Pipelines.Steps.Step} alias Memex.{Accounts.User, Pipelines.Steps.Step, Repo}
@derive {Jason.Encoder,
only: [
:slug,
:description,
:tags,
:visibility,
:inserted_at,
:steps,
:updated_at
]}
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id
schema "pipelines" do schema "pipelines" do
@ -28,7 +38,7 @@ defmodule Memex.Pipelines.Pipeline do
slug: slug(), slug: slug(),
description: String.t(), description: String.t(),
tags: [String.t()] | nil, tags: [String.t()] | nil,
tags_string: String.t(), tags_string: String.t() | nil,
visibility: :public | :private | :unlisted, visibility: :public | :private | :unlisted,
user: User.t() | Ecto.Association.NotLoaded.t(), user: User.t() | Ecto.Association.NotLoaded.t(),
user_id: User.id(), user_id: User.id(),
@ -50,6 +60,8 @@ defmodule Memex.Pipelines.Pipeline do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :user_id, :visibility]) |> validate_required([:slug, :user_id, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
@spec update_changeset(t(), attrs :: map(), User.t()) :: changeset() @spec update_changeset(t(), attrs :: map(), User.t()) :: changeset()
@ -61,18 +73,42 @@ defmodule Memex.Pipelines.Pipeline do
message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted") message: dgettext("errors", "invalid format: only numbers, letters and hyphen are accepted")
) )
|> validate_required([:slug, :visibility]) |> validate_required([:slug, :visibility])
|> unique_constraint(:slug)
|> unsafe_validate_unique(:slug, Repo)
end end
defp cast_tags_string(changeset, %{"tags_string" => tags_string}) defp cast_tags_string(changeset, attrs) do
when tags_string |> is_binary() do changeset
tags = |> put_change(:tags_string, changeset |> get_field(:tags) |> get_tags_string())
|> cast(attrs, [:tags_string])
|> validate_format(:tags_string, ~r/^[\p{L}\p{N}\-\,]+$/,
message:
dgettext(
"errors",
"invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
)
)
|> cast_tags()
end
defp cast_tags(%{valid?: false} = changeset), do: changeset
defp cast_tags(%{valid?: true} = changeset) do
tags = changeset |> get_field(:tags_string) |> process_tags()
changeset |> put_change(:tags, tags)
end
defp process_tags(tags_string) when tags_string |> is_binary() do
tags_string tags_string
|> String.split(",", trim: true) |> String.split(",", trim: true)
|> Enum.map(fn str -> str |> String.trim() end) |> Enum.map(fn str -> str |> String.trim() end)
|> Enum.reject(fn str -> str |> is_nil() end)
|> Enum.sort() |> Enum.sort()
changeset |> change(tags: tags)
end end
defp cast_tags_string(changeset, _attrs), do: changeset defp process_tags(_other_tags_string), do: []
@spec get_tags_string([String.t()] | nil) :: String.t()
def get_tags_string(nil), do: ""
def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",")
end end

View File

@ -7,6 +7,14 @@ defmodule Memex.Pipelines.Steps.Step do
alias Ecto.{Changeset, UUID} alias Ecto.{Changeset, UUID}
alias Memex.{Accounts.User, Pipelines.Pipeline} alias Memex.{Accounts.User, Pipelines.Pipeline}
@derive {Jason.Encoder,
only: [
:title,
:content,
:position,
:inserted_at,
:updated_at
]}
@primary_key {:id, :binary_id, autogenerate: true} @primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id @foreign_key_type :binary_id
schema "steps" do schema "steps" do

View File

@ -12,7 +12,7 @@ defmodule MemexWeb.Components.ContextContent do
~H""" ~H"""
<div <div
id={"show-context-content-#{@context.id}"} id={"show-context-content-#{@context.id}"}
class="input input-primary h-128 min-h-128 inline-block" class="input input-primary h-128 min-h-128 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto"
phx-hook="MaintainAttrs" phx-hook="MaintainAttrs"
phx-update="ignore" phx-update="ignore"
readonly readonly

View File

@ -105,7 +105,17 @@ defmodule MemexWeb.Components.ContextsTableComponent do
end end
defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do
tags |> Enum.join(", ") assigns = %{tags: tags}
~H"""
<div class="flex flex-wrap justify-center space-x-1">
<%= for tag <- @tags do %>
<.link patch={Routes.context_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
"""
end end
defp get_value_for_key(:actions, context, %{actions: actions}) do defp get_value_for_key(:actions, context, %{actions: actions}) do

View File

@ -0,0 +1,44 @@
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

@ -105,7 +105,17 @@ defmodule MemexWeb.Components.NotesTableComponent do
end end
defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do
tags |> Enum.join(", ") assigns = %{tags: tags}
~H"""
<div class="flex flex-wrap justify-center space-x-1">
<%= for tag <- @tags do %>
<.link patch={Routes.note_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
"""
end end
defp get_value_for_key(:actions, note, %{actions: actions}) do defp get_value_for_key(:actions, note, %{actions: actions}) do

View File

@ -118,7 +118,17 @@ defmodule MemexWeb.Components.PipelinesTableComponent do
end end
defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do defp get_value_for_key(:tags, %{tags: tags}, _additional_data) do
tags |> Enum.join(", ") assigns = %{tags: tags}
~H"""
<div class="flex flex-wrap justify-center space-x-1">
<%= for tag <- @tags do %>
<.link patch={Routes.pipeline_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
"""
end end
defp get_value_for_key(:actions, pipeline, %{actions: actions}) do defp get_value_for_key(:actions, pipeline, %{actions: actions}) do

View File

@ -12,7 +12,7 @@ defmodule MemexWeb.Components.StepContent do
~H""" ~H"""
<div <div
id={"show-step-content-#{@step.id}"} id={"show-step-content-#{@step.id}"}
class="input input-primary h-32 min-h-32 inline-block" class="input input-primary h-32 min-h-32 inline-block whitespace-pre-wrap overflow-x-hidden overflow-y-auto"
phx-hook="MaintainAttrs" phx-hook="MaintainAttrs"
phx-update="ignore" phx-update="ignore"
readonly readonly

View File

@ -22,15 +22,15 @@ defmodule MemexWeb.Components.UserCard do
<%= if @user.confirmed_at |> is_nil() do %> <%= if @user.confirmed_at |> is_nil() do %>
<%= gettext("email unconfirmed") %> <%= gettext("email unconfirmed") %>
<% else %> <% else %>
<%= gettext( <p>
"user was confirmed at %{relative_datetime}", <%= gettext("user confirmed on") %>
relative_datetime: @user.confirmed_at |> display_datetime() <%= @user.confirmed_at |> display_datetime() %>
) %> </p>
<% end %> <% end %>
</p> </p>
<p> <p>
<%= gettext("User registered on") %> <%= gettext("user registered on") %>
<%= @user.inserted_at |> display_datetime() %> <%= @user.inserted_at |> display_datetime() %>
</p> </p>
</h3> </h3>

View File

@ -0,0 +1,17 @@
defmodule MemexWeb.ExportController do
use MemexWeb, :controller
alias Memex.{Contexts, Notes, Pipelines, Pipelines.Steps}
def export(%{assigns: %{current_user: current_user}} = conn, %{"mode" => "json"}) do
pipelines =
Pipelines.list_pipelines(current_user)
|> Enum.map(fn pipeline -> Steps.preload_steps(pipeline, current_user) end)
json(conn, %{
user: current_user,
notes: Notes.list_notes(current_user),
contexts: Contexts.list_contexts(current_user),
pipelines: pipelines
})
end
end

View File

@ -6,7 +6,7 @@ defmodule MemexWeb.UserResetPasswordController do
plug :get_user_by_reset_password_token when action in [:edit, :update] plug :get_user_by_reset_password_token when action in [:edit, :update]
def new(conn, _params) do def new(conn, _params) do
render(conn, "new.html", page_title: gettext("Forgot your password?")) render(conn, "new.html", page_title: gettext("forgot your password?"))
end end
def create(conn, %{"user" => %{"email" => email}}) do def create(conn, %{"user" => %{"email" => email}}) do

View File

@ -20,7 +20,7 @@ defmodule MemexWeb.UserSessionController do
def delete(conn, _params) do def delete(conn, _params) do
conn conn
|> put_flash(:info, dgettext("prompts", "Logged out successfully.")) |> put_flash(:info, dgettext("prompts", "logged out successfully."))
|> UserAuth.log_out_user() |> UserAuth.log_out_user()
end end
end end

View File

@ -27,9 +27,7 @@
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input", id: "tags-input",
class: "input input-primary", class: "input input-primary",
placeholder: gettext("tag1,tag2"), placeholder: gettext("tag1,tag2")
phx_update: "ignore",
value: Contexts.get_tags_string(@changeset)
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

@ -3,7 +3,13 @@
<%= @context.slug %> <%= @context.slug %>
</h1> </h1>
<p><%= if @context.tags, do: @context.tags |> Enum.join(", ") %></p> <div class="flex flex-wrap space-x-1">
<%= for tag <- @context.tags do %>
<.link navigate={Routes.context_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
<.context_content context={@context} /> <.context_content context={@context} />

View File

@ -120,5 +120,26 @@
) %> ) %>
</p> </p>
</li> </li>
<li class="flex flex-col justify-center items-stretch space-y-2">
<b class="whitespace-nowrap">
<%= gettext("how many people should i invite?") %>
</b>
<p>
<%= gettext(
"while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
) %>
</p>
<p>
<%= gettext(
"note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
) %>
</p>
<p>
<%= gettext(
"so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
) %>
</p>
</li>
</ul> </ul>
</div> </div>

View File

@ -27,9 +27,7 @@
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input", id: "tags-input",
class: "input input-primary", class: "input input-primary",
placeholder: gettext("tag1,tag2"), placeholder: gettext("tag1,tag2")
phx_update: "ignore",
value: Notes.get_tags_string(@changeset)
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

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

View File

@ -3,16 +3,15 @@
<%= @note.slug %> <%= @note.slug %>
</h1> </h1>
<p><%= if @note.tags, do: @note.tags |> Enum.join(", ") %></p> <div class="flex flex-wrap space-x-1">
<%= for tag <- @note.tags do %>
<.link navigate={Routes.note_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
<textarea <.note_content note={@note} />
id="show-note-content"
class="input input-primary h-128 min-h-128"
phx-hook="MaintainAttrs"
phx-update="ignore"
readonly
phx-no-format
><%= @note.content %></textarea>
<p class="self-end"> <p class="self-end">
<%= gettext("Visibility: %{visibility}", visibility: @note.visibility) %> <%= gettext("Visibility: %{visibility}", visibility: @note.visibility) %>

View File

@ -27,9 +27,7 @@
<%= text_input(f, :tags_string, <%= text_input(f, :tags_string,
id: "tags-input", id: "tags-input",
class: "input input-primary", class: "input input-primary",
placeholder: gettext("tag1,tag2"), placeholder: gettext("tag1,tag2")
phx_update: "ignore",
value: Pipelines.get_tags_string(@changeset)
) %> ) %>
<%= error_tag(f, :tags_string) %> <%= error_tag(f, :tags_string) %>

View File

@ -3,7 +3,13 @@
<%= @pipeline.slug %> <%= @pipeline.slug %>
</h1> </h1>
<p><%= if @pipeline.tags, do: @pipeline.tags |> Enum.join(", ") %></p> <div class="flex flex-wrap space-x-1">
<%= for tag <- @pipeline.tags do %>
<.link navigate={Routes.pipeline_index_path(Endpoint, :search, tag)} class="link">
<%= tag %>
</.link>
<% end %>
</div>
<%= if @pipeline.description do %> <%= if @pipeline.description do %>
<textarea <textarea

View File

@ -76,6 +76,7 @@ defmodule MemexWeb.Router do
put "/users/settings", UserSettingsController, :update put "/users/settings", UserSettingsController, :update
delete "/users/settings/:id", UserSettingsController, :delete delete "/users/settings/:id", UserSettingsController, :delete
get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email
get "/export/:mode", ExportController, :export
end end
scope "/", MemexWeb do scope "/", MemexWeb do

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> <title>
<%= dgettext("errors", "Error") %>| memEx <%= dgettext("errors", "Error") %> | memEx
</title> </title>
<link rel="stylesheet" href="/css/app.css" /> <link rel="stylesheet" href="/css/app.css" />
<script defer type="text/javascript" src="/js/app.js"> <script defer type="text/javascript" src="/js/app.js">

View File

@ -33,7 +33,7 @@
<%= select( <%= select(
f, f,
:locale, :locale,
[{gettext("English"), "en_US"}], [{gettext("english"), "en_US"}],
class: "input input-primary col-span-2" class: "input input-primary col-span-2"
) %> ) %>
<%= error_tag(f, :locale) %> <%= error_tag(f, :locale) %>
@ -48,7 +48,7 @@
<%= dgettext("actions", "log in") %> <%= dgettext("actions", "log in") %>
</.link> </.link>
<.link href={Routes.user_reset_password_path(@conn, :new)} class="btn btn-primary"> <.link href={Routes.user_reset_password_path(@conn, :new)} class="btn btn-primary">
<%= dgettext("actions", "Forgot your password?") %> <%= dgettext("actions", "forgot your password?") %>
</.link> </.link>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
<div class="mx-auto mb-8 max-w-2xl flex flex-col justify-center items-center space-y-4"> <div class="mx-auto mb-8 max-w-2xl flex flex-col justify-center items-center space-y-4">
<h1 class="title text-primary-400 text-xl"> <h1 class="title text-primary-400 text-xl">
<%= dgettext("actions", "Forgot your password?") %> <%= dgettext("actions", "forgot your password?") %>
</h1> </h1>
<.form <.form
@ -12,7 +12,7 @@
<%= label(f, :email, class: "title text-lg text-primary-400") %> <%= label(f, :email, class: "title text-lg text-primary-400") %>
<%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %> <%= email_input(f, :email, required: true, class: "input input-primary col-span-2") %>
<%= submit(dgettext("actions", "Send instructions to reset password"), <%= submit(dgettext("actions", "send instructions to reset password"),
class: "mx-auto btn btn-primary col-span-3" class: "mx-auto btn btn-primary col-span-3"
) %> ) %>
</.form> </.form>

View File

@ -41,7 +41,7 @@
</.link> </.link>
<% end %> <% end %>
<.link href={Routes.user_reset_password_path(@conn, :new)} class="btn btn-primary"> <.link href={Routes.user_reset_password_path(@conn, :new)} class="btn btn-primary">
<%= dgettext("actions", "Forgot your password?") %> <%= dgettext("actions", "forgot your password?") %>
</.link> </.link>
</div> </div>
</div> </div>

View File

@ -136,12 +136,22 @@
<hr class="hr" /> <hr class="hr" />
<div class="flex justify-center items-center">
<.link
href={Routes.export_path(@conn, :export, :json)}
class="mx-4 my-2 btn btn-primary"
target="_blank"
>
<%= dgettext("actions", "export data as json") %>
</.link>
<.link <.link
href={Routes.user_settings_path(@conn, :delete, @current_user)} href={Routes.user_settings_path(@conn, :delete, @current_user)}
method={:delete} method={:delete}
class="btn btn-alert" class="mx-4 my-2 btn btn-alert"
data-confirm={dgettext("prompts", "are you sure you want to delete your account?")} data-confirm={dgettext("prompts", "are you sure you want to delete your account?")}
> >
<%= dgettext("actions", "delete user") %> <%= dgettext("actions", "delete user") %>
</.link> </.link>
</div>
</div> </div>

View File

@ -4,7 +4,7 @@ defmodule Memex.MixProject do
def project do def project do
[ [
app: :memex, app: :memex,
version: "0.1.1", version: "0.1.6",
elixir: "~> 1.14", elixir: "~> 1.14",
elixirc_paths: elixirc_paths(Mix.env()), elixirc_paths: elixirc_paths(Mix.env()),
compilers: Mix.compilers(), compilers: Mix.compilers(),

View File

@ -15,13 +15,6 @@ msgstr ""
msgid "Copy to clipboard" msgid "Copy to clipboard"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:51
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#, elixir-autogen, elixir-format
msgid "Forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:3 #: 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:15
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -39,11 +32,6 @@ msgstr ""
msgid "Save" msgid "Save"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#, elixir-autogen, elixir-format
msgid "Send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:15 #: lib/memex_web/templates/user_settings/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:44 #: lib/memex_web/templates/user_settings/edit.html.heex:44
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -68,28 +56,28 @@ msgid "create invite"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:49 #: lib/memex_web/live/context_live/index.html.heex:49
#: lib/memex_web/live/context_live/show.html.heex:34 #: lib/memex_web/live/context_live/show.html.heex:40
#: lib/memex_web/live/note_live/index.html.heex:49 #: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:38 #: lib/memex_web/live/note_live/show.html.heex:37
#: lib/memex_web/live/pipeline_live/index.html.heex:49 #: lib/memex_web/live/pipeline_live/index.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:43 #: lib/memex_web/live/pipeline_live/show.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:113 #: lib/memex_web/live/pipeline_live/show.html.heex:119
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "delete" msgid "delete"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:145 #: lib/memex_web/templates/user_settings/edit.html.heex:154
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "delete user" msgid "delete user"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:38 #: lib/memex_web/live/context_live/index.html.heex:38
#: lib/memex_web/live/context_live/show.html.heex:23 #: lib/memex_web/live/context_live/show.html.heex:29
#: lib/memex_web/live/note_live/index.html.heex:38 #: lib/memex_web/live/note_live/index.html.heex:38
#: lib/memex_web/live/note_live/show.html.heex:27 #: lib/memex_web/live/note_live/show.html.heex:26
#: lib/memex_web/live/pipeline_live/index.html.heex:38 #: lib/memex_web/live/pipeline_live/index.html.heex:38
#: lib/memex_web/live/pipeline_live/show.html.heex:32 #: lib/memex_web/live/pipeline_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/show.html.heex:102 #: lib/memex_web/live/pipeline_live/show.html.heex:108
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "edit" msgid "edit"
msgstr "" msgstr ""
@ -136,22 +124,39 @@ msgstr ""
msgid "register" msgid "register"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:42 #: lib/memex_web/live/context_live/form_component.html.heex:40
#: lib/memex_web/live/note_live/form_component.html.heex:42 #: lib/memex_web/live/note_live/form_component.html.heex:40
#: lib/memex_web/live/pipeline_live/form_component.html.heex:42 #: lib/memex_web/live/pipeline_live/form_component.html.heex:40
#: lib/memex_web/live/step_live/form_component.html.heex:28 #: lib/memex_web/live/step_live/form_component.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "save" msgid "save"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:16 #: lib/memex_web/live/context_live/show.html.heex:22
#: lib/memex_web/live/note_live/show.html.heex:23 #: lib/memex_web/live/note_live/show.html.heex:22
#: lib/memex_web/live/pipeline_live/show.html.heex:25 #: lib/memex_web/live/pipeline_live/show.html.heex:31
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "back" msgid "back"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:129 #: lib/memex_web/live/pipeline_live/show.html.heex:135
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "add step" msgid "add step"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:51
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#, elixir-autogen, elixir-format
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#, elixir-autogen, elixir-format
msgid "send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:145
#, elixir-autogen, elixir-format
msgid "export data as json"
msgstr ""

View File

@ -16,13 +16,6 @@ msgstr ""
msgid "Copy to clipboard" msgid "Copy to clipboard"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:51
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#, elixir-autogen, elixir-format
msgid "Forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_confirmation/new.html.heex:3 #: 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:15
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -40,11 +33,6 @@ msgstr ""
msgid "Save" msgid "Save"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#, elixir-autogen, elixir-format
msgid "Send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:15 #: lib/memex_web/templates/user_settings/edit.html.heex:15
#: lib/memex_web/templates/user_settings/edit.html.heex:44 #: lib/memex_web/templates/user_settings/edit.html.heex:44
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -69,28 +57,28 @@ msgid "create invite"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:49 #: lib/memex_web/live/context_live/index.html.heex:49
#: lib/memex_web/live/context_live/show.html.heex:34 #: lib/memex_web/live/context_live/show.html.heex:40
#: lib/memex_web/live/note_live/index.html.heex:49 #: lib/memex_web/live/note_live/index.html.heex:49
#: lib/memex_web/live/note_live/show.html.heex:38 #: lib/memex_web/live/note_live/show.html.heex:37
#: lib/memex_web/live/pipeline_live/index.html.heex:49 #: lib/memex_web/live/pipeline_live/index.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:43 #: lib/memex_web/live/pipeline_live/show.html.heex:49
#: lib/memex_web/live/pipeline_live/show.html.heex:113 #: lib/memex_web/live/pipeline_live/show.html.heex:119
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "delete" msgid "delete"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:145 #: lib/memex_web/templates/user_settings/edit.html.heex:154
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "delete user" msgid "delete user"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:38 #: lib/memex_web/live/context_live/index.html.heex:38
#: lib/memex_web/live/context_live/show.html.heex:23 #: lib/memex_web/live/context_live/show.html.heex:29
#: lib/memex_web/live/note_live/index.html.heex:38 #: lib/memex_web/live/note_live/index.html.heex:38
#: lib/memex_web/live/note_live/show.html.heex:27 #: lib/memex_web/live/note_live/show.html.heex:26
#: lib/memex_web/live/pipeline_live/index.html.heex:38 #: lib/memex_web/live/pipeline_live/index.html.heex:38
#: lib/memex_web/live/pipeline_live/show.html.heex:32 #: lib/memex_web/live/pipeline_live/show.html.heex:38
#: lib/memex_web/live/pipeline_live/show.html.heex:102 #: lib/memex_web/live/pipeline_live/show.html.heex:108
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "edit" msgid "edit"
msgstr "" msgstr ""
@ -137,22 +125,39 @@ msgstr ""
msgid "register" msgid "register"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:42 #: lib/memex_web/live/context_live/form_component.html.heex:40
#: lib/memex_web/live/note_live/form_component.html.heex:42 #: lib/memex_web/live/note_live/form_component.html.heex:40
#: lib/memex_web/live/pipeline_live/form_component.html.heex:42 #: lib/memex_web/live/pipeline_live/form_component.html.heex:40
#: lib/memex_web/live/step_live/form_component.html.heex:28 #: lib/memex_web/live/step_live/form_component.html.heex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "save" msgid "save"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:16 #: lib/memex_web/live/context_live/show.html.heex:22
#: lib/memex_web/live/note_live/show.html.heex:23 #: lib/memex_web/live/note_live/show.html.heex:22
#: lib/memex_web/live/pipeline_live/show.html.heex:25 #: lib/memex_web/live/pipeline_live/show.html.heex:31
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "back" msgid "back"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:129 #: lib/memex_web/live/pipeline_live/show.html.heex:135
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "add step" msgid "add step"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:51
#: lib/memex_web/templates/user_reset_password/new.html.heex:3
#: lib/memex_web/templates/user_session/new.html.heex:44
#, elixir-autogen, elixir-format, fuzzy
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_reset_password/new.html.heex:15
#, elixir-autogen, elixir-format, fuzzy
msgid "send instructions to reset password"
msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:145
#, elixir-autogen, elixir-format
msgid "export data as json"
msgstr ""

View File

@ -31,16 +31,6 @@ msgstr ""
msgid "Confirm your account" msgid "Confirm your account"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:36
#, elixir-autogen, elixir-format
msgid "English"
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:9
#, elixir-autogen, elixir-format
msgid "Forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:27 #: lib/memex_web/templates/user_session/new.html.heex:27
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Keep me logged in for 60 days" msgid "Keep me logged in for 60 days"
@ -76,11 +66,6 @@ msgstr ""
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
#: lib/memex_web/components/user_card.ex:33
#, elixir-autogen, elixir-format
msgid "User registered on"
msgstr ""
#: lib/memex_web/components/invite_card.ex:19 #: lib/memex_web/components/invite_card.ex:19
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Uses Left:" msgid "Uses Left:"
@ -91,9 +76,9 @@ msgstr ""
msgid "Uses left" msgid "Uses left"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:11 #: lib/memex_web/live/context_live/show.html.heex:17
#: lib/memex_web/live/note_live/show.html.heex:18 #: lib/memex_web/live/note_live/show.html.heex:17
#: lib/memex_web/live/pipeline_live/show.html.heex:20 #: lib/memex_web/live/pipeline_live/show.html.heex:26
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Visibility: %{visibility}" msgid "Visibility: %{visibility}"
msgstr "" msgstr ""
@ -182,6 +167,7 @@ msgstr ""
msgid "enable" msgid "enable"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:36
#: lib/memex_web/templates/user_settings/edit.html.heex:126 #: lib/memex_web/templates/user_settings/edit.html.heex:126
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "english" msgid "english"
@ -315,17 +301,17 @@ msgstr ""
msgid "report bugs or request features" msgid "report bugs or request features"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:43 #: lib/memex_web/live/context_live/form_component.html.heex:41
#: lib/memex_web/live/note_live/form_component.html.heex:43 #: lib/memex_web/live/note_live/form_component.html.heex:41
#: lib/memex_web/live/pipeline_live/form_component.html.heex:43 #: lib/memex_web/live/pipeline_live/form_component.html.heex:41
#: lib/memex_web/live/step_live/form_component.html.heex:29 #: lib/memex_web/live/step_live/form_component.html.heex:29
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:39 #: lib/memex_web/live/context_live/form_component.html.heex:37
#: lib/memex_web/live/note_live/form_component.html.heex:39 #: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:39 #: lib/memex_web/live/pipeline_live/form_component.html.heex:37
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "select privacy" msgid "select privacy"
msgstr "" msgstr ""
@ -359,11 +345,6 @@ msgstr ""
msgid "unlimited" msgid "unlimited"
msgstr "" msgstr ""
#: lib/memex_web/components/user_card.ex:25
#, elixir-autogen, elixir-format
msgid "user was confirmed at %{relative_datetime}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:120 #: lib/memex_web/live/invite_live/index.html.heex:120
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "users" msgid "users"
@ -510,7 +491,7 @@ msgstr ""
msgid "what is this?" msgid "what is this?"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:62 #: lib/memex_web/live/pipeline_live/show.html.heex:68
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{position}. %{title}" msgid "%{position}. %{title}"
msgstr "" msgstr ""
@ -535,12 +516,12 @@ msgstr ""
msgid "add step to %{slug}" msgid "add step to %{slug}"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:56 #: lib/memex_web/live/pipeline_live/show.html.heex:62
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "no steps" msgid "no steps"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:51 #: lib/memex_web/live/pipeline_live/show.html.heex:57
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "steps:" msgid "steps:"
msgstr "" msgstr ""
@ -649,3 +630,38 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "memEx | %{title}" msgid "memEx | %{title}"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:9
#, elixir-autogen, elixir-format, fuzzy
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:126
#, elixir-autogen, elixir-format
msgid "how many people should i invite?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:134
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:139
#, elixir-autogen, elixir-format
msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:129
#, elixir-autogen, elixir-format
msgid "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
msgstr ""
#: lib/memex_web/components/user_card.ex:26
#, elixir-autogen, elixir-format
msgid "user confirmed on"
msgstr ""
#: lib/memex_web/components/user_card.ex:33
#, elixir-autogen, elixir-format, fuzzy
msgid "user registered on"
msgstr ""

View File

@ -76,22 +76,22 @@ msgstr ""
msgid "You must confirm your account and log in to access this page." msgid "You must confirm your account and log in to access this page."
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:129 #: lib/memex/accounts/user.ex:139
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "did not change" msgid "did not change"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:150 #: lib/memex/accounts/user.ex:160
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "does not match password" msgid "does not match password"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:187 #: lib/memex/accounts/user.ex:197
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "is not valid" msgid "is not valid"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:85 #: lib/memex/accounts/user.ex:95
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "must have the @ sign and no spaces" msgid "must have the @ sign and no spaces"
msgstr "" msgstr ""
@ -102,12 +102,12 @@ msgstr ""
msgid "oops, something went wrong! Please check the errors below" msgid "oops, something went wrong! Please check the errors below"
msgstr "" msgstr ""
#: lib/memex/contexts/context.ex:49 #: lib/memex/contexts/context.ex:58
#: lib/memex/contexts/context.ex:60 #: lib/memex/contexts/context.ex:71
#: lib/memex/notes/note.ex:48 #: lib/memex/notes/note.ex:57
#: lib/memex/notes/note.ex:59 #: lib/memex/notes/note.ex:70
#: lib/memex/pipelines/pipeline.ex:50 #: lib/memex/pipelines/pipeline.ex:60
#: lib/memex/pipelines/pipeline.ex:61 #: lib/memex/pipelines/pipeline.ex:73
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted" msgid "invalid format: only numbers, letters and hyphen are accepted"
msgstr "" msgstr ""
@ -131,3 +131,10 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "unauthorized" msgid "unauthorized"
msgstr "" msgstr ""
#: lib/memex/contexts/context.ex:84
#: lib/memex/notes/note.ex:83
#: lib/memex/pipelines/pipeline.ex:86
#, elixir-autogen, elixir-format, fuzzy
msgid "invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
msgstr ""

View File

@ -81,11 +81,6 @@ msgstr ""
msgid "Language updated successfully." msgid "Language updated successfully."
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:23
#, elixir-autogen, elixir-format
msgid "Logged out successfully."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:46 #: lib/memex_web/controllers/user_reset_password_controller.ex:46
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Password reset successfully." msgid "Password reset successfully."
@ -127,7 +122,7 @@ msgstr ""
msgid "are you sure you want to delete the invite for %{invite_name}?" msgid "are you sure you want to delete the invite for %{invite_name}?"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:143 #: lib/memex_web/templates/user_settings/edit.html.heex:152
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "are you sure you want to delete your account?" msgid "are you sure you want to delete your account?"
msgstr "" msgstr ""
@ -143,12 +138,12 @@ msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:46 #: lib/memex_web/live/context_live/index.html.heex:46
#: lib/memex_web/live/context_live/show.html.heex:31 #: lib/memex_web/live/context_live/show.html.heex:37
#: lib/memex_web/live/note_live/index.html.heex:46 #: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:35 #: lib/memex_web/live/note_live/show.html.heex:34
#: lib/memex_web/live/pipeline_live/index.html.heex:46 #: lib/memex_web/live/pipeline_live/index.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:40 #: lib/memex_web/live/pipeline_live/show.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:110 #: lib/memex_web/live/pipeline_live/show.html.heex:116
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "are you sure?" msgid "are you sure?"
msgstr "" msgstr ""
@ -157,3 +152,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "register to setup %{name}" msgid "register to setup %{name}"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:23
#, elixir-autogen, elixir-format, fuzzy
msgid "logged out successfully."
msgstr ""

View File

@ -20,16 +20,6 @@ msgstr ""
msgid "Confirm your account" msgid "Confirm your account"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:36
#, elixir-autogen, elixir-format
msgid "English"
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:9
#, elixir-autogen, elixir-format
msgid "Forgot your password?"
msgstr ""
#: lib/memex_web/templates/user_session/new.html.heex:27 #: lib/memex_web/templates/user_session/new.html.heex:27
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Keep me logged in for 60 days" msgid "Keep me logged in for 60 days"
@ -65,11 +55,6 @@ msgstr ""
msgid "Settings" msgid "Settings"
msgstr "" msgstr ""
#: lib/memex_web/components/user_card.ex:33
#, elixir-autogen, elixir-format
msgid "User registered on"
msgstr ""
#: lib/memex_web/components/invite_card.ex:19 #: lib/memex_web/components/invite_card.ex:19
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Uses Left:" msgid "Uses Left:"
@ -80,9 +65,9 @@ msgstr ""
msgid "Uses left" msgid "Uses left"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/show.html.heex:11 #: lib/memex_web/live/context_live/show.html.heex:17
#: lib/memex_web/live/note_live/show.html.heex:18 #: lib/memex_web/live/note_live/show.html.heex:17
#: lib/memex_web/live/pipeline_live/show.html.heex:20 #: lib/memex_web/live/pipeline_live/show.html.heex:26
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Visibility: %{visibility}" msgid "Visibility: %{visibility}"
msgstr "" msgstr ""
@ -171,6 +156,7 @@ msgstr ""
msgid "enable" msgid "enable"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_registration/new.html.heex:36
#: lib/memex_web/templates/user_settings/edit.html.heex:126 #: lib/memex_web/templates/user_settings/edit.html.heex:126
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "english" msgid "english"
@ -304,17 +290,17 @@ msgstr ""
msgid "report bugs or request features" msgid "report bugs or request features"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:43 #: lib/memex_web/live/context_live/form_component.html.heex:41
#: lib/memex_web/live/note_live/form_component.html.heex:43 #: lib/memex_web/live/note_live/form_component.html.heex:41
#: lib/memex_web/live/pipeline_live/form_component.html.heex:43 #: lib/memex_web/live/pipeline_live/form_component.html.heex:41
#: lib/memex_web/live/step_live/form_component.html.heex:29 #: lib/memex_web/live/step_live/form_component.html.heex:29
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "saving..." msgid "saving..."
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/form_component.html.heex:39 #: lib/memex_web/live/context_live/form_component.html.heex:37
#: lib/memex_web/live/note_live/form_component.html.heex:39 #: lib/memex_web/live/note_live/form_component.html.heex:37
#: lib/memex_web/live/pipeline_live/form_component.html.heex:39 #: lib/memex_web/live/pipeline_live/form_component.html.heex:37
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "select privacy" msgid "select privacy"
msgstr "" msgstr ""
@ -348,11 +334,6 @@ msgstr ""
msgid "unlimited" msgid "unlimited"
msgstr "" msgstr ""
#: lib/memex_web/components/user_card.ex:25
#, elixir-autogen, elixir-format
msgid "user was confirmed at %{relative_datetime}"
msgstr ""
#: lib/memex_web/live/invite_live/index.html.heex:120 #: lib/memex_web/live/invite_live/index.html.heex:120
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "users" msgid "users"
@ -499,7 +480,7 @@ msgstr ""
msgid "what is this?" msgid "what is this?"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:62 #: lib/memex_web/live/pipeline_live/show.html.heex:68
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{position}. %{title}" msgid "%{position}. %{title}"
msgstr "" msgstr ""
@ -524,12 +505,12 @@ msgstr ""
msgid "add step to %{slug}" msgid "add step to %{slug}"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:56 #: lib/memex_web/live/pipeline_live/show.html.heex:62
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "no steps" msgid "no steps"
msgstr "" msgstr ""
#: lib/memex_web/live/pipeline_live/show.html.heex:51 #: lib/memex_web/live/pipeline_live/show.html.heex:57
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "steps:" msgid "steps:"
msgstr "" msgstr ""
@ -638,3 +619,38 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "memEx | %{title}" msgid "memEx | %{title}"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:9
#, elixir-autogen, elixir-format
msgid "forgot your password?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:126
#, elixir-autogen, elixir-format
msgid "how many people should i invite?"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:134
#, elixir-autogen, elixir-format
msgid "note, context and pipeline slugs must be unique, and you are free to backlink to notes not written by you."
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:139
#, elixir-autogen, elixir-format
msgid "so, i'd recommend inviting anyone you'd like to work on your collective memEx. however, when in doubt, hopefully setting up a new instance is easy enough. if it isn't, then feel free to let me know :)"
msgstr ""
#: lib/memex_web/live/faq_live.html.heex:129
#, elixir-autogen, elixir-format
msgid "while memEx fully supports multiple users, each memEx instance should be treated as a single cohesive and collaborative document."
msgstr ""
#: lib/memex_web/components/user_card.ex:26
#, elixir-autogen, elixir-format
msgid "user confirmed on"
msgstr ""
#: lib/memex_web/components/user_card.ex:33
#, elixir-autogen, elixir-format
msgid "user registered on"
msgstr ""

View File

@ -75,22 +75,22 @@ msgstr ""
msgid "You must confirm your account and log in to access this page." msgid "You must confirm your account and log in to access this page."
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:129 #: lib/memex/accounts/user.ex:139
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "did not change" msgid "did not change"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:150 #: lib/memex/accounts/user.ex:160
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "does not match password" msgid "does not match password"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:187 #: lib/memex/accounts/user.ex:197
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "is not valid" msgid "is not valid"
msgstr "" msgstr ""
#: lib/memex/accounts/user.ex:85 #: lib/memex/accounts/user.ex:95
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "must have the @ sign and no spaces" msgid "must have the @ sign and no spaces"
msgstr "" msgstr ""
@ -101,12 +101,12 @@ msgstr ""
msgid "oops, something went wrong! Please check the errors below" msgid "oops, something went wrong! Please check the errors below"
msgstr "" msgstr ""
#: lib/memex/contexts/context.ex:49 #: lib/memex/contexts/context.ex:58
#: lib/memex/contexts/context.ex:60 #: lib/memex/contexts/context.ex:71
#: lib/memex/notes/note.ex:48 #: lib/memex/notes/note.ex:57
#: lib/memex/notes/note.ex:59 #: lib/memex/notes/note.ex:70
#: lib/memex/pipelines/pipeline.ex:50 #: lib/memex/pipelines/pipeline.ex:60
#: lib/memex/pipelines/pipeline.ex:61 #: lib/memex/pipelines/pipeline.ex:73
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted" msgid "invalid format: only numbers, letters and hyphen are accepted"
msgstr "" msgstr ""
@ -130,3 +130,10 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "unauthorized" msgid "unauthorized"
msgstr "" msgstr ""
#: lib/memex/contexts/context.ex:84
#: lib/memex/notes/note.ex:83
#: lib/memex/pipelines/pipeline.ex:86
#, elixir-autogen, elixir-format
msgid "invalid format: only numbers, letters and hyphen are accepted. tags must be comma-delimited"
msgstr ""

View File

@ -80,11 +80,6 @@ msgstr ""
msgid "Language updated successfully." msgid "Language updated successfully."
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:23
#, elixir-autogen, elixir-format
msgid "Logged out successfully."
msgstr ""
#: lib/memex_web/controllers/user_reset_password_controller.ex:46 #: lib/memex_web/controllers/user_reset_password_controller.ex:46
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Password reset successfully." msgid "Password reset successfully."
@ -126,7 +121,7 @@ msgstr ""
msgid "are you sure you want to delete the invite for %{invite_name}?" msgid "are you sure you want to delete the invite for %{invite_name}?"
msgstr "" msgstr ""
#: lib/memex_web/templates/user_settings/edit.html.heex:143 #: lib/memex_web/templates/user_settings/edit.html.heex:152
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "are you sure you want to delete your account?" msgid "are you sure you want to delete your account?"
msgstr "" msgstr ""
@ -142,12 +137,12 @@ msgid "are you sure you want to make %{invite_name} unlimited?"
msgstr "" msgstr ""
#: lib/memex_web/live/context_live/index.html.heex:46 #: lib/memex_web/live/context_live/index.html.heex:46
#: lib/memex_web/live/context_live/show.html.heex:31 #: lib/memex_web/live/context_live/show.html.heex:37
#: lib/memex_web/live/note_live/index.html.heex:46 #: lib/memex_web/live/note_live/index.html.heex:46
#: lib/memex_web/live/note_live/show.html.heex:35 #: lib/memex_web/live/note_live/show.html.heex:34
#: lib/memex_web/live/pipeline_live/index.html.heex:46 #: lib/memex_web/live/pipeline_live/index.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:40 #: lib/memex_web/live/pipeline_live/show.html.heex:46
#: lib/memex_web/live/pipeline_live/show.html.heex:110 #: lib/memex_web/live/pipeline_live/show.html.heex:116
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "are you sure?" msgid "are you sure?"
msgstr "" msgstr ""
@ -156,3 +151,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "register to setup %{name}" msgid "register to setup %{name}"
msgstr "" msgstr ""
#: lib/memex_web/controllers/user_session_controller.ex:23
#, elixir-autogen, elixir-format
msgid "logged out successfully."
msgstr ""

View File

@ -0,0 +1,101 @@
defmodule MemexWeb.ExportControllerTest do
@moduledoc """
Tests the export function
"""
use MemexWeb.ConnCase
import Memex.{ContextsFixtures, NotesFixtures, PipelinesFixtures, StepsFixtures}
@moduletag :export_controller_test
setup %{conn: conn} do
current_user = user_fixture() |> confirm_user()
[
current_user: current_user,
conn: conn |> log_in_user(current_user)
]
end
defp add_data(%{current_user: current_user}) do
note = note_fixture(current_user)
context = context_fixture(current_user)
pipeline = pipeline_fixture(current_user)
step = step_fixture(0, pipeline, current_user)
%{
note: note,
context: context,
pipeline: pipeline,
step: step
}
end
describe "Exports data" do
setup [:add_data]
test "in JSON", %{
conn: conn,
current_user: current_user,
note: note,
context: context,
pipeline: pipeline,
step: step
} do
conn = get(conn, Routes.export_path(conn, :export, :json))
ideal_note = %{
"slug" => note.slug,
"content" => note.content,
"tags" => note.tags,
"visibility" => note.visibility |> to_string(),
"inserted_at" => note.inserted_at |> NaiveDateTime.to_iso8601(),
"updated_at" => note.updated_at |> NaiveDateTime.to_iso8601()
}
ideal_context = %{
"slug" => context.slug,
"content" => context.content,
"tags" => context.tags,
"visibility" => context.visibility |> to_string(),
"inserted_at" => context.inserted_at |> NaiveDateTime.to_iso8601(),
"updated_at" => context.updated_at |> NaiveDateTime.to_iso8601()
}
ideal_pipeline = %{
"slug" => pipeline.slug,
"description" => pipeline.description,
"tags" => pipeline.tags,
"visibility" => pipeline.visibility |> to_string(),
"inserted_at" => pipeline.inserted_at |> NaiveDateTime.to_iso8601(),
"updated_at" => pipeline.updated_at |> NaiveDateTime.to_iso8601(),
"steps" => [
%{
"title" => step.title,
"content" => step.content,
"position" => step.position,
"inserted_at" => step.inserted_at |> NaiveDateTime.to_iso8601(),
"updated_at" => step.updated_at |> NaiveDateTime.to_iso8601()
}
]
}
ideal_user = %{
"confirmed_at" =>
current_user.confirmed_at |> Jason.encode!() |> String.replace(~r/\"/, ""),
"email" => current_user.email,
"id" => current_user.id,
"locale" => current_user.locale,
"role" => to_string(current_user.role),
"inserted_at" => current_user.inserted_at |> NaiveDateTime.to_iso8601(),
"updated_at" => current_user.updated_at |> NaiveDateTime.to_iso8601()
}
json_resp = conn |> json_response(200)
assert %{"notes" => [^ideal_note]} = json_resp
assert %{"contexts" => [^ideal_context]} = json_resp
assert %{"pipelines" => [^ideal_pipeline]} = json_resp
assert %{"user" => ^ideal_user} = json_resp
end
end
end

View File

@ -17,7 +17,7 @@ defmodule MemexWeb.UserResetPasswordControllerTest do
test "renders the reset password page", %{conn: conn} do test "renders the reset password page", %{conn: conn} do
conn = get(conn, Routes.user_reset_password_path(conn, :new)) conn = get(conn, Routes.user_reset_password_path(conn, :new))
response = html_response(conn, 200) response = html_response(conn, 200)
assert response =~ dgettext("actions", "Forgot your password?") assert response =~ dgettext("actions", "forgot your password?")
end end
end end

View File

@ -88,14 +88,14 @@ defmodule MemexWeb.UserSessionControllerTest do
conn = conn |> log_in_user(current_user) |> delete(Routes.user_session_path(conn, :delete)) conn = conn |> log_in_user(current_user) |> delete(Routes.user_session_path(conn, :delete))
assert redirected_to(conn) == "/" assert redirected_to(conn) == "/"
refute get_session(conn, :user_token) refute get_session(conn, :user_token)
assert get_flash(conn, :info) =~ gettext("Logged out successfully") assert get_flash(conn, :info) =~ gettext("logged out successfully")
end end
test "succeeds even if the user is not logged in", %{conn: conn} do test "succeeds even if the user is not logged in", %{conn: conn} do
conn = delete(conn, Routes.user_session_path(conn, :delete)) conn = delete(conn, Routes.user_session_path(conn, :delete))
assert redirected_to(conn) == "/" assert redirected_to(conn) == "/"
refute get_session(conn, :user_token) refute get_session(conn, :user_token)
assert get_flash(conn, :info) =~ gettext("Logged out successfully") assert get_flash(conn, :info) =~ gettext("logged out successfully")
end end
end end
end end

View File

@ -18,7 +18,7 @@ defmodule MemexWeb.ContextLiveTest do
} }
@invalid_attrs %{ @invalid_attrs %{
"content" => nil, "content" => nil,
"tags_string" => "", "tags_string" => " ",
"slug" => nil, "slug" => nil,
"visibility" => nil "visibility" => nil
} }
@ -37,6 +37,14 @@ defmodule MemexWeb.ContextLiveTest do
assert html =~ context.slug assert html =~ context.slug
end end
test "searches by tag", %{conn: conn} do
{:ok, index_live, html} = live(conn, Routes.context_index_path(conn, :index))
assert html =~ "example-tag"
assert index_live |> element("a", "example-tag") |> render_click()
assert_patch(index_live, Routes.context_index_path(conn, :search, "example-tag"))
end
test "saves new context", %{conn: conn} do test "saves new context", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.context_index_path(conn, :index)) {:ok, index_live, _html} = live(conn, Routes.context_index_path(conn, :index))
@ -106,9 +114,13 @@ defmodule MemexWeb.ContextLiveTest do
assert_patch(show_live, Routes.context_show_path(conn, :edit, context.slug)) assert_patch(show_live, Routes.context_show_path(conn, :edit, context.slug))
assert show_live html =
show_live
|> form("#context-form", context: @invalid_attrs) |> form("#context-form", context: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank" |> render_change()
assert html =~ "can&#39;t be blank"
assert html =~ "tags must be comma-delimited"
{:ok, _, html} = {:ok, _, html} =
show_live show_live
@ -146,6 +158,14 @@ defmodule MemexWeb.ContextLiveTest do
] ]
end end
test "searches by tag", %{conn: conn, context: context} do
{:ok, show_live, html} = live(conn, Routes.context_show_path(conn, :show, context.slug))
assert html =~ "example-tag"
assert show_live |> element("a", "example-tag") |> render_click()
assert_redirect(show_live, Routes.context_index_path(conn, :search, "example-tag"))
end
test "displays context", %{conn: conn, context: context, note: %{slug: note_slug}} do test "displays context", %{conn: conn, context: context, note: %{slug: note_slug}} do
{:ok, show_live, html} = live(conn, Routes.context_show_path(conn, :show, context.slug)) {:ok, show_live, html} = live(conn, Routes.context_show_path(conn, :show, context.slug))

View File

@ -3,6 +3,7 @@ defmodule MemexWeb.NoteLiveTest do
import Phoenix.LiveViewTest import Phoenix.LiveViewTest
import Memex.NotesFixtures import Memex.NotesFixtures
alias MemexWeb.Endpoint
@create_attrs %{ @create_attrs %{
"content" => "some content", "content" => "some content",
@ -18,7 +19,7 @@ defmodule MemexWeb.NoteLiveTest do
} }
@invalid_attrs %{ @invalid_attrs %{
"content" => nil, "content" => nil,
"tags_string" => "", "tags_string" => " ",
"slug" => nil, "slug" => nil,
"visibility" => nil "visibility" => nil
} }
@ -37,6 +38,14 @@ defmodule MemexWeb.NoteLiveTest do
assert html =~ note.slug assert html =~ note.slug
end end
test "searches by tag", %{conn: conn} do
{:ok, index_live, html} = live(conn, Routes.note_index_path(conn, :index))
assert html =~ "example-tag"
assert index_live |> element("a", "example-tag") |> render_click()
assert_patch(index_live, Routes.note_index_path(conn, :search, "example-tag"))
end
test "saves new note", %{conn: conn} do test "saves new note", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index)) {:ok, index_live, _html} = live(conn, Routes.note_index_path(conn, :index))
@ -45,9 +54,13 @@ defmodule MemexWeb.NoteLiveTest do
assert_patch(index_live, Routes.note_index_path(conn, :new)) assert_patch(index_live, Routes.note_index_path(conn, :new))
assert index_live html =
index_live
|> form("#note-form", note: @invalid_attrs) |> form("#note-form", note: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank" |> render_change()
assert html =~ "can&#39;t be blank"
assert html =~ "tags must be comma-delimited"
{:ok, _, html} = {:ok, _, html} =
index_live index_live
@ -132,4 +145,39 @@ defmodule MemexWeb.NoteLiveTest do
refute has_element?(index_live, "#note-#{note.id}") refute has_element?(index_live, "#note-#{note.id}")
end end
end end
describe "show with note" do
setup [:register_and_log_in_user]
setup %{user: user} do
%{slug: note_slug} = note = note_fixture(user)
[
note: note,
backlinked_note:
note_fixture(%{content: "example with backlink to [[#{note_slug}]] note"}, user)
]
end
test "searches by tag", %{conn: conn, note: note} do
{:ok, show_live, html} = live(conn, Routes.note_show_path(conn, :show, note.slug))
assert html =~ "example-tag"
assert show_live |> element("a", "example-tag") |> render_click()
assert_redirect(show_live, Routes.note_index_path(conn, :search, "example-tag"))
end
test "displays context", %{
conn: conn,
backlinked_note: %{slug: backlinked_note_slug},
note: %{slug: note_slug}
} do
{:ok, show_live, html} =
live(conn, Routes.note_show_path(conn, :show, backlinked_note_slug))
assert html =~ "context"
assert html =~ Routes.note_show_path(Endpoint, :show, note_slug)
assert has_element?(show_live, "[data-qa=\"note-link-#{note_slug}\"]")
end
end
end end

View File

@ -17,7 +17,7 @@ defmodule MemexWeb.PipelineLiveTest do
} }
@invalid_attrs %{ @invalid_attrs %{
"description" => nil, "description" => nil,
"tags_string" => "", "tags_string" => " ",
"slug" => nil, "slug" => nil,
"visibility" => nil "visibility" => nil
} }
@ -48,6 +48,14 @@ defmodule MemexWeb.PipelineLiveTest do
assert html =~ pipeline.description assert html =~ pipeline.description
end end
test "searches by tag", %{conn: conn} do
{:ok, index_live, html} = live(conn, Routes.pipeline_index_path(conn, :index))
assert html =~ "example-tag"
assert index_live |> element("a", "example-tag") |> render_click()
assert_patch(index_live, Routes.pipeline_index_path(conn, :search, "example-tag"))
end
test "saves new pipeline", %{conn: conn} do test "saves new pipeline", %{conn: conn} do
{:ok, index_live, _html} = live(conn, Routes.pipeline_index_path(conn, :index)) {:ok, index_live, _html} = live(conn, Routes.pipeline_index_path(conn, :index))
@ -120,9 +128,13 @@ defmodule MemexWeb.PipelineLiveTest do
assert_patch(show_live, Routes.pipeline_show_path(conn, :edit, pipeline.slug)) assert_patch(show_live, Routes.pipeline_show_path(conn, :edit, pipeline.slug))
assert show_live html =
show_live
|> form("#pipeline-form", pipeline: @invalid_attrs) |> form("#pipeline-form", pipeline: @invalid_attrs)
|> render_change() =~ "can&#39;t be blank" |> render_change()
assert html =~ "can&#39;t be blank"
assert html =~ "tags must be comma-delimited"
{:ok, _, html} = {:ok, _, html} =
show_live show_live
@ -175,6 +187,14 @@ defmodule MemexWeb.PipelineLiveTest do
] ]
end end
test "searches by tag", %{conn: conn, pipeline: pipeline} do
{:ok, show_live, html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))
assert html =~ "example-tag"
assert show_live |> element("a", "example-tag") |> render_click()
assert_redirect(show_live, Routes.pipeline_index_path(conn, :search, "example-tag"))
end
test "updates a step", %{conn: conn, pipeline: pipeline, step: step} do test "updates a step", %{conn: conn, pipeline: pipeline, step: step} do
{:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug)) {:ok, show_live, _html} = live(conn, Routes.pipeline_show_path(conn, :show, pipeline.slug))

View File

@ -16,12 +16,12 @@ defmodule Memex.ContextsFixtures do
attrs attrs
|> Enum.into(%{ |> Enum.into(%{
content: "some content", content: "some content",
tags: [], tags: ["example-tag"],
slug: random_slug(), slug: random_slug(),
visibility: :private visibility: :private
}) })
|> Contexts.create_context(user) |> Contexts.create_context(user)
context %{context | tags_string: nil}
end end
end end

View File

@ -16,12 +16,12 @@ defmodule Memex.NotesFixtures do
attrs attrs
|> Enum.into(%{ |> Enum.into(%{
content: "some content", content: "some content",
tags: [], tags: ["example-tag"],
slug: random_slug(), slug: random_slug(),
visibility: :private visibility: :private
}) })
|> Notes.create_note(user) |> Notes.create_note(user)
note %{note | tags_string: nil}
end end
end end

View File

@ -16,12 +16,12 @@ defmodule Memex.PipelinesFixtures do
attrs attrs
|> Enum.into(%{ |> Enum.into(%{
description: "some description", description: "some description",
tags: [], tags: ["example-tag"],
slug: random_slug(), slug: random_slug(),
visibility: :private visibility: :private
}) })
|> Pipelines.create_pipeline(user) |> Pipelines.create_pipeline(user)
pipeline %{pipeline | tags_string: nil}
end end
end end