From 8668de15018ba723e165658139d255f0b151e3b9 Mon Sep 17 00:00:00 2001 From: Sean Collings Date: Thu, 22 May 2025 12:50:27 -0600 Subject: [PATCH 1/2] feat: broke up interaction code into seperate classes --- config/routes.rb | 9 ++++ lib/atomic_admin/interaction.rb | 59 +++-------------------- lib/atomic_admin/interaction/analytics.rb | 13 +++++ lib/atomic_admin/interaction/base.rb | 27 +++++++++++ lib/atomic_admin/interaction/json_form.rb | 19 ++++++++ lib/atomic_admin/interaction/manager.rb | 59 +++++++++++++++++++++++ lib/atomic_admin/interaction/resource.rb | 15 ++++++ 7 files changed, 148 insertions(+), 53 deletions(-) create mode 100644 lib/atomic_admin/interaction/analytics.rb create mode 100644 lib/atomic_admin/interaction/base.rb create mode 100644 lib/atomic_admin/interaction/json_form.rb create mode 100644 lib/atomic_admin/interaction/manager.rb create mode 100644 lib/atomic_admin/interaction/resource.rb diff --git a/config/routes.rb b/config/routes.rb index 80764cc..a2b8d6f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -36,6 +36,15 @@ resources :tenant_platform_guid_strategies resources :tenant_deployments resources :stats + + AtomicAdmin.application_instance_interactions.for_type(:resource).each do |interaction| + controller_name = interaction.key.to_s.pluralize + resources controller_name do + collection do + get :interactions + end + end + end end end end diff --git a/lib/atomic_admin/interaction.rb b/lib/atomic_admin/interaction.rb index 34fa975..7c1d329 100644 --- a/lib/atomic_admin/interaction.rb +++ b/lib/atomic_admin/interaction.rb @@ -1,55 +1,8 @@ -module AtomicAdmin::Interaction - class Manager - def initialize - @interactions = {} - @curr_index = 0 - end - - def add(key, **kwargs) - @interactions[key] = { - **kwargs, - order: @curr_index, - } - - if @interactions[key][:type] == :analytics && @interactions[key][:controller].present? - controller_class = @interactions[key][:controller] - Rails.application.config.to_prepare do - AtomicAdmin::Api::Admin::V1.const_set(:StatsController, controller_class.constantize) - end - end - @curr_index += 1 - end - - def get(key) - @interactions[key] - end +require_relative 'interaction/base' +require_relative 'interaction/json_form' +require_relative 'interaction/analytics' +require_relative 'interaction/resource' +require_relative 'interaction/manager' - def tap - yield self - self - end - - def resolve(**kwargs) - sorted = @interactions.sort_by { |key, interaction| interaction[:order] } - sorted.map do |key, interaction| - type = interaction[:type] - hash = { - key: key, - type: type, - title: interaction[:title], - icon: interaction[:icon], - } - - case type - when :jsonform - schema_factory = interaction[:schema] - schema = schema_factory.new(**kwargs) - hash[:schema] = schema.schema - hash[:uischema] = schema.uischema - end - - hash - end - end - end +module AtomicAdmin::Interaction end diff --git a/lib/atomic_admin/interaction/analytics.rb b/lib/atomic_admin/interaction/analytics.rb new file mode 100644 index 0000000..a2102e6 --- /dev/null +++ b/lib/atomic_admin/interaction/analytics.rb @@ -0,0 +1,13 @@ +module AtomicAdmin::Interaction + class Analytics < AtomicAdmin::Interaction::Base + + def initialize(controller:, **kwargs) + super(**kwargs) + @controller = controller + + Rails.application.config.to_prepare do + AtomicAdmin::Api::Admin::V1.const_set(:StatsController, @controller.constantize) + end + end + end +end diff --git a/lib/atomic_admin/interaction/base.rb b/lib/atomic_admin/interaction/base.rb new file mode 100644 index 0000000..b529dfe --- /dev/null +++ b/lib/atomic_admin/interaction/base.rb @@ -0,0 +1,27 @@ +module AtomicAdmin::Interaction + class Base + attr_accessor :key, :type, :key, :title, :icon, :order + + def initialize(key:, type:, title: nil, icon: nil, order: 0, **kwargs) + @key = key + @title = title + @icon = icon + @order = order + @data = kwargs + @type = type + end + + def resolve(**kwargs) + { + key: key, + type: type, + title: title, + icon: icon, + } + end + + + def to_prepare + end + end +end diff --git a/lib/atomic_admin/interaction/json_form.rb b/lib/atomic_admin/interaction/json_form.rb new file mode 100644 index 0000000..05b501e --- /dev/null +++ b/lib/atomic_admin/interaction/json_form.rb @@ -0,0 +1,19 @@ +module AtomicAdmin::Interaction + class JsonForm < AtomicAdmin::Interaction::Base + + def initialize(schema:, **kwargs) + super(**kwargs) + @schema_factory = schema + end + + def resolve(**kwargs) + hash = super(**kwargs) + + schema = @schema_factory.new(**kwargs) + hash[:schema] = schema.schema + hash[:uischema] = schema.uischema + + hash + end + end +end diff --git a/lib/atomic_admin/interaction/manager.rb b/lib/atomic_admin/interaction/manager.rb new file mode 100644 index 0000000..a07e9b5 --- /dev/null +++ b/lib/atomic_admin/interaction/manager.rb @@ -0,0 +1,59 @@ +module AtomicAdmin::Interaction + class Manager + include Enumerable + + INTERACTIONS = { + analytics: AtomicAdmin::Interaction::Analytics, + jsonform: AtomicAdmin::Interaction::JsonForm, + resource: AtomicAdmin::Interaction::Resource, + }.freeze + + def initialize + @interactions = {} + @curr_index = 0 + end + + def each(&block) + @interactions.each do |key, interaction| + block.call(key, interaction) + end + end + + def add(key, type:, **kwargs) + interaction_cls = INTERACTIONS[type] || AtomicAdmin::Interaction::Base + + interaction = interaction_cls.new(key:, type:, order: @curr_index, **kwargs) + @interactions[key] = interaction + @curr_index += 1 + + nil + end + + def get(key) + @interactions[key] + end + + def [](key) + @interactions[key] + end + + def tap + yield self + self + end + + def for_type(type) + @interactions.values.select { |interaction| interaction.type == type } + end + + + def as_json(**kwargs) + sorted = @interactions.sort_by { |key, interaction| interaction.order } + sorted.map do |key, interaction| + interaction.resolve(**kwargs) + end + end + + alias resolve as_json + end +end diff --git a/lib/atomic_admin/interaction/resource.rb b/lib/atomic_admin/interaction/resource.rb new file mode 100644 index 0000000..eb863f0 --- /dev/null +++ b/lib/atomic_admin/interaction/resource.rb @@ -0,0 +1,15 @@ +module AtomicAdmin::Interaction + class Resource < AtomicAdmin::Interaction::Base + + def initialize(controller:, **kwargs) + super(**kwargs) + @controller = controller + + + Rails.application.config.to_prepare do + controller_name = controller.demodulize + AtomicAdmin::Api::Admin::V1.const_set(controller_name, controller.constantize) + end + end + end +end From b3a688d86b2ebd6c891db7e4b86593544e0b9e37 Mon Sep 17 00:00:00 2001 From: Sean Collings Date: Thu, 22 May 2025 14:33:23 -0600 Subject: [PATCH 2/2] feat: support for custom resources --- .../atomic_admin/v1/admin_controller.rb | 1 + .../v1/application_instances_controller.rb | 2 +- .../v1/applications_controller.rb | 2 +- .../v1/lti_platforms_controller.rb | 2 +- .../atomic_admin/v1/sites_controller.rb | 2 +- .../tenant_client_id_strategies_controller.rb | 2 +- .../v1/tenant_deployments_controller.rb | 2 +- ...ant_platform_guid_strategies_controller.rb | 2 +- lib/atomic_admin.rb | 1 + .../atomic_admin}/filtering.rb | 2 +- lib/atomic_admin/interaction/base.rb | 4 --- lib/atomic_admin/interaction/manager.rb | 4 +-- lib/atomic_admin/interaction/resource.rb | 34 +++++++++++++++++-- 13 files changed, 43 insertions(+), 17 deletions(-) rename {app/controllers/concerns => lib/atomic_admin}/filtering.rb (98%) diff --git a/app/controllers/atomic_admin/v1/admin_controller.rb b/app/controllers/atomic_admin/v1/admin_controller.rb index 1a77f6a..4ecf6b6 100644 --- a/app/controllers/atomic_admin/v1/admin_controller.rb +++ b/app/controllers/atomic_admin/v1/admin_controller.rb @@ -1,6 +1,7 @@ module AtomicAdmin::V1 class AdminController < ActionController::API include RequireJwtToken + before_action :validate_admin_token rescue_from ActiveRecord::RecordNotFound, with: :record_not_found diff --git a/app/controllers/atomic_admin/v1/application_instances_controller.rb b/app/controllers/atomic_admin/v1/application_instances_controller.rb index 5bd1958..794ce02 100644 --- a/app/controllers/atomic_admin/v1/application_instances_controller.rb +++ b/app/controllers/atomic_admin/v1/application_instances_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class ApplicationInstancesController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_sort_columns %w[nickname] allowed_search_columns %w[nickname] diff --git a/app/controllers/atomic_admin/v1/applications_controller.rb b/app/controllers/atomic_admin/v1/applications_controller.rb index 1dd8197..473dc8c 100644 --- a/app/controllers/atomic_admin/v1/applications_controller.rb +++ b/app/controllers/atomic_admin/v1/applications_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class ApplicationsController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_sort_columns %w[name] allowed_search_columns %w[name] diff --git a/app/controllers/atomic_admin/v1/lti_platforms_controller.rb b/app/controllers/atomic_admin/v1/lti_platforms_controller.rb index 8ef423d..7234ae7 100644 --- a/app/controllers/atomic_admin/v1/lti_platforms_controller.rb +++ b/app/controllers/atomic_admin/v1/lti_platforms_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class LtiPlatformsController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_search_columns %w[iss] allowed_sort_columns %w[iss] diff --git a/app/controllers/atomic_admin/v1/sites_controller.rb b/app/controllers/atomic_admin/v1/sites_controller.rb index 8ba7b4e..2b6cb1e 100644 --- a/app/controllers/atomic_admin/v1/sites_controller.rb +++ b/app/controllers/atomic_admin/v1/sites_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class SitesController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_search_columns %w[url] allowed_sort_columns %w[url] diff --git a/app/controllers/atomic_admin/v1/tenant_client_id_strategies_controller.rb b/app/controllers/atomic_admin/v1/tenant_client_id_strategies_controller.rb index 77d905e..7d8750f 100644 --- a/app/controllers/atomic_admin/v1/tenant_client_id_strategies_controller.rb +++ b/app/controllers/atomic_admin/v1/tenant_client_id_strategies_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class TenantClientIdStrategiesController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_search_columns %w[client_id, iss] allowed_sort_columns %w[client_id, iss] diff --git a/app/controllers/atomic_admin/v1/tenant_deployments_controller.rb b/app/controllers/atomic_admin/v1/tenant_deployments_controller.rb index 22f17f5..7232158 100644 --- a/app/controllers/atomic_admin/v1/tenant_deployments_controller.rb +++ b/app/controllers/atomic_admin/v1/tenant_deployments_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class TenantDeploymentsController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_search_columns %w[deployment_id, iss] allowed_sort_columns %w[deployment_id, iss] diff --git a/app/controllers/atomic_admin/v1/tenant_platform_guid_strategies_controller.rb b/app/controllers/atomic_admin/v1/tenant_platform_guid_strategies_controller.rb index cbe0b97..203b134 100644 --- a/app/controllers/atomic_admin/v1/tenant_platform_guid_strategies_controller.rb +++ b/app/controllers/atomic_admin/v1/tenant_platform_guid_strategies_controller.rb @@ -1,6 +1,6 @@ module AtomicAdmin::V1 class TenantPlatformGuidStrategiesController < AdminController - include Filtering + include AtomicAdmin::Filtering allowed_search_columns %w[platform_guid, iss] allowed_sort_columns %w[platform_guid, iss] diff --git a/lib/atomic_admin.rb b/lib/atomic_admin.rb index b72e4c6..c3ede57 100644 --- a/lib/atomic_admin.rb +++ b/lib/atomic_admin.rb @@ -3,6 +3,7 @@ require "atomic_admin/jwt_token" require "atomic_admin/schema" require "atomic_admin/interaction" +require "atomic_admin/filtering" module AtomicAdmin mattr_accessor :admin_jwks_url diff --git a/app/controllers/concerns/filtering.rb b/lib/atomic_admin/filtering.rb similarity index 98% rename from app/controllers/concerns/filtering.rb rename to lib/atomic_admin/filtering.rb index f396af4..a7dea15 100644 --- a/app/controllers/concerns/filtering.rb +++ b/lib/atomic_admin/filtering.rb @@ -1,4 +1,4 @@ -module Filtering +module AtomicAdmin::Filtering extend ActiveSupport::Concern included do diff --git a/lib/atomic_admin/interaction/base.rb b/lib/atomic_admin/interaction/base.rb index b529dfe..12bf977 100644 --- a/lib/atomic_admin/interaction/base.rb +++ b/lib/atomic_admin/interaction/base.rb @@ -19,9 +19,5 @@ def resolve(**kwargs) icon: icon, } end - - - def to_prepare - end end end diff --git a/lib/atomic_admin/interaction/manager.rb b/lib/atomic_admin/interaction/manager.rb index a07e9b5..61ee61b 100644 --- a/lib/atomic_admin/interaction/manager.rb +++ b/lib/atomic_admin/interaction/manager.rb @@ -47,13 +47,11 @@ def for_type(type) end - def as_json(**kwargs) + def resolve(**kwargs) sorted = @interactions.sort_by { |key, interaction| interaction.order } sorted.map do |key, interaction| interaction.resolve(**kwargs) end end - - alias resolve as_json end end diff --git a/lib/atomic_admin/interaction/resource.rb b/lib/atomic_admin/interaction/resource.rb index eb863f0..ace32d5 100644 --- a/lib/atomic_admin/interaction/resource.rb +++ b/lib/atomic_admin/interaction/resource.rb @@ -1,15 +1,45 @@ module AtomicAdmin::Interaction class Resource < AtomicAdmin::Interaction::Base - def initialize(controller:, **kwargs) + def initialize(controller:, table:, actions: [], plural:, singular:, **kwargs) super(**kwargs) @controller = controller - + @table = table + @actions = actions + @plural = plural + @singular = singular Rails.application.config.to_prepare do controller_name = controller.demodulize AtomicAdmin::Api::Admin::V1.const_set(controller_name, controller.constantize) end end + + def resolve(**kwargs) + hash = super(**kwargs) + + hash[:plural] = @plural + hash[:singular] = @singular + hash[:table] = @table + + hash[:actions] = @actions.map do |action| + action_hash = { + type: action[:type], + label: action[:label], + } + + if action[:schema] + schema_factory = action[:schema] + schema = schema_factory.new(**kwargs) + + action_hash[:schema] = schema.schema + action_hash[:uischema] = schema.uischema + end + + action_hash + end + + hash + end end end