mirror of
https://github.com/ClaperCo/Claper.git
synced 2026-08-29 10:09:08 +02:00
Add audit log (#214)
* Add audit log * Update translation files * Improve Audit queries * Improve Audit.Log schema * Make user auth audit logs async * Relax Flop and Flop Phoenix dep specs * Make Flop.validate!/2 call more robust * Improve a11y and UI for audit log live view * Improve audit_logs indexes * Fix formatting * Fix async_log_action and tests * Add remote_ip * Update translation files
This commit is contained in:
@@ -75,6 +75,14 @@ MAIL_FROM_NAME=Claper
|
||||
# GS_JPG_RESOLUTION=300x300
|
||||
# LANGUAGES=en,fr,es,it,nl,de
|
||||
|
||||
# == Reverse proxy / IP forwarding (set these if Claper runs behind a load balancer or reverse proxy)
|
||||
|
||||
# Comma-separated list of trusted proxy IPs or CIDR ranges whose forwarding headers will be trusted
|
||||
# REMOTE_IP_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
|
||||
# Comma-separated list of headers to inspect for the real client IP (replaces the defaults: forwarded, x-forwarded-for, x-client-ip, x-real-ip)
|
||||
# REMOTE_IP_HEADERS=forwarded,x-forwarded-for,x-client-ip,x-real-ip
|
||||
|
||||
|
||||
# === OIDC configuration ===
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ config :porcelain, driver: Porcelain.Driver.Basic
|
||||
|
||||
config :claper, :storage_dir, System.get_env("PRESENTATION_STORAGE_DIR", "priv/static")
|
||||
|
||||
config :flop, repo: Claper.Repo
|
||||
|
||||
# Import environment specific config. This must remain at the bottom
|
||||
# of this file so it overrides the configuration defined above.
|
||||
import_config "#{config_env()}.exs"
|
||||
|
||||
@@ -110,6 +110,22 @@ s3_public_url =
|
||||
)
|
||||
)
|
||||
|
||||
remote_ip_proxies =
|
||||
get_var_from_path_or_env(config_dir, "REMOTE_IP_PROXIES", "")
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
|
||||
remote_ip_headers =
|
||||
get_var_from_path_or_env(
|
||||
config_dir,
|
||||
"REMOTE_IP_HEADERS",
|
||||
"forwarded,x-forwarded-for,x-client-ip,x-real-ip"
|
||||
)
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.trim/1)
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
|
||||
same_site_cookie = get_var_from_path_or_env(config_dir, "SAME_SITE_COOKIE", "Lax")
|
||||
|
||||
secure_cookie =
|
||||
@@ -192,7 +208,9 @@ config :claper,
|
||||
email_confirmation: email_confirmation,
|
||||
allow_unlink_external_provider: allow_unlink_external_provider,
|
||||
logout_redirect_url: logout_redirect_url,
|
||||
languages: languages
|
||||
languages: languages,
|
||||
remote_ip_proxies: remote_ip_proxies,
|
||||
remote_ip_headers: remote_ip_headers
|
||||
|
||||
config :claper, :presentations,
|
||||
max_file_size: max_file_size,
|
||||
|
||||
125
lib/claper/audit.ex
Normal file
125
lib/claper/audit.ex
Normal file
@@ -0,0 +1,125 @@
|
||||
defmodule Claper.Audit do
|
||||
@moduledoc """
|
||||
The Audit context for tracking actions in the system.
|
||||
"""
|
||||
|
||||
import Ecto.Query, only: [from: 2]
|
||||
|
||||
alias Claper.{Accounts, Repo}
|
||||
alias Claper.Audit.Log
|
||||
|
||||
@doc """
|
||||
Logs an action.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> log_action(user, "user.login", %{ip_address: "127.0.0.1"})
|
||||
{:ok, %Log{}}
|
||||
|
||||
iex> log_action(nil, "system.startup", %{})
|
||||
{:ok, %Log{}}
|
||||
|
||||
"""
|
||||
def log_action(user, action, metadata \\ %{})
|
||||
|
||||
def log_action(%Accounts.User{} = user, action, metadata) do
|
||||
create_log(%{
|
||||
user_id: user.id,
|
||||
action: action,
|
||||
metadata: metadata
|
||||
})
|
||||
end
|
||||
|
||||
def log_action(nil, action, metadata) do
|
||||
create_log(%{
|
||||
action: action,
|
||||
metadata: metadata
|
||||
})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Logs an action related to a specific resource.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> log_resource_action(user, "event.create", "event", 123, %{})
|
||||
{:ok, %Log{}}
|
||||
|
||||
"""
|
||||
def log_resource_action(
|
||||
%Accounts.User{} = user,
|
||||
action,
|
||||
resource_type,
|
||||
resource_id,
|
||||
metadata \\ %{}
|
||||
) do
|
||||
create_log(%{
|
||||
user_id: user.id,
|
||||
action: action,
|
||||
resource_type: resource_type,
|
||||
resource_id: resource_id,
|
||||
metadata: metadata
|
||||
})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a paginated, optionally filtered and sorted, list of audit logs.
|
||||
"""
|
||||
def list_logs(params \\ %{}) do
|
||||
query = from l in Log, left_join: u in assoc(l, :user), as: :user, preload: [user: u]
|
||||
Flop.validate_and_run!(query, params, for: Log, replace_invalid_params: true)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a list of distinct action types for filtering.
|
||||
"""
|
||||
def list_action_types do
|
||||
from(l in Log,
|
||||
distinct: true,
|
||||
select: l.action,
|
||||
order_by: l.action
|
||||
)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single log.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Log does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_log!(123)
|
||||
%Log{}
|
||||
|
||||
iex> get_log!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_log!(id) do
|
||||
Repo.one!(
|
||||
from l in Log, left_join: u in assoc(l, :user), where: l.id == ^id, preload: [user: u]
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a log entry.
|
||||
|
||||
This is a simple wrapper over a low-level insert. You likely want to use
|
||||
`log_action/3` and `log_resource_action/5` instead.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_log(%{action: "user.login"})
|
||||
{:ok, %Log{}}
|
||||
|
||||
iex> create_log(%{action: nil})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_log(attrs \\ %{}) do
|
||||
%Log{}
|
||||
|> Log.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
end
|
||||
45
lib/claper/audit/log.ex
Normal file
45
lib/claper/audit/log.ex
Normal file
@@ -0,0 +1,45 @@
|
||||
defmodule Claper.Audit.Log do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@derive {
|
||||
Flop.Schema,
|
||||
max_limit: 100,
|
||||
filterable: [:action, :user_email],
|
||||
sortable: [:inserted_at, :action],
|
||||
default_order: %{
|
||||
order_by: [:inserted_at],
|
||||
order_directions: [:desc]
|
||||
},
|
||||
adapter_opts: [
|
||||
join_fields: [
|
||||
user_email: [
|
||||
binding: :user,
|
||||
field: :email,
|
||||
path: [:user, :email]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
schema "audit_logs" do
|
||||
field :action, :string
|
||||
field :resource_type, :string
|
||||
field :resource_id, :integer
|
||||
field :metadata, :map, default: %{}
|
||||
|
||||
belongs_to :user, Claper.Accounts.User
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(log, attrs) do
|
||||
log
|
||||
|> cast(attrs, [:action, :resource_type, :resource_id, :metadata, :user_id])
|
||||
|> validate_required([:action])
|
||||
|> validate_length(:action, max: 255)
|
||||
|> validate_length(:resource_type, max: 255)
|
||||
|> assoc_constraint(:user)
|
||||
end
|
||||
end
|
||||
498
lib/claper_web/components/core_components.ex
Normal file
498
lib/claper_web/components/core_components.ex
Normal file
@@ -0,0 +1,498 @@
|
||||
defmodule ClaperWeb.CoreComponents do
|
||||
@moduledoc """
|
||||
Provides core UI components.
|
||||
|
||||
At first glance, this module may seem daunting, but its goal is to provide
|
||||
core building blocks for your application, such as tables, forms, and
|
||||
inputs. The components consist mostly of markup and are well-documented
|
||||
with doc strings and declarative assigns. You may customize and style
|
||||
them in any way you want, based on your application growth and needs.
|
||||
|
||||
The foundation for styling is Tailwind CSS, a utility-first CSS framework,
|
||||
augmented with daisyUI, a Tailwind CSS plugin that provides UI components
|
||||
and themes. Here are useful references:
|
||||
|
||||
* [daisyUI](https://daisyui.com/docs/intro/) - a good place to get
|
||||
started and see the available components.
|
||||
|
||||
* [Tailwind CSS](https://tailwindcss.com) - the foundational framework
|
||||
we build on. You will use it for layout, sizing, flexbox, grid, and
|
||||
spacing.
|
||||
|
||||
* [Heroicons](https://heroicons.com) - see `icon/1` for usage.
|
||||
|
||||
* [Phoenix.Component](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html) -
|
||||
the component system used by Phoenix. Some components, such as `<.link>`
|
||||
and `<.form>`, are defined there.
|
||||
|
||||
"""
|
||||
use Phoenix.Component
|
||||
use Gettext, backend: ClaperWeb.Gettext
|
||||
|
||||
alias Phoenix.LiveView.JS
|
||||
|
||||
@doc """
|
||||
Renders flash notices.
|
||||
|
||||
## Examples
|
||||
|
||||
<.flash kind={:info} flash={@flash} />
|
||||
<.flash kind={:info} phx-mounted={show("#flash")}>Welcome Back!</.flash>
|
||||
"""
|
||||
attr :id, :string, doc: "the optional id of flash container"
|
||||
attr :flash, :map, default: %{}, doc: "the map of flash messages to display"
|
||||
attr :title, :string, default: nil
|
||||
attr :kind, :atom, values: [:info, :error], doc: "used for styling and flash lookup"
|
||||
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
|
||||
|
||||
slot :inner_block, doc: "the optional inner block that renders the flash message"
|
||||
|
||||
def flash(assigns) do
|
||||
assigns = assign_new(assigns, :id, fn -> "flash-#{assigns.kind}" end)
|
||||
|
||||
~H"""
|
||||
<div
|
||||
:if={msg = render_slot(@inner_block) || Phoenix.Flash.get(@flash, @kind)}
|
||||
id={@id}
|
||||
phx-click={JS.push("lv:clear-flash", value: %{key: @kind}) |> hide("##{@id}")}
|
||||
role="alert"
|
||||
class="toast toast-top toast-end z-50"
|
||||
{@rest}
|
||||
>
|
||||
<div class={[
|
||||
"alert w-80 sm:w-96 max-w-80 sm:max-w-96 text-wrap",
|
||||
@kind == :info && "alert-info",
|
||||
@kind == :error && "alert-error"
|
||||
]}>
|
||||
<.icon :if={@kind == :info} name="hero-information-circle" class="size-5 shrink-0" />
|
||||
<.icon :if={@kind == :error} name="hero-exclamation-circle" class="size-5 shrink-0" />
|
||||
<div>
|
||||
<p :if={@title} class="font-semibold">{@title}</p>
|
||||
<p>{msg}</p>
|
||||
</div>
|
||||
<div class="flex-1" />
|
||||
<button type="button" class="group self-start cursor-pointer" aria-label={gettext("close")}>
|
||||
<.icon name="hero-x-mark" class="size-5 opacity-40 group-hover:opacity-70" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a button with navigation support.
|
||||
|
||||
## Examples
|
||||
|
||||
<.button>Send!</.button>
|
||||
<.button phx-click="go" variant="primary">Send!</.button>
|
||||
<.button navigate={~p"/"}>Home</.button>
|
||||
"""
|
||||
attr :rest, :global, include: ~w(href navigate patch method download name value disabled)
|
||||
attr :class, :any
|
||||
attr :variant, :string, values: ~w(primary)
|
||||
slot :inner_block, required: true
|
||||
|
||||
def button(%{rest: rest} = assigns) do
|
||||
variants = %{"primary" => "btn-primary", nil => "btn-primary btn-soft"}
|
||||
|
||||
assigns =
|
||||
assign_new(assigns, :class, fn ->
|
||||
["btn", Map.fetch!(variants, assigns[:variant])]
|
||||
end)
|
||||
|
||||
if rest[:href] || rest[:navigate] || rest[:patch] do
|
||||
~H"""
|
||||
<.link class={@class} {@rest}>
|
||||
{render_slot(@inner_block)}
|
||||
</.link>
|
||||
"""
|
||||
else
|
||||
~H"""
|
||||
<button class={@class} {@rest}>
|
||||
{render_slot(@inner_block)}
|
||||
</button>
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders an input with label and error messages.
|
||||
|
||||
A `Phoenix.HTML.FormField` may be passed as argument,
|
||||
which is used to retrieve the input name, id, and values.
|
||||
Otherwise all attributes may be passed explicitly.
|
||||
|
||||
## Types
|
||||
|
||||
This function accepts all HTML input types, considering that:
|
||||
|
||||
* You may also set `type="select"` to render a `<select>` tag
|
||||
|
||||
* `type="checkbox"` is used exclusively to render boolean values
|
||||
|
||||
* For live file uploads, see `Phoenix.Component.live_file_input/1`
|
||||
|
||||
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
|
||||
for more information. Unsupported types, such as radio, are best
|
||||
written directly in your templates.
|
||||
|
||||
## Examples
|
||||
|
||||
```heex
|
||||
<.input field={@form[:email]} type="email" />
|
||||
<.input name="my-input" errors={["oh no!"]} />
|
||||
```
|
||||
|
||||
## Select type
|
||||
|
||||
When using `type="select"`, you must pass the `options` and optionally
|
||||
a `value` to mark which option should be preselected.
|
||||
|
||||
```heex
|
||||
<.input field={@form[:user_type]} type="select" options={["Admin": "admin", "User": "user"]} />
|
||||
```
|
||||
|
||||
For more information on what kind of data can be passed to `options` see
|
||||
[`options_for_select`](https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#options_for_select/2).
|
||||
"""
|
||||
attr :id, :any, default: nil
|
||||
attr :name, :any
|
||||
attr :label, :string, default: nil
|
||||
attr :value, :any
|
||||
|
||||
attr :type, :string,
|
||||
default: "text",
|
||||
values: ~w(checkbox color date datetime-local email file month number password
|
||||
search select tel text textarea time url week hidden)
|
||||
|
||||
attr :field, Phoenix.HTML.FormField,
|
||||
doc: "a form field struct retrieved from the form, for example: @form[:email]"
|
||||
|
||||
attr :errors, :list, default: []
|
||||
attr :checked, :boolean, doc: "the checked flag for checkbox inputs"
|
||||
attr :prompt, :string, default: nil, doc: "the prompt for select inputs"
|
||||
attr :options, :list, doc: "the options to pass to Phoenix.HTML.Form.options_for_select/2"
|
||||
attr :multiple, :boolean, default: false, doc: "the multiple flag for select inputs"
|
||||
attr :class, :any, default: nil, doc: "the input class to use over defaults"
|
||||
attr :error_class, :any, default: nil, doc: "the input error class to use over defaults"
|
||||
|
||||
attr :rest, :global,
|
||||
include: ~w(accept autocomplete capture cols disabled form list max maxlength min minlength
|
||||
multiple pattern placeholder readonly required rows size step)
|
||||
|
||||
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
||||
errors = if Phoenix.Component.used_input?(field), do: field.errors, else: []
|
||||
|
||||
assigns
|
||||
|> assign(field: nil, id: assigns.id || field.id)
|
||||
|> assign(:errors, Enum.map(errors, &translate_error(&1)))
|
||||
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|
||||
|> assign_new(:value, fn -> field.value end)
|
||||
|> input()
|
||||
end
|
||||
|
||||
def input(%{type: "hidden"} = assigns) do
|
||||
~H"""
|
||||
<input type="hidden" id={@id} name={@name} value={@value} {@rest} />
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "checkbox"} = assigns) do
|
||||
assigns =
|
||||
assign_new(assigns, :checked, fn ->
|
||||
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
|
||||
end)
|
||||
|
||||
~H"""
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
type="hidden"
|
||||
name={@name}
|
||||
value="false"
|
||||
disabled={@rest[:disabled]}
|
||||
form={@rest[:form]}
|
||||
/>
|
||||
<span class="label">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={@id}
|
||||
name={@name}
|
||||
value="true"
|
||||
checked={@checked}
|
||||
class={@class || "checkbox checkbox-sm"}
|
||||
{@rest}
|
||||
/>{@label}
|
||||
</span>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "select"} = assigns) do
|
||||
~H"""
|
||||
<div>
|
||||
<label>
|
||||
<span :if={@label} class="label mb-1">{@label}</span>
|
||||
<select
|
||||
id={@id}
|
||||
name={@name}
|
||||
class={[@class || "w-full select", @errors != [] && (@error_class || "select-error")]}
|
||||
multiple={@multiple}
|
||||
{@rest}
|
||||
>
|
||||
<option :if={@prompt} value="">{@prompt}</option>
|
||||
{Phoenix.HTML.Form.options_for_select(@options, @value)}
|
||||
</select>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def input(%{type: "textarea"} = assigns) do
|
||||
~H"""
|
||||
<div>
|
||||
<label>
|
||||
<span :if={@label} class="label mb-1">{@label}</span>
|
||||
<textarea
|
||||
id={@id}
|
||||
name={@name}
|
||||
class={[
|
||||
@class || "w-full textarea",
|
||||
@errors != [] && (@error_class || "textarea-error")
|
||||
]}
|
||||
{@rest}
|
||||
>{Phoenix.HTML.Form.normalize_value("textarea", @value)}</textarea>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
# All other inputs text, datetime-local, url, password, etc. are handled here...
|
||||
def input(assigns) do
|
||||
~H"""
|
||||
<div>
|
||||
<label>
|
||||
<span :if={@label} class="label mb-1">{@label}</span>
|
||||
<input
|
||||
type={@type}
|
||||
name={@name}
|
||||
id={@id}
|
||||
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
||||
class={[
|
||||
@class || "w-full input",
|
||||
@errors != [] && (@error_class || "input-error")
|
||||
]}
|
||||
{@rest}
|
||||
/>
|
||||
</label>
|
||||
<.error :for={msg <- @errors}>{msg}</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
# Helper used by inputs to generate form errors
|
||||
defp error(assigns) do
|
||||
~H"""
|
||||
<p class="mt-1.5 flex gap-2 items-center text-sm text-error">
|
||||
<.icon name="hero-exclamation-circle" class="size-5" />
|
||||
{render_slot(@inner_block)}
|
||||
</p>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a header with title.
|
||||
"""
|
||||
slot :inner_block, required: true
|
||||
slot :subtitle
|
||||
slot :actions
|
||||
|
||||
def header(assigns) do
|
||||
~H"""
|
||||
<header class={[@actions != [] && "flex items-center justify-between gap-6", "pb-4"]}>
|
||||
<div>
|
||||
<h1 class="text-lg font-semibold leading-8">
|
||||
{render_slot(@inner_block)}
|
||||
</h1>
|
||||
<p :if={@subtitle != []} class="text-sm text-base-content/70">
|
||||
{render_slot(@subtitle)}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex-none">{render_slot(@actions)}</div>
|
||||
</header>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a table with generic styling.
|
||||
|
||||
## Examples
|
||||
|
||||
<.table id="users" rows={@users}>
|
||||
<:col :let={user} label="id">{user.id}</:col>
|
||||
<:col :let={user} label="username">{user.username}</:col>
|
||||
</.table>
|
||||
"""
|
||||
attr :id, :string, required: true
|
||||
attr :rows, :list, required: true
|
||||
attr :row_id, :any, default: nil, doc: "the function for generating the row id"
|
||||
attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row"
|
||||
|
||||
attr :row_item, :any,
|
||||
default: &Function.identity/1,
|
||||
doc: "the function for mapping each row before calling the :col and :action slots"
|
||||
|
||||
slot :col, required: true do
|
||||
attr :label, :string
|
||||
end
|
||||
|
||||
slot :action, doc: "the slot for showing user actions in the last table column"
|
||||
|
||||
def table(assigns) do
|
||||
assigns =
|
||||
with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do
|
||||
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
|
||||
end
|
||||
|
||||
~H"""
|
||||
<table class="table table-zebra">
|
||||
<thead>
|
||||
<tr>
|
||||
<th :for={col <- @col}>{col[:label]}</th>
|
||||
<th :if={@action != []}>
|
||||
<span class="sr-only">{gettext("Actions")}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id={@id} phx-update={is_struct(@rows, Phoenix.LiveView.LiveStream) && "stream"}>
|
||||
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
|
||||
<td
|
||||
:for={col <- @col}
|
||||
phx-click={@row_click && @row_click.(row)}
|
||||
class={@row_click && "hover:cursor-pointer"}
|
||||
>
|
||||
{render_slot(col, @row_item.(row))}
|
||||
</td>
|
||||
<td :if={@action != []} class="w-0 font-semibold">
|
||||
<div class="flex gap-4">
|
||||
<%= for action <- @action do %>
|
||||
{render_slot(action, @row_item.(row))}
|
||||
<% end %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a data list.
|
||||
|
||||
## Examples
|
||||
|
||||
<.list>
|
||||
<:item title="Title">{@post.title}</:item>
|
||||
<:item title="Views">{@post.views}</:item>
|
||||
</.list>
|
||||
"""
|
||||
slot :item, required: true do
|
||||
attr :title, :string, required: true
|
||||
end
|
||||
|
||||
def list(assigns) do
|
||||
~H"""
|
||||
<ul class="list">
|
||||
<li :for={item <- @item} class="list-row">
|
||||
<div class="list-col-grow">
|
||||
<div class="font-bold">{item.title}</div>
|
||||
<div>{render_slot(item)}</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a [Heroicon](https://heroicons.com).
|
||||
|
||||
Heroicons come in three styles – outline, solid, and mini.
|
||||
By default, the outline style is used, but solid and mini may
|
||||
be applied by using the `-solid` and `-mini` suffix.
|
||||
|
||||
You can customize the size and colors of the icons by setting
|
||||
width, height, and background color classes.
|
||||
|
||||
Icons are extracted from the `deps/heroicons` directory and bundled within
|
||||
your compiled app.css by the plugin in `assets/vendor/heroicons.js`.
|
||||
|
||||
## Examples
|
||||
|
||||
<.icon name="hero-x-mark" />
|
||||
<.icon name="hero-arrow-path" class="ml-1 size-3 motion-safe:animate-spin" />
|
||||
"""
|
||||
attr :name, :string, required: true
|
||||
attr :class, :any, default: "size-4"
|
||||
|
||||
def icon(%{name: "hero-" <> _} = assigns) do
|
||||
~H"""
|
||||
<span class={[@name, @class]} />
|
||||
"""
|
||||
end
|
||||
|
||||
## JS Commands
|
||||
|
||||
def show(js \\ %JS{}, selector) do
|
||||
JS.show(js,
|
||||
to: selector,
|
||||
time: 300,
|
||||
transition:
|
||||
{"transition-all ease-out duration-300",
|
||||
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95",
|
||||
"opacity-100 translate-y-0 sm:scale-100"}
|
||||
)
|
||||
end
|
||||
|
||||
def hide(js \\ %JS{}, selector) do
|
||||
JS.hide(js,
|
||||
to: selector,
|
||||
time: 200,
|
||||
transition:
|
||||
{"transition-all ease-in duration-200", "opacity-100 translate-y-0 sm:scale-100",
|
||||
"opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"}
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Translates an error message using gettext.
|
||||
"""
|
||||
def translate_error({msg, opts}) do
|
||||
# When using gettext, we typically pass the strings we want
|
||||
# to translate as a static argument:
|
||||
#
|
||||
# # Translate the number of files with plural rules
|
||||
# dngettext("errors", "1 file", "%{count} files", count)
|
||||
#
|
||||
# However the error messages in our forms and APIs are generated
|
||||
# dynamically, so we need to translate them by calling Gettext
|
||||
# with our gettext backend as first argument. Translations are
|
||||
# available in the errors.po file (as we use the "errors" domain).
|
||||
if count = opts[:count] do
|
||||
Gettext.dngettext(ClaperWeb.Gettext, "errors", msg, msg, count, opts)
|
||||
else
|
||||
Gettext.dgettext(ClaperWeb.Gettext, "errors", msg, opts)
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Translates the errors for a field from a keyword list of errors.
|
||||
"""
|
||||
def translate_errors(errors, field) when is_list(errors) do
|
||||
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
|
||||
end
|
||||
end
|
||||
57
lib/claper_web/components/icons.ex
Normal file
57
lib/claper_web/components/icons.ex
Normal file
@@ -0,0 +1,57 @@
|
||||
defmodule ClaperWeb.Icons do
|
||||
use Phoenix.Component
|
||||
|
||||
def eye(assigns) do
|
||||
~H"""
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
class="w-5 h-5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"
|
||||
/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
"""
|
||||
end
|
||||
|
||||
def arrow_up(assigns) do
|
||||
~H"""
|
||||
<svg
|
||||
class="ml-2 h-5 w-5 text-gray-500 group-hover:text-gray-700 inline"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L6.707 7.707a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
"""
|
||||
end
|
||||
|
||||
def arrow_down(assigns) do
|
||||
~H"""
|
||||
<svg
|
||||
class="ml-2 h-5 w-5 text-gray-500 group-hover:text-gray-700 inline"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M14.707 12.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 14.586V3a1 1 0 012 0v11.586l2.293-2.293a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
"""
|
||||
end
|
||||
end
|
||||
@@ -4,10 +4,13 @@ defmodule ClaperWeb.UserAuth do
|
||||
"""
|
||||
use ClaperWeb, :controller
|
||||
|
||||
require Logger
|
||||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
import ClaperWeb.Helpers.ConnUtils, only: [get_client_ip: 1, get_user_agent: 1]
|
||||
|
||||
alias Claper.Accounts
|
||||
alias Claper.{Accounts, Audit}
|
||||
|
||||
# Make the remember me cookie valid for 60 days.
|
||||
# If you want bump or reduce this value, also change
|
||||
@@ -32,6 +35,11 @@ defmodule ClaperWeb.UserAuth do
|
||||
token = Accounts.generate_user_session_token(user)
|
||||
user_return_to = get_session(conn, :user_return_to)
|
||||
|
||||
async_log_action(user, "user.login", %{
|
||||
ip_address: get_client_ip(conn),
|
||||
user_agent: get_user_agent(conn)
|
||||
})
|
||||
|
||||
conn
|
||||
|> renew_session()
|
||||
|> put_session(:user_token, token)
|
||||
@@ -83,6 +91,11 @@ defmodule ClaperWeb.UserAuth do
|
||||
ClaperWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
|
||||
end
|
||||
|
||||
async_log_action(conn.assigns[:current_user], "user.logout", %{
|
||||
ip_address: get_client_ip(conn),
|
||||
user_agent: get_user_agent(conn)
|
||||
})
|
||||
|
||||
conn
|
||||
|> renew_session()
|
||||
|> delete_resp_cookie(@remember_me_cookie)
|
||||
@@ -161,4 +174,14 @@ defmodule ClaperWeb.UserAuth do
|
||||
defp maybe_store_return_to(conn), do: conn
|
||||
|
||||
defp signed_in_path(_conn), do: "/events"
|
||||
|
||||
defp async_log_action(user, action, metadata) do
|
||||
Task.Supervisor.start_child(Claper.TaskSupervisor, fn ->
|
||||
with {:error, reason} <- Audit.log_action(user, action, metadata) do
|
||||
Logger.error(
|
||||
"Error creating #{inspect(action)} audit log for user #{inspect(get_in(user.email))}: #{inspect(reason)}"
|
||||
)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,6 +60,10 @@ defmodule ClaperWeb.Endpoint do
|
||||
|
||||
plug(:runtime_session)
|
||||
|
||||
plug RemoteIp,
|
||||
proxies: {Application, :get_env, [:claper, :remote_ip_proxies, []]},
|
||||
headers: {Application, :get_env, [:claper, :remote_ip_headers, []]}
|
||||
|
||||
plug ClaperWeb.Router
|
||||
|
||||
def runtime_session(conn, _opts) do
|
||||
|
||||
31
lib/claper_web/helpers/conn_utils.ex
Normal file
31
lib/claper_web/helpers/conn_utils.ex
Normal file
@@ -0,0 +1,31 @@
|
||||
defmodule ClaperWeb.Helpers.ConnUtils do
|
||||
@moduledoc """
|
||||
Utility functions for extracting information from Plug.Conn.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Extracts the client IP address from the connection.
|
||||
|
||||
The `RemoteIp` plug (configured in the endpoint) resolves the real client IP
|
||||
by inspecting the headers defined in `REMOTE_IP_HEADERS` and trusting only
|
||||
the proxies listed in `REMOTE_IP_PROXIES`, then rewrites `conn.remote_ip`
|
||||
before this is called.
|
||||
"""
|
||||
def get_client_ip(conn) do
|
||||
conn.remote_ip |> :inet.ntoa() |> to_string()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Extracts the user agent string from the connection.
|
||||
|
||||
Returns `nil` if no user agent header is present.
|
||||
"""
|
||||
def get_user_agent(conn) do
|
||||
user_agent = Plug.Conn.get_req_header(conn, "user-agent")
|
||||
|
||||
case user_agent do
|
||||
[ua | _] -> ua
|
||||
[] -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
74
lib/claper_web/live/admin_live/audit_log_live.ex
Normal file
74
lib/claper_web/live/admin_live/audit_log_live.ex
Normal file
@@ -0,0 +1,74 @@
|
||||
defmodule ClaperWeb.AdminLive.AuditLogLive do
|
||||
use ClaperWeb, :live_view
|
||||
|
||||
alias Claper.Audit
|
||||
|
||||
@impl Phoenix.LiveView
|
||||
def mount(_params, session, socket) do
|
||||
with %{"locale" => locale} <- session do
|
||||
Gettext.put_locale(ClaperWeb.Gettext, locale)
|
||||
end
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
|
||||
@impl Phoenix.LiveView
|
||||
def handle_params(params, _url, socket) do
|
||||
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
|
||||
end
|
||||
|
||||
defp apply_action(socket, :index, params) do
|
||||
{logs, meta} = Audit.list_logs(params)
|
||||
|
||||
socket
|
||||
|> assign(:page_title, gettext("Audit Logs"))
|
||||
|> assign(:logs, logs)
|
||||
|> assign(:meta, meta)
|
||||
|> assign(:form, Phoenix.Component.to_form(meta))
|
||||
|> assign_new(:action_types, &Audit.list_action_types/0)
|
||||
|> assign_new(:fields, fn %{action_types: action_types} ->
|
||||
[
|
||||
user_email: [
|
||||
label: nil,
|
||||
placeholder: gettext("Search by user email"),
|
||||
type: "text",
|
||||
op: :ilike_or
|
||||
],
|
||||
action: [
|
||||
label: nil,
|
||||
prompt: gettext("All actions"),
|
||||
field: :action,
|
||||
type: "select",
|
||||
options: action_types
|
||||
]
|
||||
]
|
||||
end)
|
||||
end
|
||||
|
||||
defp apply_action(socket, :show, %{"id" => id}) do
|
||||
socket
|
||||
|> assign(:page_title, gettext("Audit Log Details"))
|
||||
|> assign(:log, Audit.get_log!(id))
|
||||
end
|
||||
|
||||
@impl Phoenix.LiveView
|
||||
def handle_event("filter-logs", unsigned_params, socket) do
|
||||
flop = Flop.validate!(unsigned_params, for: Audit.Log, replace_invalid_params: true)
|
||||
to = Flop.Phoenix.build_path(~p"/admin/audit_logs", flop)
|
||||
|
||||
{:noreply, push_patch(socket, to: to)}
|
||||
end
|
||||
|
||||
defp format_metadata(nil), do: "—"
|
||||
defp format_metadata(metadata) when map_size(metadata) == 0, do: "—"
|
||||
|
||||
defp format_metadata(metadata) do
|
||||
Enum.map_join(metadata, ", ", fn {k, v} -> "#{k}: #{v}" end)
|
||||
end
|
||||
|
||||
defp format_timestamp(%NaiveDateTime{} = timestamp) do
|
||||
Calendar.strftime(timestamp, "%Y-%m-%d %H:%M:%S\u00A0UTC")
|
||||
end
|
||||
|
||||
defp format_timestamp(timestamp), do: inspect(timestamp)
|
||||
end
|
||||
169
lib/claper_web/live/admin_live/audit_log_live.html.heex
Normal file
169
lib/claper_web/live/admin_live/audit_log_live.html.heex
Normal file
@@ -0,0 +1,169 @@
|
||||
<h1 class="text-3xl font-bold mb-24">{@page_title}</h1>
|
||||
|
||||
<%= if @live_action == :index do %>
|
||||
<div class="flex flex-col sm:flex-row items-stretch gap-3 @container/controls">
|
||||
<.form
|
||||
for={@form}
|
||||
class="grow flex flex-col sm:flex-row gap-3 sm:[&>div]:basis-[250px]"
|
||||
phx-change="filter-logs"
|
||||
>
|
||||
<Flop.Phoenix.filter_fields :let={i} form={@form} fields={@fields}>
|
||||
<ClaperWeb.CoreComponents.input field={i.field} label={i.label} type={i.type} {i.rest} />
|
||||
</Flop.Phoenix.filter_fields>
|
||||
</.form>
|
||||
<Flop.Phoenix.pagination
|
||||
meta={@meta}
|
||||
path={~p"/admin/audit_logs"}
|
||||
class="flex [&>ul]:mr-3 justify-end"
|
||||
page_list_attrs={[class: "hidden @4xl/controls:flex"]}
|
||||
page_list_item_attrs={[
|
||||
class:
|
||||
"grid place-content-stretch min-h-10 min-w-10 border-t border-r border-b border-gray-300 first:border-l first:rounded-l-full last:rounded-r-full first:[&>*]:rounded-l-full last:[&>*]:rounded-r-full text-gray-500 bg-white [&>*]:grid [&>*]:place-content-center"
|
||||
]}
|
||||
page_link_attrs={[
|
||||
class: "hover:text-black hover:bg-gray-200"
|
||||
]}
|
||||
current_page_link_attrs={[
|
||||
class: "pointer-events-none font-bold text-black"
|
||||
]}
|
||||
>
|
||||
<:previous attrs={[
|
||||
class:
|
||||
"order-1 border border-gray-300 rounded-l-full h-10 p-5 bg-white flex items-center justify-center aria-disabled:text-gray-300 hover:not-aria-disabled:bg-gray-200"
|
||||
]}>
|
||||
{gettext("Previous")}
|
||||
</:previous>
|
||||
<:next attrs={[
|
||||
class:
|
||||
"order-2 border-t border-r border-b border-gray-300 rounded-r-full h-10 p-5 bg-white flex items-center justify-center aria-disabled:text-gray-300 hover:not-aria-disabled:bg-gray-200"
|
||||
]}>
|
||||
{gettext("Next")}
|
||||
</:next>
|
||||
<:ellipsis>
|
||||
<span aria-hidden="true" class="text-gray-300">•••</span>
|
||||
</:ellipsis>
|
||||
</Flop.Phoenix.pagination>
|
||||
</div>
|
||||
<Flop.Phoenix.table
|
||||
items={@logs}
|
||||
meta={@meta}
|
||||
path={~p"/admin/audit_logs"}
|
||||
opts={[
|
||||
container: true,
|
||||
container_attrs: [class: "card bg-base-100 shadow-xl overflow-x-auto my-5"],
|
||||
no_results_content: ~H"""
|
||||
<p class="text-center py-10">{gettext("No results.")}</p>
|
||||
""",
|
||||
table_attrs: [class: "table table-zebra w-full"],
|
||||
symbol_asc: ~H"""
|
||||
<span aria-hidden="true"><ClaperWeb.Icons.arrow_up /></span>
|
||||
""",
|
||||
symbol_desc: ~H"""
|
||||
<span aria-hidden="true"><ClaperWeb.Icons.arrow_down /></span>
|
||||
"""
|
||||
]}
|
||||
>
|
||||
<:col :let={log} label={gettext("ID")} field={:id}>{log.id}</:col>
|
||||
<:col :let={log} label={gettext("Action")} field={:action}>
|
||||
<span class="badge badge-outline">{log.action}</span>
|
||||
</:col>
|
||||
<:col :let={log} label={gettext("User")} field={:user_email}>
|
||||
{get_in(log.user.email) || "—"}
|
||||
</:col>
|
||||
<:col :let={log} label={gettext("Timestamp")} field={:inserted_at}>
|
||||
{format_timestamp(log.inserted_at)}
|
||||
</:col>
|
||||
<:col
|
||||
:let={log}
|
||||
label={gettext("Metadata")}
|
||||
field={:metadata}
|
||||
tbody_td_attrs={[class: "max-w-xs truncate text-sm text-base-content/70"]}
|
||||
>
|
||||
{format_metadata(log.metadata)}
|
||||
</:col>
|
||||
<:action :let={log} tbody_td_attrs={[class: "text-right"]}>
|
||||
<.link
|
||||
patch={~p"/admin/audit_logs/#{log}"}
|
||||
class="btn btn-link btn-sm"
|
||||
aria-label={gettext("View details for log #%{id}", id: log.id)}
|
||||
>
|
||||
<ClaperWeb.Icons.eye />
|
||||
</.link>
|
||||
</:action>
|
||||
</Flop.Phoenix.table>
|
||||
<% end %>
|
||||
|
||||
<%= if @live_action == :show do %>
|
||||
<dl class="card card-body bg-base-100 shadow-xl grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-5">
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("ID")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
{@log.id}
|
||||
</dd>
|
||||
</div>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("Action")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
<span class="badge badge-outline">{@log.action}</span>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("User")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
<%= if @log.user do %>
|
||||
<span class="space-x-2">
|
||||
<a href={"mailto:#{@log.user.email}"} class="link link-primary">{@log.user.email}</a>
|
||||
<.link
|
||||
navigate={~p"/admin/users/#{@log.user}"}
|
||||
class="link link-primary *:inline"
|
||||
aria-label={gettext("View profile for %{email}", email: @log.user.email)}
|
||||
>
|
||||
<ClaperWeb.Icons.eye />
|
||||
</.link>
|
||||
</span>
|
||||
<% else %>
|
||||
—
|
||||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("Timestamp")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
{format_timestamp(@log.inserted_at)}
|
||||
</dd>
|
||||
</div>
|
||||
<%= if @log.resource_type do %>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("Resource Type")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
{@log.resource_type}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if @log.resource_id do %>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("Resource ID")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
{@log.resource_id}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col-span-full grid grid-cols-subgrid gap-y-1 items-baseline">
|
||||
<dt class="font-medium sm:text-right">{gettext("Metadata")}</dt>
|
||||
<dd class="bg-base-200 p-3 rounded-lg inset-shadow-sm overflow-x-auto">
|
||||
<%= if @log.metadata && map_size(@log.metadata) > 0 do %>
|
||||
<dl class="space-y-2 min-w-min">
|
||||
<%= for {key, value} <- @log.metadata do %>
|
||||
<div class="ml-5 -indent-5">
|
||||
<dt class="inline font-medium">{key}:</dt>
|
||||
<dd class="inline">{value}</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
</dl>
|
||||
<% else %>
|
||||
—
|
||||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<% end %>
|
||||
@@ -198,6 +198,9 @@ defmodule ClaperWeb.Router do
|
||||
live "/oidc_providers/new", OidcProviderLive, :new
|
||||
live "/oidc_providers/:id/edit", OidcProviderLive, :edit
|
||||
live "/oidc_providers/:id", OidcProviderLive, :show
|
||||
|
||||
live "/audit_logs", AuditLogLive, :index
|
||||
live "/audit_logs/:id", AuditLogLive, :show
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="drawer lg:drawer-open">
|
||||
<input id="drawer-toggle" type="checkbox" class="drawer-toggle" />
|
||||
|
||||
<div class="drawer-content flex flex-col">
|
||||
<div class="drawer-content flex flex-col min-h-screen">
|
||||
<!-- Navbar for mobile -->
|
||||
<div class="navbar lg:hidden bg-base-100 shadow-lg">
|
||||
<div class="flex-none">
|
||||
@@ -230,6 +230,22 @@
|
||||
{gettext("Users")}
|
||||
</.link>
|
||||
</li>
|
||||
<li>
|
||||
<.link
|
||||
patch={~p"/admin/audit_logs"}
|
||||
class={"#{if @conn.path_info == ["admin", "audit_logs"], do: "active", else: ""}"}
|
||||
>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
{gettext("Audit Logs")}
|
||||
</.link>
|
||||
</li>
|
||||
<%!-- <li>
|
||||
<.link
|
||||
patch={~p"/admin/oidc_providers"}
|
||||
|
||||
3
mix.exs
3
mix.exs
@@ -115,6 +115,9 @@ defmodule Claper.MixProject do
|
||||
{:oidcc, "~> 3.5"},
|
||||
{:oban, "~> 2.19"},
|
||||
{:hammer, "~> 7.0"},
|
||||
{:flop, "~> 0.26"},
|
||||
{:flop_phoenix, "~> 0.25"},
|
||||
{:remote_ip, "~> 1.2"},
|
||||
{:tailwind, "~> 0.3", runtime: Mix.env() == :dev}
|
||||
]
|
||||
end
|
||||
|
||||
4
mix.lock
4
mix.lock
@@ -2,6 +2,7 @@
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
|
||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
"castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
|
||||
"cowboy": {:hex, :cowboy, "2.13.0", "09d770dd5f6a22cc60c071f432cd7cb87776164527f205c5a6b0f24ff6b38990", [:make, :rebar3], [{:cowlib, ">= 2.14.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e724d3a70995025d654c1992c7b11dbfea95205c047d86ff9bf1cda92ddc5614"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
@@ -23,6 +24,8 @@
|
||||
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
|
||||
"finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"},
|
||||
"floki": {:hex, :floki, "0.38.0", "62b642386fa3f2f90713f6e231da0fa3256e41ef1089f83b6ceac7a3fd3abf33", [:mix], [], "hexpm", "a5943ee91e93fb2d635b612caf5508e36d37548e84928463ef9dd986f0d1abd9"},
|
||||
"flop": {:hex, :flop, "0.26.3", "9bc700b34f96a57e56aaa89b850926356311372556eacd5a1abe0fdd0ea40bf2", [:mix], [{:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}], "hexpm", "cd77588229778ac55560c90dfbe15ab6486773f067d6e52db9fa703b8c9a9d2d"},
|
||||
"flop_phoenix": {:hex, :flop_phoenix, "0.25.3", "a623649f6cd00ce3be1eac8dbd6d4fadf47a3212c7d2fc4701f6f2f90f347549", [:mix], [{:flop, ">= 0.23.0 and < 0.27.0", [hex: :flop, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.6.0 and < 1.9.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0.6 or ~> 1.1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "912fae3c343dde43c5ea4f642275793d9dbef32989bf200013e12b85adb93b9c"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "1.3.0", "62c3d91f0dcf6ce9db71bcb6881d7ad0d1d834c7f38c13fa8e952f4104a8442e", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "0b73fbf069864ecbce02fe653b16d3f35fd889d0fdd4e14527675565c39d84e6"},
|
||||
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
|
||||
"hammer": {:hex, :hammer, "7.2.0", "73113eca87f0fd20a6d3679c1182e8c4c1778266f61de4e9dc8c589dee156c30", [:mix], [], "hexpm", "c50fa865ddfe7b3d4f8a6941f56940679e02a9a1465b00668a95d140b101d828"},
|
||||
@@ -60,6 +63,7 @@
|
||||
"porcelain": {:hex, :porcelain, "2.0.3", "2d77b17d1f21fed875b8c5ecba72a01533db2013bd2e5e62c6d286c029150fdc", [:mix], [], "hexpm", "dc996ab8fadbc09912c787c7ab8673065e50ea1a6245177b0c24569013d23620"},
|
||||
"postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"},
|
||||
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
|
||||
"remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"},
|
||||
"req": {:hex, :req, "0.5.14", "521b449fa0bf275e6d034c05f29bec21789a0d6cd6f7a1c326c7bee642bf6e07", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b7b15692071d556c73432c7797aa7e96b51d1a2db76f746b976edef95c930021"},
|
||||
"sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"},
|
||||
"swoosh": {:hex, :swoosh, "1.19.3", "02ad4455939f502386e4e1443d4de94c514995fd0e51b3cafffd6bd270ffe81c", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "04a10f8496786b744b84130e3510eb53ca51e769c39511b65023bdf4136b732f"},
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Einstellungen"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -476,9 +476,9 @@ msgstr "Interaktion hinzufügen"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Wenn Sie diesen Benutzer sperren, werden alle seine Nachrichten gelöscht, und er kann nicht mehr beitreten. Bestätigen?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Sie wurden von dieser Veranstaltung ausgeschlossen"
|
||||
@@ -705,7 +705,7 @@ msgstr "Formulareinsendungen der Teilnehmer werden hier angezeigt."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
@@ -1068,6 +1068,7 @@ msgstr "Hier finden Sie alle Interaktionen Ihrer Teilnehmer. Sie können Nachric
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identifizieren Sie Benutzer anhand ihrer einzigartigen Avatare."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1194,7 +1195,7 @@ msgstr "Wählen Sie Ihre Präsentation aus (optional)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Dieser Code wird von Ihren Teilnehmern verwendet, um auf die Veranstaltung zuzugreifen. Sie haben die Möglichkeit, einen benutzerdefinierten Code zu erstellen."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Diese Veranstaltung wurde beendet"
|
||||
@@ -1216,7 +1217,7 @@ msgstr "Erstellen Sie Ihre nächste Präsentation mit"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "Veranstaltung existiert nicht"
|
||||
@@ -1272,7 +1273,7 @@ msgid "Event manager"
|
||||
msgstr "Veranstaltungsmanager"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Dokumentation"
|
||||
@@ -1475,6 +1476,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Bitte geben Sie einen gültigen Link ein, der mit http:// oder https:// beginnt"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Bitte geben Sie gültigen HTML-Inhalt mit einem iframe-Tag ein"
|
||||
@@ -1564,12 +1566,12 @@ msgstr "Beenden"
|
||||
msgid "More options"
|
||||
msgstr "Weitere Optionen"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "Nein"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@@ -1718,6 +1720,7 @@ msgstr "Neues Quiz"
|
||||
msgid "Presentation"
|
||||
msgstr "Präsentation"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1932,6 +1935,7 @@ msgstr "Ein eindeutiger Name zur Identifikation dieses OIDC-Anbieters"
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr "Konto ist bestätigt und aktiv"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2639,7 +2643,7 @@ msgstr "Anbieter"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr "Zurück zur App"
|
||||
@@ -2679,3 +2683,84 @@ msgstr "Erforderlich"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(optional)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Aktion"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Alle Aktionen"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Details zum Überwachungsprotokoll"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Überwachungsprotokolle"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metadaten"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Keine Ergebnisse."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "Ressourcen-ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Ressourcentyp"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Suche nach Benutzer-E-Mail"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Zeitstempel"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "schließen"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Details für Protokoll Nr. %{id} anzeigen"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Profil für %{email} anzeigen"
|
||||
|
||||
@@ -20,7 +20,7 @@ msgstr ""
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -478,9 +478,9 @@ msgstr ""
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr ""
|
||||
@@ -707,7 +707,7 @@ msgstr ""
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
@@ -1070,6 +1070,7 @@ msgstr ""
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1196,7 +1197,7 @@ msgstr ""
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr ""
|
||||
@@ -1218,7 +1219,7 @@ msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr ""
|
||||
@@ -1274,7 +1275,7 @@ msgid "Event manager"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr ""
|
||||
@@ -1477,6 +1478,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr ""
|
||||
@@ -1566,12 +1568,12 @@ msgstr ""
|
||||
msgid "More options"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
@@ -1720,6 +1722,7 @@ msgstr ""
|
||||
msgid "Presentation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1934,6 +1937,7 @@ msgstr ""
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2641,7 +2645,7 @@ msgstr ""
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr ""
|
||||
@@ -2681,3 +2685,84 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All actions"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr ""
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -476,9 +476,9 @@ msgstr ""
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr ""
|
||||
@@ -705,7 +705,7 @@ msgstr ""
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
@@ -1068,6 +1068,7 @@ msgstr ""
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1194,7 +1195,7 @@ msgstr ""
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr ""
|
||||
@@ -1216,7 +1217,7 @@ msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr ""
|
||||
@@ -1272,7 +1273,7 @@ msgid "Event manager"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr ""
|
||||
@@ -1475,6 +1476,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr ""
|
||||
@@ -1564,12 +1566,12 @@ msgstr ""
|
||||
msgid "More options"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
@@ -1718,6 +1720,7 @@ msgstr ""
|
||||
msgid "Presentation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1932,6 +1935,7 @@ msgstr ""
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2639,7 +2643,7 @@ msgstr ""
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr ""
|
||||
@@ -2679,3 +2683,84 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr ""
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Configuración"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -476,9 +476,9 @@ msgstr "Añadir interacción"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Bloquear este usuario borrará todos sus mensajes y él no será capaz de unirse de nuevo, ¿estás seguro?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Has sido excluido/a de este evento"
|
||||
@@ -705,7 +705,7 @@ msgstr "Los envíos de formulario de los asistentes aparecerán aquí."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
@@ -1068,6 +1068,7 @@ msgstr "Aquí encontrarás todas las interacciones de tus asistentes. Puedes ges
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identificar usuarios por sus avatares únicos."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1194,7 +1195,7 @@ msgstr "Selecciona tu presentación (opcional)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Este código será usado por tus asistentes para acceder al evento. Tienes la opción de crear un código personalizado."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Este evento ha sido terminado"
|
||||
@@ -1216,7 +1217,7 @@ msgstr "Crea tu siguiente presentación con"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "El evento no existe"
|
||||
@@ -1272,7 +1273,7 @@ msgid "Event manager"
|
||||
msgstr "Gestor de evento"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Documentación"
|
||||
@@ -1475,6 +1476,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Por favor, introduce un enlace válido que comience con http:// o https://"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Por favor, introduce contenido HTML válido con una etiqueta iframe"
|
||||
@@ -1564,12 +1566,12 @@ msgstr "Finalizar"
|
||||
msgid "More options"
|
||||
msgstr "Más opciones"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Sí"
|
||||
@@ -1718,6 +1720,7 @@ msgstr "Nuevo cuestionario"
|
||||
msgid "Presentation"
|
||||
msgstr "Presentación"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1932,6 +1935,7 @@ msgstr "Un nombre único para identificar este proveedor OIDC"
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr "La cuenta está confirmada y activa"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2639,7 +2643,7 @@ msgstr "Proveedor"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr "Volver a la aplicación"
|
||||
@@ -2679,3 +2683,84 @@ msgstr "Obligatorio"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(opcional)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Todas las acciones"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Detalles del registro de auditoría"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Registros de auditoría"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metadatos"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Sin resultados."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "ID del recurso"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Tipo de recurso"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Buscar por email de usuario"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Fecha y hora"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Usuario"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "cerrar"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Ver detalles del registro nº %{id}"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Ver perfil de %{email}"
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Paramètres"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -477,9 +477,9 @@ msgstr "Ajouter une interaction"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Bloquer cet utilisateur supprimera tous ses messages et il ne pourra pas rejoindre à nouveau, confirmer ?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Vous avez été banni de cet événement"
|
||||
@@ -709,7 +709,7 @@ msgstr "Les formulaires soumis par les participants apparaîtront ici."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
@@ -1072,6 +1072,7 @@ msgstr "Ici, vous trouverez toutes les interactions de vos participants. Vous po
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identifiez les utilisateurs par leurs avatars uniques."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1198,7 +1199,7 @@ msgstr "Sélectionnez votre présentation (facultatif)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Ce code sera utilisé par vos participants pour accéder à l'événement. Vous avez la possibilité de créer un code personnalisé."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Cet événement viens d'être terminé"
|
||||
@@ -1220,7 +1221,7 @@ msgstr "Créez votre prochaine présentation avec"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "L'événement n'existe pas"
|
||||
@@ -1276,7 +1277,7 @@ msgid "Event manager"
|
||||
msgstr "Gestionnaire d'événement"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Documentation"
|
||||
@@ -1479,6 +1480,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Veuillez entrer un lien valide commençant par http:// ou https://"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Veuillez entrer un contenu HTML valide avec une balise iframe"
|
||||
@@ -1568,12 +1570,12 @@ msgstr "Terminer"
|
||||
msgid "More options"
|
||||
msgstr "Plus d'options"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "Non"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Oui"
|
||||
@@ -1722,6 +1724,7 @@ msgstr "Nouveau quiz"
|
||||
msgid "Presentation"
|
||||
msgstr "Présentation"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1936,6 +1939,7 @@ msgstr "Un nom unique pour identifier ce fournisseur OIDC"
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr "Le compte est confirmé et actif"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2643,7 +2647,7 @@ msgstr "Détails du fournisseur"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr "Retour à l'app"
|
||||
@@ -2683,3 +2687,84 @@ msgstr "Obligatoire"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(facultatif)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Action"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Toutes les actions"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Détails du journal d'audit"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Journaux d'audit"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Métadonnées"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Aucun résultat."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "ID de ressource"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Type de ressource"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Recherche par e-mail de l'utilisateur"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Horodatage"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Utilisateur"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "fermer"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Afficher les détails du journal nº %{id}"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Voir le profil pour %{email}"
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Beállítások"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -476,9 +476,9 @@ msgstr "Interakció hozzáadása"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Ezen felhasználó blokkolásával az üzenetei törlődnek, és nem fog tudni újra csatlakozni. Biztos benne?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Ki van tiltva erről az eseményről"
|
||||
@@ -705,7 +705,7 @@ msgstr "A résztvevők által beküldött űrlapok itt fognak megjelenni."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Név"
|
||||
@@ -1068,6 +1068,7 @@ msgstr "Itt találhatóak majd a résztvevők interakciói. Lehetőség van az
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Azonosítsa a felhasználókat egyedi profilképeik alapján."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1194,7 +1195,7 @@ msgstr "Válassza ki a prezentációt (opcionális)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "A résztvevők ezt a kódot fogják használni a csatlakozáshoz. Lehetőség van egyéni kódot is létrehozni."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Az esemény befejeződött"
|
||||
@@ -1216,7 +1217,7 @@ msgstr "Hozza létre következő prezentációját ezzel:"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "Az esemény nem található"
|
||||
@@ -1272,7 +1273,7 @@ msgid "Event manager"
|
||||
msgstr "Eseménykezelő"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Dokumentáció"
|
||||
@@ -1475,6 +1476,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Adjon meg egy http:// vagy https:// előtaggal kezdődő érvényes linket"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Adjon meg érvényes HTML tartalmat iframe taggel"
|
||||
@@ -1564,12 +1566,12 @@ msgstr "Befejezés"
|
||||
msgid "More options"
|
||||
msgstr "További lehetőségek"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "Nem"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Igen"
|
||||
@@ -1718,6 +1720,7 @@ msgstr "Új kvíz"
|
||||
msgid "Presentation"
|
||||
msgstr "Prezentáció"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1932,6 +1935,7 @@ msgstr ""
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2639,10 +2643,10 @@ msgstr "Szolgáltató"
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr ""
|
||||
msgstr "Vissza az alkalmazáshoz"
|
||||
|
||||
#: lib/claper_web/templates/user_notifier/change.html.heex:17
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
@@ -2679,3 +2683,84 @@ msgstr "Kötelező"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(opcionális)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Művelet"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Összes művelet"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Auditnapló részletei"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Auditnaplók"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "Azonosító"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metaadatok"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Nincsenek találatok."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "Erőforrás-azonosító"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Erőforrás típusa"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Keresés e-mail cím alapján"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Időbélyeg"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Felhasználó"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "bezárás"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Az %{id}. napló részleteinek megtekintése"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Az %{email} profil megtekintése"
|
||||
|
||||
@@ -19,7 +19,7 @@ msgstr "Impostazioni"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -477,9 +477,9 @@ msgstr "Aggiungi interazione"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Bloccando questo utente verranno eliminati tutti i suoi messaggi e non potrà più iscriversi, confermi?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Sei stato bandito da questo evento"
|
||||
@@ -706,7 +706,7 @@ msgstr "I moduli compilati dai partecipanti appariranno qui."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
@@ -1069,6 +1069,7 @@ msgstr "Qui troverai tutte le interazioni dei tuoi partecipanti. Puoi gestire me
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identifica gli utenti tramite i loro avatar unici."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1195,7 +1196,7 @@ msgstr "Seleziona la tua presentazione (facoltativo)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Questo codice verrà utilizzato dai tuoi partecipanti per accedere all'evento. Hai la possibilità di creare un codice personalizzato."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Questo evento è stato terminato"
|
||||
@@ -1217,7 +1218,7 @@ msgstr "Crea la tua prossima presentazione con"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "L'evento non esiste"
|
||||
@@ -1273,7 +1274,7 @@ msgid "Event manager"
|
||||
msgstr "Responsabile eventi"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Documentazione"
|
||||
@@ -1476,6 +1477,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Inserisci un collegamento valido che inizia con http:// o https://"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Inserisci un contenuto HTML valido con un tag iframe"
|
||||
@@ -1565,12 +1567,12 @@ msgstr "Fine"
|
||||
msgid "More options"
|
||||
msgstr "Altre opzioni"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Sì"
|
||||
@@ -1719,6 +1721,7 @@ msgstr "Nuovo quiz"
|
||||
msgid "Presentation"
|
||||
msgstr "Presentazione"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1933,6 +1936,7 @@ msgstr "Un nome unico per identificare questo provider OIDC"
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr "L'account è confermato e attivo"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2640,7 +2644,7 @@ msgstr "Dettagli provider"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr "Torna all'app"
|
||||
@@ -2680,3 +2684,84 @@ msgstr "Obbligatorio"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(facoltativo)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Azione"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Tutte le azioni"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Dettagli del registro di controllo"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Registri di controllo"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metadati"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Nessun risultato."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "ID risorsa"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Tipo di risorsa"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Timestamp"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Utente"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "chiudi"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Visualizza i dettagli per il registro n. %{id}"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Visualizza ir profilo per %{email}"
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Iestatījumi"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -477,9 +477,9 @@ msgstr "Pievienot mijiedarbību"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Bloķējot šo lietotāju, tiks dzēsti visi lietotāja ziņojumi un viņš vairs nevarēs pievienoties, apstipriniet?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Jums ir aizliegts piedalīties šajā pasākumā"
|
||||
@@ -709,7 +709,7 @@ msgstr "Dalībnieku iesniegtās veidlapas parādīsies šeit."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Nosaukums"
|
||||
@@ -1072,6 +1072,7 @@ msgstr "Šeit atradīsiet visas dalībnieku mijiedarbības. Varat pārvaldīt zi
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identificēt lietotājus pēc viņu unikālajiem avatariem."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1198,7 +1199,7 @@ msgstr "Izvēlieties savu prezentāciju (pēc izvēles)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Šo kodu dalībnieki izmantos, lai piekļūtu pasākumam. Jums ir iespēja izveidot pielāgotu kodu."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Šis notikums ir pārtraukts"
|
||||
@@ -1220,7 +1221,7 @@ msgstr "Izveidojiet nākamo prezentāciju, izmantojot"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "Notikums neeksistē"
|
||||
@@ -1276,7 +1277,7 @@ msgid "Event manager"
|
||||
msgstr "Pasākumu vadītājs"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Dokumentācija"
|
||||
@@ -1479,6 +1480,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Lūdzu, ievadiet derīgu saiti, kas sākas ar http:// vai https://"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Lūdzu, ievadiet derīgu HTML saturu ar iframe tagu"
|
||||
@@ -1568,12 +1570,12 @@ msgstr "Izbeigt"
|
||||
msgid "More options"
|
||||
msgstr "Vairāk iespēju"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "Nē"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Jā"
|
||||
@@ -1722,6 +1724,7 @@ msgstr "Jauna viktorīna"
|
||||
msgid "Presentation"
|
||||
msgstr "Prezentācija"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1936,6 +1939,7 @@ msgstr ""
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2643,10 +2647,10 @@ msgstr "Nodrošinātājs"
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr ""
|
||||
msgstr "Atpakaļ uz lietotni"
|
||||
|
||||
#: lib/claper_web/templates/user_notifier/change.html.heex:17
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
@@ -2683,3 +2687,84 @@ msgstr "Obligāti aizpildāms"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(pēc izvēles)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Darbība"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Visas darbības"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Audita žurnāla informācija"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Audita žurnāli"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metadati"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Nav rezultātu."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "Resursa ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Resursa veids"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Meklēt pēc e-pasta"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Laika zīmogs"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Lietotājs"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "aizvērt"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Skatīt žurnāla Nr. %{id} informāciju"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Skatīt profilu %{email}"
|
||||
|
||||
@@ -18,7 +18,7 @@ msgstr "Instellingen"
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/user_live/form_component.ex:18
|
||||
#: lib/claper_web/live/event_live/manage.ex:838
|
||||
#: lib/claper_web/live/event_live/manage.ex:844
|
||||
#: lib/claper_web/live/form_live/form_component.html.heex:32
|
||||
#: lib/claper_web/live/user_settings_live/show.html.heex:34
|
||||
#: lib/claper_web/templates/user_registration/new.html.heex:29
|
||||
@@ -476,9 +476,9 @@ msgstr "Voeg interactie toe"
|
||||
msgid "Blocking this user will delete all his messages and he will not be able to join again, confirm ?"
|
||||
msgstr "Als je deze gebruiker blokkeert, worden al zijn berichten verwijderd en kan hij niet meer deelnemen. Bevestigen ?"
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:51
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#: lib/claper_web/live/event_live/show.ex:221
|
||||
#: lib/claper_web/live/event_live/show.ex:64
|
||||
#: lib/claper_web/live/event_live/show.ex:219
|
||||
#: lib/claper_web/live/event_live/show.ex:234
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have been banned from this event"
|
||||
msgstr "Je bent uitgesloten van dit evenement"
|
||||
@@ -705,7 +705,7 @@ msgstr "Formulierinzendingen van deelnemers worden hier weergegeven."
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:74
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:254
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live/form_component.ex:24
|
||||
#: lib/claper_web/live/event_live/manage.ex:837
|
||||
#: lib/claper_web/live/event_live/manage.ex:843
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Name"
|
||||
msgstr "Naam"
|
||||
@@ -1068,6 +1068,7 @@ msgstr "Hier vind je alle interacties van je bezoekers. Je kunt berichten, vastg
|
||||
msgid "Identify users by their unique avatars."
|
||||
msgstr "Identificeer gebruikers aan de hand van hun unieke avatars."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:40
|
||||
#: lib/claper_web/live/event_live/event_form_component.html.heex:5
|
||||
#: lib/claper_web/live/event_live/index.html.heex:106
|
||||
#: lib/claper_web/live/event_live/manage.html.heex:427
|
||||
@@ -1194,7 +1195,7 @@ msgstr "Selecteer de presentatie (optioneel)"
|
||||
msgid "This code will be used by your attendees to access the event. You have the option to create a custom code."
|
||||
msgstr "Deze code wordt door je bezoekers gebruikt om toegang te krijgen tot het evenement. Je hebt de mogelijkheid om een aangepaste code aan te maken."
|
||||
|
||||
#: lib/claper_web/live/event_live/show.ex:193
|
||||
#: lib/claper_web/live/event_live/show.ex:206
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This event has been terminated"
|
||||
msgstr "Dit evenement is gestopt"
|
||||
@@ -1216,7 +1217,7 @@ msgstr "Maak je volgende presentatie met"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:23
|
||||
#: lib/claper_web/live/event_live/presenter.ex:26
|
||||
#: lib/claper_web/live/event_live/show.ex:25
|
||||
#: lib/claper_web/live/event_live/show.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Event doesn't exist"
|
||||
msgstr "Evenement bestaat niet"
|
||||
@@ -1272,7 +1273,7 @@ msgid "Event manager"
|
||||
msgstr "Evenementmanager"
|
||||
|
||||
#: lib/claper_web/templates/layout/_user_menu.html.heex:19
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:262
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Documentation"
|
||||
msgstr "Documentatie"
|
||||
@@ -1475,6 +1476,7 @@ msgid "Please enter a valid link starting with http:// or https://"
|
||||
msgstr "Voer een geldige link in die begint met http:// of https://"
|
||||
|
||||
#: lib/claper/embeds/embed.ex:98
|
||||
#: lib/claper/embeds/embed.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please enter valid HTML content with an iframe tag"
|
||||
msgstr "Voer geldige HTML-inhoud in met een iframe-tag"
|
||||
@@ -1564,12 +1566,12 @@ msgstr "Beëindigen"
|
||||
msgid "More options"
|
||||
msgstr "Meer opties"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No"
|
||||
msgstr "Nee"
|
||||
|
||||
#: lib/claper_web/live/event_live/manage.ex:818
|
||||
#: lib/claper_web/live/event_live/manage.ex:824
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Yes"
|
||||
msgstr "Ja"
|
||||
@@ -1718,6 +1720,7 @@ msgstr "Nieuwe quiz"
|
||||
msgid "Presentation"
|
||||
msgstr "Presentatie"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:34
|
||||
#: lib/claper_web/live/event_live/manager_settings_component.ex:168
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Previous"
|
||||
@@ -1932,6 +1935,7 @@ msgstr "Een unieke naam om deze OIDC-aanbieder te identificeren"
|
||||
msgid "Account is confirmed and active"
|
||||
msgstr "Account is bevestigd en actief"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:368
|
||||
#: lib/claper_web/live/admin_live/event_live.html.heex:126
|
||||
#: lib/claper_web/live/admin_live/oidc_provider_live.html.heex:108
|
||||
#: lib/claper_web/live/admin_live/user_live.html.heex:111
|
||||
@@ -2639,7 +2643,7 @@ msgstr "Aanbieder details"
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:285
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to app"
|
||||
msgstr "Terug naar app"
|
||||
@@ -2679,3 +2683,84 @@ msgstr "Verplicht"
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "(optional)"
|
||||
msgstr "(optioneel)"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:67
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:105
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action"
|
||||
msgstr "Actie"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:39
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "All actions"
|
||||
msgstr "Alle acties"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:50
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Log Details"
|
||||
msgstr "Details auditlogboek"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:24
|
||||
#: lib/claper_web/templates/layout/admin.html.heex:246
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Audit Logs"
|
||||
msgstr "Auditlogboeken"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:66
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:78
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:152
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Metadata"
|
||||
msgstr "Metadata"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No results."
|
||||
msgstr "Geen resultaten."
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:145
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource ID"
|
||||
msgstr "Resource-ID"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:137
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Resource Type"
|
||||
msgstr "Resourcetype"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.ex:33
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search by user email"
|
||||
msgstr "Zoeken op e-mail"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:73
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Timestamp"
|
||||
msgstr "Tijdstempel"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:70
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:111
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "User"
|
||||
msgstr "Gebruiker"
|
||||
|
||||
#: lib/claper_web/components/core_components.ex:74
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "close"
|
||||
msgstr "sluiten"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View details for log #%{id}"
|
||||
msgstr "Bekijk details voor logboek #%{id}"
|
||||
|
||||
#: lib/claper_web/live/admin_live/audit_log_live.html.heex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View profile for %{email}"
|
||||
msgstr "Bekijk profiel voor %{email}"
|
||||
|
||||
19
priv/repo/migrations/20260129165937_create_audit_logs.exs
Normal file
19
priv/repo/migrations/20260129165937_create_audit_logs.exs
Normal file
@@ -0,0 +1,19 @@
|
||||
defmodule Claper.Repo.Migrations.CreateAuditLogs do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:audit_logs) do
|
||||
add :action, :string, null: false
|
||||
add :resource_type, :string
|
||||
add :resource_id, :bigint
|
||||
add :metadata, :map, default: %{}
|
||||
add :user_id, references(:users, on_delete: :nilify_all)
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
create index(:audit_logs, [:inserted_at])
|
||||
create index(:audit_logs, [:action, :inserted_at])
|
||||
create index(:audit_logs, [:user_id, :inserted_at])
|
||||
end
|
||||
end
|
||||
89
test/claper/audit_test.exs
Normal file
89
test/claper/audit_test.exs
Normal file
@@ -0,0 +1,89 @@
|
||||
defmodule Claper.AuditTest do
|
||||
use Claper.DataCase
|
||||
|
||||
alias Claper.Audit
|
||||
|
||||
describe "audit_logs" do
|
||||
alias Claper.Audit.Log
|
||||
|
||||
import Claper.AuditFixtures
|
||||
import Claper.AccountsFixtures
|
||||
|
||||
@invalid_attrs %{action: nil}
|
||||
|
||||
test "list_logs/0 paginates all audit_logs" do
|
||||
log = log_fixture()
|
||||
{logs, _meta} = Audit.list_logs()
|
||||
assert Enum.any?(logs, fn l -> l.id == log.id end)
|
||||
end
|
||||
|
||||
test "get_log!/1 returns the log with given id" do
|
||||
log = log_fixture()
|
||||
fetched_log = Audit.get_log!(log.id)
|
||||
assert fetched_log.id == log.id
|
||||
assert fetched_log.action == log.action
|
||||
end
|
||||
|
||||
test "create_log/1 with valid data creates a log" do
|
||||
valid_attrs = %{
|
||||
metadata: %{},
|
||||
action: "some action",
|
||||
resource_type: "some resource_type",
|
||||
resource_id: 42
|
||||
}
|
||||
|
||||
assert {:ok, %Log{} = log} = Audit.create_log(valid_attrs)
|
||||
assert log.metadata == %{}
|
||||
assert log.action == "some action"
|
||||
assert log.resource_type == "some resource_type"
|
||||
assert log.resource_id == 42
|
||||
end
|
||||
|
||||
test "create_log/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Audit.create_log(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "log_action/3 creates a log for a user" do
|
||||
user = user_fixture()
|
||||
metadata = %{ip_address: "127.0.0.1"}
|
||||
|
||||
assert {:ok, %Log{} = log} = Audit.log_action(user, "user.login", metadata)
|
||||
assert log.user_id == user.id
|
||||
assert log.action == "user.login"
|
||||
assert log.metadata == metadata
|
||||
end
|
||||
|
||||
test "log_action/3 creates a log without a user" do
|
||||
metadata = %{reason: "system startup"}
|
||||
|
||||
assert {:ok, %Log{} = log} = Audit.log_action(nil, "system.startup", metadata)
|
||||
assert log.user_id == nil
|
||||
assert log.action == "system.startup"
|
||||
assert log.metadata == metadata
|
||||
end
|
||||
|
||||
test "log_resource_action/5 creates a log with resource info" do
|
||||
user = user_fixture()
|
||||
metadata = %{}
|
||||
|
||||
assert {:ok, %Log{} = log} =
|
||||
Audit.log_resource_action(user, "event.create", "event", 123, metadata)
|
||||
|
||||
assert log.user_id == user.id
|
||||
assert log.action == "event.create"
|
||||
assert log.resource_type == "event"
|
||||
assert log.resource_id == 123
|
||||
end
|
||||
|
||||
test "list_action_types/0 returns distinct action types" do
|
||||
log_fixture(%{action: "user.login"})
|
||||
log_fixture(%{action: "user.login"})
|
||||
log_fixture(%{action: "event.create"})
|
||||
|
||||
action_types = Audit.list_action_types()
|
||||
assert "user.login" in action_types
|
||||
assert "event.create" in action_types
|
||||
assert length(action_types) == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
29
test/claper_web/helpers/conn_utils_test.exs
Normal file
29
test/claper_web/helpers/conn_utils_test.exs
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule ClaperWeb.Helpers.ConnUtilsTest do
|
||||
use ClaperWeb.ConnCase, async: true
|
||||
|
||||
alias ClaperWeb.Helpers.ConnUtils
|
||||
|
||||
describe "get_client_ip/1" do
|
||||
test "returns the remote_ip from the connection as a string" do
|
||||
conn = build_conn() |> Map.put(:remote_ip, {93, 184, 216, 34})
|
||||
assert ConnUtils.get_client_ip(conn) == "93.184.216.34"
|
||||
end
|
||||
|
||||
test "handles IPv6 addresses" do
|
||||
conn = build_conn() |> Map.put(:remote_ip, {8193, 3512, 0, 0, 0, 0, 0, 1})
|
||||
assert ConnUtils.get_client_ip(conn) == "2001:db8::1"
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_user_agent/1" do
|
||||
test "returns the user agent header when present" do
|
||||
conn = build_conn() |> put_req_header("user-agent", "Mozilla/5.0")
|
||||
assert ConnUtils.get_user_agent(conn) == "Mozilla/5.0"
|
||||
end
|
||||
|
||||
test "returns nil when no user agent header is present" do
|
||||
conn = build_conn()
|
||||
assert ConnUtils.get_user_agent(conn) == nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -36,10 +36,29 @@ defmodule ClaperWeb.ConnCase do
|
||||
|
||||
setup tags do
|
||||
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Claper.Repo, shared: not tags[:async])
|
||||
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
|
||||
|
||||
on_exit(fn ->
|
||||
drain_task_supervisor(Claper.TaskSupervisor)
|
||||
Ecto.Adapters.SQL.Sandbox.stop_owner(pid)
|
||||
end)
|
||||
|
||||
{:ok, conn: Phoenix.ConnTest.build_conn()}
|
||||
end
|
||||
|
||||
defp drain_task_supervisor(supervisor) do
|
||||
supervisor
|
||||
|> Task.Supervisor.children()
|
||||
|> Enum.each(fn pid ->
|
||||
ref = Process.monitor(pid)
|
||||
|
||||
receive do
|
||||
{:DOWN, ^ref, :process, ^pid, _} -> :ok
|
||||
after
|
||||
1_000 -> Process.demonitor(ref, [:flush])
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Setup helper that registers and logs in users.
|
||||
|
||||
|
||||
@@ -32,12 +32,30 @@ defmodule Claper.DataCase do
|
||||
# Don't check out a connection if a setup_all did so already
|
||||
if context[:sandbox_owner_pid] == nil do
|
||||
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(Claper.Repo, shared: not context[:async])
|
||||
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
|
||||
|
||||
on_exit(fn ->
|
||||
drain_task_supervisor(Claper.TaskSupervisor)
|
||||
Ecto.Adapters.SQL.Sandbox.stop_owner(pid)
|
||||
end)
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
defp drain_task_supervisor(supervisor) do
|
||||
supervisor
|
||||
|> Task.Supervisor.children()
|
||||
|> Enum.each(fn pid ->
|
||||
ref = Process.monitor(pid)
|
||||
|
||||
receive do
|
||||
{:DOWN, ^ref, :process, ^pid, _} -> :ok
|
||||
after
|
||||
1_000 -> Process.demonitor(ref, [:flush])
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
A helper that transforms changeset errors into a map of messages.
|
||||
|
||||
|
||||
23
test/support/fixtures/audit_fixtures.ex
Normal file
23
test/support/fixtures/audit_fixtures.ex
Normal file
@@ -0,0 +1,23 @@
|
||||
defmodule Claper.AuditFixtures do
|
||||
@moduledoc """
|
||||
This module defines test helpers for creating
|
||||
entities via the `Claper.Audit` context.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Generate a log.
|
||||
"""
|
||||
def log_fixture(attrs \\ %{}) do
|
||||
{:ok, log} =
|
||||
attrs
|
||||
|> Enum.into(%{
|
||||
action: "some action",
|
||||
metadata: %{},
|
||||
resource_id: 42,
|
||||
resource_type: "some resource_type"
|
||||
})
|
||||
|> Claper.Audit.create_log()
|
||||
|
||||
log
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user