MishkaGervaz.Table.Web.Live (MishkaGervaz v0.0.1-alpha.2)

Copy Markdown View Source

LiveComponent for MishkaGervaz admin tables.

This is a thin orchestrator that delegates to specialized modules:

  • State - State management
  • DataLoader - Async data loading with streams
  • Events - Event handling
  • Renderer - Template rendering

Usage

Minimal usage (all config from DSL):

<.live_component
  module={MishkaGervaz.Table.Web.Live}
  id="posts-table"
  resource={MyApp.Post}
  current_user={@current_user}
/>

That's it! Everything else comes from the DSL defined on your resource.

Required Assigns

  • id - Unique component ID
  • resource - Ash resource module with MishkaGervaz.Resource extension
  • current_user - Current user for authorization

Parent LiveView Integration

The component sends messages to the parent for certain actions:

def handle_info({:show_modal, id}, socket), do: ...
def handle_info({:edit_modal, id}, socket), do: ...
def handle_info({:show_versions, id}, socket), do: ...
def handle_info({:expand_row, id}, socket), do: ...
def handle_info({:row_action, event_name, payload}, socket), do: ...
def handle_info({:bulk_action, action_name, selected_ids}, socket), do: ...

PubSub Integration (Automatic)

The component automatically subscribes to PubSub topics when realtime is configured on the resource or domain. It uses prefix from the resource's realtime config and pubsub module from domain defaults.

The parent LiveView only needs to forward broadcast notifications to the component:

def handle_info(
      %Phoenix.Socket.Broadcast{topic: "site" <> _, payload: %Ash.Notifier.Notification{} = notification},
      socket
    ) do
  # Get component_id stored by the component during subscription
  if component_id = Process.get({:mishka_gervaz_component, "site"}) do
    send_update(MishkaGervaz.Table.Web.Live,
      id: component_id,
      pubsub_notification: notification
    )
  end
  {:noreply, socket}
end

Expanded Row Content

When a row is expanded via :raw_accordion action, send content back:

def handle_info({:expand_row, id}, socket) do
  # Load expanded content async
  html = render_expanded_content(id)
  send_update(MishkaGervaz.Table.Web.Live,
    id: "posts-table",
    expanded_html: html
  )
  {:noreply, socket}
end

Auto Refresh Integration

When refresh is enabled in the DSL, the component schedules a timer that sends :gervaz_refresh to the parent LiveView. The parent must handle this and forward it to the component:

def handle_info(:gervaz_refresh, socket) do
  # Forward to the table component
  send_update(MishkaGervaz.Table.Web.Live,
    id: "posts-table",
    gervaz_refresh: true
  )
  {:noreply, socket}
end

Configure refresh in DSL:

refresh do
  enabled true
  interval 30_000  # 30 seconds
end

See MishkaGervaz.Table.Web.State, MishkaGervaz.Table.Web.DataLoader, MishkaGervaz.Table.Web.Events, MishkaGervaz.Table.Web.Renderer, MishkaGervaz.Table.Web.Refresh, MishkaGervaz.Table.Web.UrlSync, MishkaGervaz.Resource.Info.Table.