Skip to content

Conversation

@seanrcollings
Copy link
Contributor

@seanrcollings seanrcollings commented Jul 25, 2025

Enabled apps to declare a "custom resource" to expose in the admin UI.

Here's a simple one that I created to expose Atomic CAT's programs for an app instance:

Configuration

class ProgramsSchema < AtomicAdmin::Schema::ApplicationInstanceSchema
  def schema
    {
      type: "object",
      properties: {
        name: {
          type: "string",
          title: "Name",
          minLength: 1,
          maxLength: 255,
          description: "The name of the program.",
        },
      },
    }
  end

  def uischema
    {
      type: "VerticalLayout",
      elements: [
        {
          type: "Control",
          scope: "#/properties/name",
        },
      ],
    }
  end
end

AtomicAdmin.configure do |config|
  config.application_interactions.tap do |inter|
    inter.add(
      :programs,
      type: :resource,
      plural: :programs,
      singular: :program,
      title: "Programs",
      icon: "school",
      controller: "Api::Admin::ProgramsController",
      table: {
        columns: [
          { key: "name", label: "Name", searchable: true, sortable: true },
        ],
      },
      actions: [
        { type: :create, label: "Create Program", schema: ProgramsSchema },
        { type: :update, label: "Update Program", schema: ProgramsSchema },
        { type: :delete, label: "Delete Program" },
      ],
    )
  end 
end

Controller

The app then can implement a controller with the needed actions

class Api::Admin::ProgramsController < AtomicAdmin::V1::AdminController
  include AtomicAdmin::Filtering
  around_action :set_tenant

  allowed_sort_columns %w[name]
  allowed_search_columns %w[name]

  def index
    @programs, meta = filter(Program.all)

    render json: { programs: @programs.as_json, meta: }
  end

  def show
    @program = Program.find(params[:id])
    render json: { program: @program.as_json }
  end

  def create
    @program = Program.new(program_params)
    if @program.save
      render json: { program: @program.as_json }, status: :created
    else
      render json: { errors: @program.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def update
    @program = Program.find(params[:id])
    if @program.update(program_params)
      render json: { program: @program.as_json }
    else
      render json: { errors: @program.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def destroy
    @program = Program.find(params[:id])
    if @program.destroy
      render json: { message: "Program deleted successfully" }, status: :ok
    else
      render json: { errors: @program.errors.full_messages }, status: :unprocessable_entity
    end
  end

  private

  def set_tenant
    Tenant.switch(current_application_instance.tenant) do
      yield
    end
  end

  def current_application_instance
    @current_application_instance ||= ApplicationInstance.find(params[:application_instance_id])
  end

  def program_params
    params.require(:program).permit(:name)
  end
end

Result

Which ends up in the UI like this

image

controller_name = interaction.key.to_s.pluralize
resources controller_name do
collection do
get :interactions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants