PhoenixKit.Annotations (phoenix_kit v1.7.115)

Copy Markdown View Source

Context for phoenix_kit_annotations — drawn-on-image shapes created via the Etcher overlay layer in the MediaBrowser modal.

Most callers won't use this directly — they go through PhoenixKit.Modules.Storage.EtcherAdapter which implements the Etcher.Storage behaviour and dispatches to this context. The module is exposed so admin tooling, audits, or background workers can do CRUD without reaching for the adapter.

Summary

Functions

Create an annotation for a file.

Delete an annotation by UUID.

Fetch a single annotation by UUID, or nil.

List annotations for a file, ordered by position then insertion time.

List annotations for a file together with a tooltip-friendly preview of their comment thread. Each element is a map

Update an annotation's geometry / style / metadata / position.

Types

attrs()

@type attrs() :: map()

uuid()

@type uuid() :: String.t()

Functions

create(attrs)

@spec create(attrs()) ::
  {:ok, PhoenixKit.Annotations.Annotation.t()} | {:error, Ecto.Changeset.t()}

Create an annotation for a file.

attrs accepts both atom- and string-keyed maps (the latter is what flows in from LiveView events). Keys: :file_uuid, :kind, :geometry, optional :creator_uuid, :style, :metadata, :position.

delete(uuid)

@spec delete(uuid()) :: :ok | {:error, :not_found | Ecto.Changeset.t()}

Delete an annotation by UUID.

Cascades to any linked comments — i.e. comments on the annotation's file that carry metadata.annotation_uuid pointing at this row. The cascade is a hard delete: annotation comments are conceptually owned by their annotation, so they go with it instead of lingering as [removed] placeholders in the file's thread. phoenix_kit_comment_media rows fall away via their ON DELETE CASCADE; the underlying media files (referenced via comment_media.file_uuid) stay untouched — they're library assets, not comment-owned. No-ops cleanly when PhoenixKitComments isn't installed.

get(uuid)

@spec get(uuid()) :: PhoenixKit.Annotations.Annotation.t() | nil

Fetch a single annotation by UUID, or nil.

list_for_file(file_uuid)

@spec list_for_file(uuid()) :: [PhoenixKit.Annotations.Annotation.t()]

List annotations for a file, ordered by position then insertion time.

list_for_file_with_previews(file_uuid)

@spec list_for_file_with_previews(uuid()) :: [map()]

List annotations for a file together with a tooltip-friendly preview of their comment thread. Each element is a map:

%{
  annotation: %Annotation{},
  first_comment: %{content, author, thumbnail_url} | nil,
  comment_count: integer()
}

Annotation comments are stored against the file (resource_type: "file", resource_uuid: file_uuid) with metadata.annotation_uuid pointing at the annotation, so they show up in the file's main comments thread alongside non-annotated discussion. This loader pulls every file comment in one query and groups by that metadata key.

If the comments package isn't installed, returns the same shape with first_comment: nil and comment_count: 0 so callers always handle one schema.

update(uuid, attrs)

@spec update(uuid(), attrs()) ::
  {:ok, PhoenixKit.Annotations.Annotation.t()}
  | {:error, :not_found | Ecto.Changeset.t()}

Update an annotation's geometry / style / metadata / position.