Packages

phoenix_kit

1.7.178
1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

221 Versions

Jump to

Compare versions

16 files changed
+484 additions
-50 deletions
unknownCHANGELOG.md
File is too large to be displayed (100 KB limit).
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/BeamLabEU/phoenix_kit">>}]}.
2 2 {<<"name">>,<<"phoenix_kit">>}.
3 - {<<"version">>,<<"1.7.177">>}.
3 + {<<"version">>,<<"1.7.178">>}.
4 4 {<<"description">>,
5 5 <<65,32,102,111,117,110,100,97,116,105,111,110,32,102,111,114,32,98,117,105,
6 6 108,100,105,110,103,32,69,108,105,120,105,114,32,80,104,111,101,110,105,
  @@ -350,6 +350,7 @@
350 350 <<"lib/phoenix_kit/integrations/events.ex">>,
351 351 <<"lib/phoenix_kit/integrations/providers.ex">>,
352 352 <<"lib/phoenix_kit/integrations/integrations.ex">>,
353 + <<"lib/phoenix_kit/integrations/resource_links.ex">>,
353 354 <<"lib/phoenix_kit/integrations/encryption.ex">>,
354 355 <<"lib/phoenix_kit/integrations/oauth.ex">>,
355 356 <<"lib/phoenix_kit/supervisor.ex">>,<<"lib/phoenix_kit/audit_log.ex">>,
  @@ -1270,12 +1270,23 @@ defmodule PhoenixKit.Integrations do
1270 1270 defp log_activity(action, provider, name, metadata, mode, actor_uuid)
1271 1271 when is_binary(provider) and is_binary(name) do
1272 1272 if Code.ensure_loaded?(PhoenixKit.Activity) do
1273 + # Stamp the storage row's uuid so the activity deep-links to the
1274 + # connection's edit page (via PhoenixKit.Integrations.ResourceLinks).
1275 + # nil when the row can't be resolved (e.g. a disconnect that removed it) —
1276 + # the feed still renders, just without a link.
1277 + resource_uuid =
1278 + case find_uuid_by_provider_name({provider, name}) do
1279 + {:ok, uuid} -> uuid
1280 + _ -> nil
1281 + end
1282 +
1273 1283 PhoenixKit.Activity.log(%{
1274 1284 action: action,
1275 1285 module: "integrations",
1276 1286 mode: mode,
1277 1287 actor_uuid: actor_uuid,
1278 1288 resource_type: "integration",
1289 + resource_uuid: resource_uuid,
1279 1290 metadata:
1280 1291 Map.merge(metadata, %{
1281 1292 "provider" => provider,
  @@ -0,0 +1,58 @@
1 + defmodule PhoenixKit.Integrations.ResourceLinks do
2 + @moduledoc """
3 + Resolves `"integration"` resources to their edit page for deep-linking.
4 +
5 + An activity logged against an integration (`resource_type: "integration"`,
6 + `resource_uuid:` the storage row's uuid) resolves to the connection's edit
7 + page (`/admin/settings/integrations/:uuid`), titled `provider / name`.
8 +
9 + Registered as the `"integration"` handler by `PhoenixKit.ResourceLinks`
10 + (gated on this module being loaded). Mirrors
11 + `PhoenixKit.Users.CommentResources` — implements the same
12 + `resolve_comment_resources/1` contract and returns a **raw** phoenix_kit path
13 + (`Routes.path/1` is applied once at render).
14 + """
15 +
16 + alias PhoenixKit.Integrations
17 +
18 + @spec resolve_comment_resources([binary()]) :: %{binary() => map()}
19 + def resolve_comment_resources(resource_uuids) when is_list(resource_uuids) do
20 + resource_uuids
21 + |> Enum.uniq()
22 + |> Enum.reduce(%{}, fn uuid, acc ->
23 + case info_for(uuid) do
24 + nil -> acc
25 + info -> Map.put(acc, uuid, info)
26 + end
27 + end)
28 + rescue
29 + _ -> %{}
30 + end
31 +
32 + # Raw path — the caller applies Routes.path/1 (prefix + locale) at render.
33 + # The title lookup is best-effort: a transient settings error falls back to a
34 + # generic label rather than dropping the (still-valid) deep-link.
35 + defp info_for(uuid) when is_binary(uuid) and uuid != "" do
36 + %{title: title_for(uuid), path: "/admin/settings/integrations/#{uuid}"}
37 + end
38 +
39 + defp info_for(_), do: nil
40 +
41 + defp title_for(uuid) do
42 + case Integrations.get_integration_by_uuid(uuid) do
43 + {:ok, %{provider: provider, name: name}} -> connection_title(provider, name)
44 + _ -> "Integration"
45 + end
46 + rescue
47 + _ -> "Integration"
48 + end
49 +
50 + defp connection_title(provider, name) do
51 + case {to_string(provider), to_string(name)} do
52 + {"", ""} -> "Integration"
53 + {p, ""} -> p
54 + {"", n} -> n
55 + {p, n} -> "#{p} / #{n}"
56 + end
57 + end
58 + end
  @@ -150,6 +150,43 @@ defmodule PhoenixKit.Module do
150 150 """
151 151 @callback notification_types() :: [map()]
152 152
153 + @doc """
154 + Declares how this module's resource types deep-link to their pages.
155 +
156 + Lets the activity feed, notifications, and the comments moderation admin turn
157 + a `(resource_type, resource_uuid)` pair from *this* module into a clickable
158 + link to the underlying record — with zero host configuration. Returns a map of
159 + `resource_type => resolver`, where a resolver is either:
160 +
161 + * **a module** implementing `resolve_comment_resources/1` (the same contract
162 + core's `"user"`/`"file"`/`"post"` handlers use) — for rich resolution with
163 + a title and optional thumbnail. Return `%{uuid => %{title:, path:}}` with a
164 + **raw** phoenix_kit path (`Routes.path/1` is applied once at render).
165 +
166 + * **a path-template string** — the no-code shortcut, e.g.
167 + `"/admin/widgets/:uuid"`. Placeholders: `:uuid` and `:metadata.<key>`
168 + (pulled from the activity/comment metadata). Treated as an internal
169 + phoenix_kit route (SPA-navigated, prefix/locale applied). Use the map form
170 + `%{"path" => "...", "title" => ":metadata.name"}` to set a display title.
171 +
172 + ## Examples
173 +
174 + # No-code: a raw admin route with a uuid segment
175 + def resource_links, do: %{"widget" => "/admin/widgets/:uuid"}
176 +
177 + # Titled template
178 + def resource_links,
179 + do: %{"widget" => %{"path" => "/admin/widgets/:uuid", "title" => ":metadata.name"}}
180 +
181 + # Rich: point at a resolver module (title + thumbnail via a DB lookup)
182 + def resource_links, do: %{"widget" => MyApp.WidgetLinks}
183 +
184 + Merges with core's built-in handlers and the host's `comment_resource_paths`
185 + setting via `PhoenixKit.ResourceLinks`. Modules with no linkable resources can
186 + skip this callback — the default is `%{}`.
187 + """
188 + @callback resource_links() :: %{optional(String.t()) => module() | String.t() | map()}
189 +
153 190 @doc """
154 191 Returns Tailwind CSS source roots for scanning.
155 192
  @@ -329,6 +366,7 @@ defmodule PhoenixKit.Module do
329 366 required_integrations: 0,
330 367 integration_providers: 0,
331 368 notification_types: 0,
369 + resource_links: 0,
332 370 css_sources: 0,
333 371 js_sources: 0,
334 372 sitemap_sources: 0,
  @@ -385,6 +423,9 @@ defmodule PhoenixKit.Module do
385 423 @impl PhoenixKit.Module
386 424 def notification_types, do: []
387 425
426 + @impl PhoenixKit.Module
427 + def resource_links, do: %{}
428 +
388 429 @impl PhoenixKit.Module
389 430 def css_sources, do: []
390 431
  @@ -413,6 +454,7 @@ defmodule PhoenixKit.Module do
413 454 required_integrations: 0,
414 455 integration_providers: 0,
415 456 notification_types: 0,
457 + resource_links: 0,
416 458 css_sources: 0,
417 459 js_sources: 0,
418 460 sitemap_sources: 0,
Loading more files…