aesmail / kaffy

Powerfully simple admin package for phoenix applications
https://kaffy.fly.dev/admin/
MIT License
1.34k stars 155 forks source link

[FEATURE-REQUEST] Allow to {:ok, conn} on `action` in any `resource_actions` to support redirect somewhere else #267

Open ryvasquez opened 1 year ago

ryvasquez commented 1 year ago

Describe the problem you're proposing to solve

So I have a action in resource_actions that requires redirect to some internal page after performing the action

def resource_actions(_conn) do
    [
      approve_move_to_next: %{
        name: "Approve product and redirect somewhere",
        action: fn conn, product ->
          Product.approve(product)
          redirect(conn, to: somewhere_internal_url)
        end,
      },
    ]
  end

However action only accepts {:ok, record} | {:error, changeset} | {:error, record, custom_error} as a return value, and if you modify with the conn it will successfully redirect but raise an error something like

09:06:30.980 [error] Ranch listener SkyeWeb.Endpoint.HTTPS had connection process started with :cowboy_tls:start_link/4 at #PID<0.1179.0> exit with reason: {{:badmatch, :undefined}, [{:cow_http2_machine, :prepare_headers, 5, [file: '/Users/ryvasquez/Documents/apps/sample_app/deps/cowlib/src/cow_http2_machine.erl', line: 1119]}, {:cowboy_http2, :send_response, 5, [file: '/Users/ryvasquez/Documents/apps/sample_app/deps/cowboy/src/cowboy_http2.erl', line: 790]}, {:cowboy_http2, :commands, 3, [file: '/Users/ryvasquez/Documents/apps/sample_app/deps/cowboy/src/cowboy_http2.erl', line: 664]}, {:cowboy_http2, :loop, 2, [file: '/Users/ryvasquez/Documents/apps/sample_app/deps/cowboy/src/cowboy_http2.erl', line: 277]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}]}

Describe the solution you'd like

Maybe we can pattern match a Plug.Conn in this part https://github.com/aesmail/kaffy/blob/c0b16cafe085638e198c7a4ad3e3afe0c31a2076/lib/kaffy_web/controllers/resource_controller.ex#L326-L337

and return as is since it was a conn.

Let me know if this is a valid solution, Im happy to work on it 👍

Describe alternatives you've considered

Additional context Add any other context or screenshots about the feature request here.

KalleJoP commented 11 months ago

This could also be helpful for download actions. In my case I want to generate a qr code and sent it as an download to the user.

  def resource_actions(_conn) do
    [
      generate_qr_code: %{name: "Generate QR Code", action: fn c, p -> generate_qr_code(c, p) end}
    ]
  end
  defp generate_qr_code(conn, product) do
    filename = "qr-product_id-#{product.id}.png"
    filepath = "/tmp/#{filename}"

    unverified_url(conn, "/admin/inventory/physical_product_variant/#{product.id}")
    |> QRCode.create(:high)
    |> QRCode.render(:png)
    |> QRCode.save(filepath)

    conn
    |> put_resp_header(
      "content-disposition",
      ~s(attachment; filename="#{filename}")
    )
    |> send_download({:file, filepath})
  end
ryvasquez commented 10 months ago

@aesmail any feedback on the request? 🙂 apologies for constantly pinging 🙇‍♂️