activeadmin_favorites 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +17 -0
- data/CODE_OF_CONDUCT.md +31 -0
- data/CONTRIBUTING.md +29 -0
- data/GOVERNANCE.md +29 -0
- data/LICENSE.md +21 -0
- data/README.md +146 -0
- data/SECURITY.md +27 -0
- data/activeadmin_favorites.gemspec +68 -0
- data/app/assets/controllers/activeadmin_favorites/personalization_controller.js +199 -0
- data/app/models/active_admin/favorites/application_record.rb +9 -0
- data/app/models/active_admin/favorites/combined_favorite.rb +9 -0
- data/app/models/active_admin/favorites/favorite/macro_builder.rb +43 -0
- data/app/models/active_admin/favorites/favorite/macro_catalog.rb +118 -0
- data/app/models/active_admin/favorites/favorite/macro_resolver.rb +86 -0
- data/app/models/active_admin/favorites/favorite/macro_validator.rb +87 -0
- data/app/models/active_admin/favorites/favorite/query_params.rb +41 -0
- data/app/models/active_admin/favorites/favorite/range_detector.rb +54 -0
- data/app/models/active_admin/favorites/favorite.rb +339 -0
- data/app/models/active_admin/favorites/filters_favorite.rb +8 -0
- data/app/models/active_admin/favorites/lens_favorite.rb +9 -0
- data/app/models/active_admin/favorites/view_lens/layout.rb +86 -0
- data/app/models/active_admin/favorites/view_lens_default.rb +40 -0
- data/app/models/active_admin/favorites.rb +6 -0
- data/app/views/active_admin/favorites/_lens_catalog_data.html.erb +9 -0
- data/app/views/active_admin/favorites/_macro_fields.html.erb +53 -0
- data/app/views/active_admin/favorites/_personalization_trigger.html.erb +69 -0
- data/app/views/active_admin/resource/index.html.arb +99 -0
- data/app/views/active_admin/resource/show.html.arb +13 -0
- data/config/locales/activeadmin_favorites.en.yml +60 -0
- data/config/locales/activeadmin_favorites.host.yml.example +17 -0
- data/config/polyrun_coverage.yml +8 -0
- data/db/migrate/20260709100000_create_active_admin_view_lens_defaults.rb +24 -0
- data/db/migrate/20260709130000_create_admin_favorites.rb +33 -0
- data/lib/activeadmin/favorites/configuration.rb +31 -0
- data/lib/activeadmin/favorites/engine.rb +75 -0
- data/lib/activeadmin/favorites/hash_coercion.rb +34 -0
- data/lib/activeadmin/favorites/install.rb +121 -0
- data/lib/activeadmin/favorites/migration_helpers.rb +34 -0
- data/lib/activeadmin/favorites/migration_support.rb +19 -0
- data/lib/activeadmin/favorites/register_favorites.rb +272 -0
- data/lib/activeadmin/favorites/register_view_lens_preferences.rb +98 -0
- data/lib/activeadmin/favorites/user_record.rb +26 -0
- data/lib/activeadmin/favorites/version.rb +7 -0
- data/lib/activeadmin/favorites/view_lens/applicator.rb +150 -0
- data/lib/activeadmin/favorites/view_lens/catalog.rb +108 -0
- data/lib/activeadmin/favorites/view_lens/current.rb +28 -0
- data/lib/activeadmin/favorites/view_lens/patches.rb +95 -0
- data/lib/activeadmin/favorites/view_lens/resource_dsl.rb +44 -0
- data/lib/activeadmin/favorites/view_lens.rb +8 -0
- data/lib/activeadmin/favorites.rb +30 -0
- data/lib/activeadmin_favorites.rb +5 -0
- data/lib/generators/activeadmin_favorites/install/templates/favorite_policy.rb +56 -0
- data/lib/generators/activeadmin_favorites/install/templates/initializer.rb +16 -0
- data/lib/generators/activeadmin_favorites/install/templates/locale.en.yml +60 -0
- data/lib/generators/activeadmin_favorites/install_generator.rb +37 -0
- data/lib/tasks/activeadmin_favorites_tasks.rake +39 -0
- data/sig/activeadmin/favorites.rbs +5 -0
- metadata +418 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module Favorites
|
|
5
|
+
module ViewLens
|
|
6
|
+
module TableForPatch
|
|
7
|
+
def column(*args, &block)
|
|
8
|
+
layout = Applicator.current_layout
|
|
9
|
+
resource_key = helpers.active_admin_config&.resource_name&.route_key
|
|
10
|
+
column_id = Applicator.extract_column_id(args, resource_key: resource_key)
|
|
11
|
+
|
|
12
|
+
if resource_key.present? && column_id.present?
|
|
13
|
+
label = Applicator.column_label_from_args(args, column_id: column_id)
|
|
14
|
+
Applicator.register_column(resource_key: resource_key, id: column_id, label: label)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
return if layout&.hidden_column?(column_id)
|
|
18
|
+
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module AttributesTablePatch
|
|
24
|
+
def row(*args, &block)
|
|
25
|
+
layout = Applicator.current_layout
|
|
26
|
+
title = args[0]
|
|
27
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
|
28
|
+
row_id = Applicator.extract_row_id(title, options)
|
|
29
|
+
resource_key = helpers.active_admin_config&.resource_name&.route_key
|
|
30
|
+
|
|
31
|
+
if resource_key.present? && row_id.present?
|
|
32
|
+
Applicator.register_row(resource_key: resource_key, id: row_id, label: title.to_s)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
return if layout&.hidden_show_row?(row_id)
|
|
36
|
+
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module PanelPatch
|
|
42
|
+
def build(title, attributes = {})
|
|
43
|
+
layout = Applicator.current_layout
|
|
44
|
+
panel_id = Applicator.extract_panel_id(title, attributes)
|
|
45
|
+
resource_key = helpers.active_admin_config&.resource_name&.route_key
|
|
46
|
+
|
|
47
|
+
if resource_key.present? && panel_id.present?
|
|
48
|
+
Applicator.register_panel(resource_key: resource_key, id: panel_id, label: title.to_s)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
return if layout&.hidden_panel?(panel_id)
|
|
52
|
+
|
|
53
|
+
attributes = attributes.merge("data-lens-panel": panel_id)
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
module FiltersPatch
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def filter_lookup
|
|
62
|
+
filters = super
|
|
63
|
+
layout = Applicator.current_layout
|
|
64
|
+
return filters if filters.nil?
|
|
65
|
+
return filters unless layout.respond_to?(:hidden_filter?)
|
|
66
|
+
|
|
67
|
+
filters.reject { |filter_key, _| layout.hidden_filter?(filter_key) }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module ActionItemsPatch
|
|
72
|
+
def action_items_for(action, render_context = nil)
|
|
73
|
+
items = super
|
|
74
|
+
layout = Applicator.current_layout
|
|
75
|
+
return items if items.nil?
|
|
76
|
+
return items unless layout.respond_to?(:hidden_action_item?)
|
|
77
|
+
|
|
78
|
+
items.reject { |item| layout.hidden_action_item?(item.name) }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
module InstallPatches
|
|
83
|
+
module_function
|
|
84
|
+
|
|
85
|
+
def call
|
|
86
|
+
ActiveAdmin::Views::TableFor.prepend(TableForPatch) unless ActiveAdmin::Views::TableFor < TableForPatch
|
|
87
|
+
ActiveAdmin::Views::AttributesTable.prepend(AttributesTablePatch) unless ActiveAdmin::Views::AttributesTable < AttributesTablePatch
|
|
88
|
+
ActiveAdmin::Views::Panel.prepend(PanelPatch) unless ActiveAdmin::Views::Panel < PanelPatch
|
|
89
|
+
ActiveAdmin::Filters::ResourceExtension.prepend(FiltersPatch) unless ActiveAdmin::Filters::ResourceExtension < FiltersPatch
|
|
90
|
+
ActiveAdmin::Resource::ActionItems.prepend(ActionItemsPatch) unless ActiveAdmin::Resource::ActionItems < ActionItemsPatch
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module Favorites
|
|
5
|
+
module ViewLens
|
|
6
|
+
module ControllerMethods
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action :apply_active_admin_favorites_lens, only: [:index, :show]
|
|
11
|
+
after_action :clear_active_admin_favorites_lens, only: [:index, :show]
|
|
12
|
+
|
|
13
|
+
helper_method :active_admin_favorites_catalog, :active_admin_favorites_layout
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def clear_active_admin_favorites_lens
|
|
17
|
+
ViewLens::Applicator.reset!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def apply_active_admin_favorites_lens
|
|
21
|
+
return if active_admin_config.resource_class == Favorite
|
|
22
|
+
|
|
23
|
+
ViewLens::Applicator.resolve_layout(controller: self)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def active_admin_favorites_catalog
|
|
27
|
+
context = ViewLens::Current.catalog_context
|
|
28
|
+
return ViewLens::Applicator.current_catalog if ViewLens::Applicator.current_catalog.present?
|
|
29
|
+
return [] unless context
|
|
30
|
+
|
|
31
|
+
ViewLens::Applicator.build_catalog(
|
|
32
|
+
active_admin_config: context[:active_admin_config],
|
|
33
|
+
action: context[:action],
|
|
34
|
+
render_context: context[:render_context]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def active_admin_favorites_layout
|
|
39
|
+
ViewLens::Applicator.current_layout
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "activeadmin/favorites/version"
|
|
4
|
+
require "activeadmin/favorites/configuration"
|
|
5
|
+
|
|
6
|
+
module ActiveAdmin
|
|
7
|
+
module Favorites
|
|
8
|
+
class << self
|
|
9
|
+
def config
|
|
10
|
+
@config ||= Configuration.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def configure
|
|
14
|
+
yield config
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def install!
|
|
18
|
+
require "activeadmin/favorites/install"
|
|
19
|
+
Install.call
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def register_resources!
|
|
23
|
+
require "activeadmin/favorites/register_favorites"
|
|
24
|
+
require "activeadmin/favorites/register_view_lens_preferences"
|
|
25
|
+
RegisterFavorites.call
|
|
26
|
+
RegisterViewLensPreferences.call
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module Favorites
|
|
5
|
+
class FavoritePolicy < ApplicationPolicy
|
|
6
|
+
def index?
|
|
7
|
+
staff?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def show?
|
|
11
|
+
visible?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create?
|
|
15
|
+
staff?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def new?
|
|
19
|
+
create?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update?
|
|
23
|
+
owner?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def edit?
|
|
27
|
+
update?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def destroy?
|
|
31
|
+
owner?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
default_scope do |relation|
|
|
35
|
+
return relation.none unless staff?
|
|
36
|
+
|
|
37
|
+
relation.visible_to(user)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def staff?
|
|
43
|
+
user.present?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def visible?
|
|
47
|
+
staff? && (owner? || record.published?)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def owner?
|
|
51
|
+
foreign_key = ActiveAdmin::Favorites.config.user_foreign_key
|
|
52
|
+
staff? && record.public_send(foreign_key) == user.id
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
ActiveAdmin::Favorites.configure do |config|
|
|
4
|
+
# Example for a custom staff model:
|
|
5
|
+
# config.user_class = "AdminUser"
|
|
6
|
+
# config.user_foreign_key = :admin_user_id
|
|
7
|
+
# config.user_association_name = :admin_user
|
|
8
|
+
# config.user_label_method = :email
|
|
9
|
+
# config.current_user_method = :current_admin_user
|
|
10
|
+
|
|
11
|
+
config.user_class = "User"
|
|
12
|
+
config.user_foreign_key = :user_id
|
|
13
|
+
config.user_association_name = :user
|
|
14
|
+
config.user_label_method = :email
|
|
15
|
+
config.current_user_method = :current_user
|
|
16
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
en:
|
|
2
|
+
active_admin:
|
|
3
|
+
favorites:
|
|
4
|
+
add_favorite: Add to favorites
|
|
5
|
+
advanced_macros: Advanced macros
|
|
6
|
+
created: Favorite saved
|
|
7
|
+
creator_column: Creator
|
|
8
|
+
edit_favorite: Edit favorite
|
|
9
|
+
filters_column: Filters
|
|
10
|
+
form_panel: Favorite details
|
|
11
|
+
macros_hint: Choose shortcut templates to keep date filters up to date when you open this favorite.
|
|
12
|
+
macros_json_hint: JSON array of macro objects. Use only when templates are not enough.
|
|
13
|
+
macros_json_invalid: Macros JSON is invalid
|
|
14
|
+
macros_panel: Dynamic filters
|
|
15
|
+
menu: Favorites
|
|
16
|
+
no_detected_ranges: No date range filters detected in the current view. Use advanced macros if needed.
|
|
17
|
+
open: Open
|
|
18
|
+
published: Published for everyone
|
|
19
|
+
updated: Favorite updated
|
|
20
|
+
use_advanced_macros: Edit macros as JSON
|
|
21
|
+
use_dynamic_range: Use dynamic range
|
|
22
|
+
visibility:
|
|
23
|
+
mine: Only me
|
|
24
|
+
published: "Published (%{time})"
|
|
25
|
+
visibility_column: Visibility
|
|
26
|
+
macro_templates:
|
|
27
|
+
previous_calendar_month: Previous calendar month
|
|
28
|
+
current_calendar_month: Current calendar month
|
|
29
|
+
previous_calendar_day: Previous day
|
|
30
|
+
current_calendar_day: Today
|
|
31
|
+
rolling_last_7_days: Last 7 days
|
|
32
|
+
rolling_last_30_days: Last 30 days
|
|
33
|
+
previous_fiscal_year: Previous fiscal year (Apr–Mar)
|
|
34
|
+
current_fiscal_year_to_date: Current fiscal year to date (Apr–Mar)
|
|
35
|
+
personalize_page: Personalize page
|
|
36
|
+
personalization_region: Page personalization
|
|
37
|
+
save_default: Save as my default
|
|
38
|
+
reset_default: Reset to defaults
|
|
39
|
+
save_lens_favorite: Save lens as favorite
|
|
40
|
+
include_layout: Include current page layout
|
|
41
|
+
lens_summary: Page layout
|
|
42
|
+
lens_created: Lens favorite saved
|
|
43
|
+
combined_created: Combined favorite saved
|
|
44
|
+
layout_saved: Page layout saved
|
|
45
|
+
layout_reset: Page layout reset
|
|
46
|
+
kind_column: Type
|
|
47
|
+
kind_navigation: Favorite types
|
|
48
|
+
no_personalization_items: No personalization options are available on this page.
|
|
49
|
+
kinds:
|
|
50
|
+
all: All
|
|
51
|
+
filters: Filters
|
|
52
|
+
lens: Lens
|
|
53
|
+
combined: Combined
|
|
54
|
+
groups:
|
|
55
|
+
columns: Columns
|
|
56
|
+
filters: Filters
|
|
57
|
+
action_items: Actions
|
|
58
|
+
panels: Panels
|
|
59
|
+
show_rows: Rows
|
|
60
|
+
block_column: Custom column %{position}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/base"
|
|
4
|
+
|
|
5
|
+
module ActiveadminFavorites
|
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
|
7
|
+
source_root File.expand_path("install/templates", __dir__)
|
|
8
|
+
|
|
9
|
+
desc "Install activeadmin_favorites initializer, policy, and locale template"
|
|
10
|
+
|
|
11
|
+
def copy_initializer
|
|
12
|
+
template "initializer.rb", "config/initializers/activeadmin_favorites.rb"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def copy_policy
|
|
16
|
+
template "favorite_policy.rb", "app/policies/active_admin/favorites/favorite_policy.rb"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def copy_locale_template
|
|
20
|
+
template "locale.en.yml", "config/locales/activeadmin_favorites.en.yml"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def install_migrations
|
|
24
|
+
rake "activeadmin_favorites:install:migrations"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def show_page_policy_note
|
|
28
|
+
say <<~NOTE, :yellow
|
|
29
|
+
|
|
30
|
+
Add save_lens_favorite? and reset? to your ActiveAdmin::PagePolicy (or equivalent)
|
|
31
|
+
so view lens preference page actions authorize correctly.
|
|
32
|
+
|
|
33
|
+
Copy active_admin.favorites keys into your fi/sv locale files if needed.
|
|
34
|
+
NOTE
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :activeadmin_favorites do
|
|
4
|
+
namespace :install do
|
|
5
|
+
desc "Copy activeadmin_favorites migrations into db/migrate"
|
|
6
|
+
task migrations: :environment do
|
|
7
|
+
require "fileutils"
|
|
8
|
+
require "activeadmin/favorites/migration_helpers"
|
|
9
|
+
|
|
10
|
+
destination = Rails.root.join("db/migrate")
|
|
11
|
+
FileUtils.mkdir_p(destination)
|
|
12
|
+
|
|
13
|
+
copied = []
|
|
14
|
+
skipped = []
|
|
15
|
+
|
|
16
|
+
ActiveAdmin::Favorites::MigrationHelpers.engine_migration_paths.each do |source|
|
|
17
|
+
target = destination.join(File.basename(source))
|
|
18
|
+
version = File.basename(source).split("_", 2).first
|
|
19
|
+
|
|
20
|
+
if target.exist?
|
|
21
|
+
skipped << version
|
|
22
|
+
next
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
FileUtils.cp(source, target)
|
|
26
|
+
copied << version
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if copied.any?
|
|
30
|
+
puts "Copied migrations: #{copied.join(", ")}"
|
|
31
|
+
else
|
|
32
|
+
puts "No new migrations copied."
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
puts "Skipped existing versions: #{skipped.join(", ")}" if skipped.any?
|
|
36
|
+
puts "Run bin/rails db:migrate when ready."
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|