activeadmin_favorites 0.1.9 → 0.1.10
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/app/assets/controllers/activeadmin_favorites/filter_favorite_controller.js +38 -0
- data/app/assets/controllers/activeadmin_favorites/macro_fields_controller.js +34 -0
- data/app/models/active_admin/favorites/favorite.rb +5 -1
- data/app/views/active_admin/favorites/_filter_favorite_button.html.erb +16 -1
- data/app/views/active_admin/favorites/_macro_fields.html.erb +63 -48
- data/config/locales/activeadmin_favorites.en.yml +1 -0
- data/lib/activeadmin/favorites/engine.rb +6 -0
- data/lib/activeadmin/favorites/install.rb +10 -1
- data/lib/activeadmin/favorites/register_favorites.rb +33 -1
- data/lib/activeadmin/favorites/version.rb +1 -1
- data/lib/generators/activeadmin_favorites/install/templates/locale.en.yml +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb66b5a12099039bdfcb6e541cfad6bf15be19aab694d260b3440a026fab49ed
|
|
4
|
+
data.tar.gz: fed666eb55e41a6cf53b1dae6cb8ec88e13cc84980514e454d81c93227a7b84b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a5771c7a4aeaef966f22fe485af17c9c7f76053b788f53a53b54fb63d4b171e13f2cb60280fd6348edefd695e5701e69086b1fc7a56585ec31efe8868755234
|
|
7
|
+
data.tar.gz: 35f952fa4d89e25bfcbeb7c5c389b80b7256d607e7ec0605be9f269a8dad56e0101b9a37513014f610c7bfba9f548161d374a53ae4a0e0a9f244b147a3d29ab2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.1.10 (2026-11-04)
|
|
4
|
+
|
|
5
|
+
- Save a private filter favorite from the index star in one step (suggested name; stay on the filtered index).
|
|
6
|
+
- Keep the full favorites form for edit and as a no-JavaScript fallback from the star.
|
|
7
|
+
- Drop the required marker on "Published for everyone".
|
|
8
|
+
- Show macros JSON only when "Edit macros as JSON" is checked; disable template rows in that mode.
|
|
9
|
+
- Hide Dynamic filters and Advanced macros on create when no date ranges are detected.
|
|
10
|
+
|
|
3
11
|
## 0.1.9 (2026-11-04)
|
|
4
12
|
|
|
5
13
|
- Show Add to favorites / Edit favorite as a star icon button on index action rows (accessible name only; filled when an owned favorite matches).
|
data/README.md
CHANGED
|
@@ -108,7 +108,7 @@ Catalog entries are discovered at render time from ActiveAdmin columns, filters,
|
|
|
108
108
|
|
|
109
109
|
The gem installs:
|
|
110
110
|
|
|
111
|
-
- **Add to favorites** star icon on index pages (outline when unsaved, filled when an owned filter favorite matches the current query; label is the accessible name only)
|
|
111
|
+
- **Add to favorites** star icon on index pages (outline when unsaved, filled when an owned filter favorite matches the current query; label is the accessible name only). With JavaScript, the star saves a private filter favorite under a suggested name and stays on the filtered index. The full form remains for edit and as a no-JavaScript fallback.
|
|
112
112
|
- **Personalize page** cogwheel on index and show pages (hidden when the page lens catalog is empty)
|
|
113
113
|
- **Favorites** hub at `/admin/favorites` with type tabs (all, filters, lens, combined)
|
|
114
114
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static values = {
|
|
5
|
+
createUrl: String,
|
|
6
|
+
path: String,
|
|
7
|
+
queryString: String,
|
|
8
|
+
resourceKey: String,
|
|
9
|
+
actionName: String
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async quickCreate(event) {
|
|
13
|
+
event.preventDefault()
|
|
14
|
+
|
|
15
|
+
const body = new FormData()
|
|
16
|
+
body.append("path", this.pathValue)
|
|
17
|
+
body.append("query_string", this.queryStringValue || "")
|
|
18
|
+
body.append("resource_key", this.resourceKeyValue)
|
|
19
|
+
body.append("action_name", this.actionNameValue || "index")
|
|
20
|
+
body.append("authenticity_token", this.csrfToken())
|
|
21
|
+
|
|
22
|
+
const response = await fetch(this.createUrlValue, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
body,
|
|
25
|
+
headers: { Accept: "text/html" }
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
if (response.redirected) {
|
|
29
|
+
window.location.href = response.url
|
|
30
|
+
} else if (response.ok) {
|
|
31
|
+
window.location.reload()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
csrfToken() {
|
|
36
|
+
return document.querySelector("meta[name='csrf-token']")?.content
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static targets = ["jsonField", "templates", "hint"]
|
|
5
|
+
|
|
6
|
+
connect() {
|
|
7
|
+
this.sync(this.advancedChecked())
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
toggle(event) {
|
|
11
|
+
this.sync(event.target.checked)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
sync(advanced) {
|
|
15
|
+
if (this.hasJsonFieldTarget) {
|
|
16
|
+
this.jsonFieldTarget.hidden = !advanced
|
|
17
|
+
this.jsonFieldTarget.disabled = !advanced
|
|
18
|
+
}
|
|
19
|
+
if (this.hasHintTarget) {
|
|
20
|
+
this.hintTarget.hidden = !advanced
|
|
21
|
+
}
|
|
22
|
+
if (this.hasTemplatesTarget) {
|
|
23
|
+
this.templatesTarget.querySelectorAll("input, select").forEach((element) => {
|
|
24
|
+
if (element.type === "hidden") return
|
|
25
|
+
element.disabled = advanced
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
advancedChecked() {
|
|
31
|
+
const checkbox = this.element.querySelector("#favorite_use_advanced_macros")
|
|
32
|
+
return Boolean(checkbox?.checked)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -22,7 +22,6 @@ module ActiveAdmin
|
|
|
22
22
|
attr_accessor :macros_json, :use_advanced_macros, :include_layout
|
|
23
23
|
|
|
24
24
|
validates :name, :resource_key, :path, presence: true
|
|
25
|
-
validates :published, inclusion: {in: [true, false]}
|
|
26
25
|
validates :macros_version, numericality: {only_integer: true, greater_than: 0}
|
|
27
26
|
validates :action, inclusion: {in: ACTIONS}, allow_nil: true
|
|
28
27
|
|
|
@@ -31,6 +30,7 @@ module ActiveAdmin
|
|
|
31
30
|
validate :validate_macros_schema
|
|
32
31
|
|
|
33
32
|
before_validation :normalize_blank_query_string
|
|
33
|
+
before_validation :normalize_published
|
|
34
34
|
|
|
35
35
|
before_save :sync_published_at
|
|
36
36
|
before_validation :assign_default_type
|
|
@@ -294,6 +294,10 @@ module ActiveAdmin
|
|
|
294
294
|
self.query_string = "" if query_string.nil?
|
|
295
295
|
end
|
|
296
296
|
|
|
297
|
+
def normalize_published
|
|
298
|
+
self.published = false if published.nil?
|
|
299
|
+
end
|
|
300
|
+
|
|
297
301
|
def unique_path_query_and_type_per_user
|
|
298
302
|
foreign_key = ActiveAdmin::Favorites.config.user_foreign_key
|
|
299
303
|
owner_id = public_send(foreign_key)
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
+
<%
|
|
2
|
+
stimulus_controller = "activeadmin-favorites--filter-favorite"
|
|
3
|
+
link_data = {testid: "filter-favorite", favorited: favorited}
|
|
4
|
+
unless favorited
|
|
5
|
+
link_data.merge!(
|
|
6
|
+
controller: stimulus_controller,
|
|
7
|
+
action: "click->#{stimulus_controller}#quickCreate",
|
|
8
|
+
"#{stimulus_controller}-create-url-value": quick_create_url,
|
|
9
|
+
"#{stimulus_controller}-path-value": path,
|
|
10
|
+
"#{stimulus_controller}-query-string-value": query_string.to_s,
|
|
11
|
+
"#{stimulus_controller}-resource-key-value": resource_key,
|
|
12
|
+
"#{stimulus_controller}-action-name-value": action_name
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
%>
|
|
1
16
|
<%= link_to(
|
|
2
17
|
destination,
|
|
3
18
|
class: "action-item-button inline-flex items-center justify-center",
|
|
4
19
|
aria: {label: label},
|
|
5
|
-
data:
|
|
20
|
+
data: link_data,
|
|
6
21
|
title: label
|
|
7
22
|
) do %>
|
|
8
23
|
<% if favorited %>
|
|
@@ -1,53 +1,68 @@
|
|
|
1
1
|
<% bookmark = f.object %>
|
|
2
|
-
<%
|
|
3
|
-
|
|
2
|
+
<% show_templates = bookmark.macro_form_rows.any? %>
|
|
3
|
+
<% show_advanced = show_templates || bookmark.persisted? || ActiveModel::Type::Boolean.new.cast(bookmark.use_advanced_macros) %>
|
|
4
|
+
<% if show_templates || show_advanced %>
|
|
5
|
+
<% template_options = ActiveAdmin::Favorites::Favorite::MacroCatalog.options_for_select %>
|
|
6
|
+
<%= hidden_field_tag :macro_form_submitted, "1" %>
|
|
4
7
|
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
<div data-controller="activeadmin-favorites--macro-fields">
|
|
9
|
+
<% if show_templates %>
|
|
10
|
+
<fieldset class="inputs" data-activeadmin-favorites--macro-fields-target="templates">
|
|
11
|
+
<legend><span><%= t("active_admin.favorites.macros_panel") %></span></legend>
|
|
12
|
+
<p class="inline-hints"><%= t("active_admin.favorites.macros_hint") %></p>
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<p class="text-sm text-gray-600 dark:text-gray-300"><%= t("active_admin.favorites.no_detected_ranges") %></p>
|
|
37
|
-
<% end %>
|
|
38
|
-
</fieldset>
|
|
14
|
+
<ol class="space-y-4 list-none p-0">
|
|
15
|
+
<% bookmark.macro_form_rows.each_with_index do |row, index| %>
|
|
16
|
+
<li class="rounded-md border border-gray-200 p-4 dark:border-white/10">
|
|
17
|
+
<div class="font-medium text-sm mb-2">
|
|
18
|
+
<%= row[:attribute].to_s.tr("_", " ") %>
|
|
19
|
+
<% if row[:gteq].present? || row[:lteq].present? %>
|
|
20
|
+
<span class="text-gray-500">
|
|
21
|
+
(<%= [row[:gteq], row[:lteq]].compact.join(" – ") %>)
|
|
22
|
+
</span>
|
|
23
|
+
<% end %>
|
|
24
|
+
</div>
|
|
25
|
+
<%= hidden_field_tag "macro_template_assignments[#{index}][attribute]", row[:attribute] %>
|
|
26
|
+
<div class="flex flex-wrap items-center gap-4">
|
|
27
|
+
<label class="inline-flex items-center gap-2 text-sm">
|
|
28
|
+
<%= check_box_tag "macro_template_assignments[#{index}][enabled]", "1", row[:enabled], id: "macro_template_assignments_#{index}_enabled" %>
|
|
29
|
+
<%= t("active_admin.favorites.use_dynamic_range") %>
|
|
30
|
+
</label>
|
|
31
|
+
<%= select_tag "macro_template_assignments[#{index}][name]",
|
|
32
|
+
options_for_select(template_options, row[:name]),
|
|
33
|
+
id: "macro_template_assignments_#{index}_name",
|
|
34
|
+
class: "rounded-md border-gray-300 text-sm dark:border-white/20 dark:bg-gray-900" %>
|
|
35
|
+
</div>
|
|
36
|
+
</li>
|
|
37
|
+
<% end %>
|
|
38
|
+
</ol>
|
|
39
|
+
</fieldset>
|
|
40
|
+
<% end %>
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
<% if show_advanced %>
|
|
43
|
+
<details class="mt-6 rounded-md border border-gray-200 p-4 dark:border-white/10" <%= "open" if ActiveModel::Type::Boolean.new.cast(bookmark.use_advanced_macros) %>>
|
|
44
|
+
<summary class="cursor-pointer text-sm font-medium"><%= t("active_admin.favorites.advanced_macros") %></summary>
|
|
45
|
+
<div class="mt-4 space-y-3">
|
|
46
|
+
<label class="inline-flex items-center gap-2 text-sm">
|
|
47
|
+
<%= check_box_tag "favorite[use_advanced_macros]", "1", bookmark.use_advanced_macros,
|
|
48
|
+
id: "favorite_use_advanced_macros",
|
|
49
|
+
data: {action: "change->activeadmin-favorites--macro-fields#toggle"} %>
|
|
50
|
+
<%= t("active_admin.favorites.use_advanced_macros") %>
|
|
51
|
+
</label>
|
|
52
|
+
<p class="text-xs text-gray-500"><%= t("active_admin.favorites.use_advanced_macros_hint") %></p>
|
|
53
|
+
<%= text_area_tag "favorite[macros_json]", bookmark.macros_json_for_form,
|
|
54
|
+
rows: 10,
|
|
55
|
+
id: "favorite_macros_json",
|
|
56
|
+
class: "w-full font-mono text-xs rounded-md border-gray-300 dark:border-white/20 dark:bg-gray-900",
|
|
57
|
+
spellcheck: false,
|
|
58
|
+
hidden: !ActiveModel::Type::Boolean.new.cast(bookmark.use_advanced_macros),
|
|
59
|
+
disabled: !ActiveModel::Type::Boolean.new.cast(bookmark.use_advanced_macros),
|
|
60
|
+
data: {"activeadmin-favorites--macro-fields-target": "jsonField"} %>
|
|
61
|
+
<p class="text-xs text-gray-500" data-activeadmin-favorites--macro-fields-target="hint" <%= "hidden" unless ActiveModel::Type::Boolean.new.cast(bookmark.use_advanced_macros) %>>
|
|
62
|
+
<%= t("active_admin.favorites.macros_json_hint") %>
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
</details>
|
|
66
|
+
<% end %>
|
|
52
67
|
</div>
|
|
53
|
-
|
|
68
|
+
<% end %>
|
|
@@ -19,6 +19,7 @@ en:
|
|
|
19
19
|
published: Published for everyone
|
|
20
20
|
updated: Favorite updated
|
|
21
21
|
use_advanced_macros: Edit macros as JSON
|
|
22
|
+
use_advanced_macros_hint: When checked, the JSON below replaces template assignments on save.
|
|
22
23
|
use_dynamic_range: Use dynamic range
|
|
23
24
|
visibility:
|
|
24
25
|
mine: Only me
|
|
@@ -29,6 +29,8 @@ module ActiveAdmin
|
|
|
29
29
|
next unless app.config.respond_to?(:assets)
|
|
30
30
|
|
|
31
31
|
app.config.assets.precompile << "activeadmin_favorites/personalization_controller.js"
|
|
32
|
+
app.config.assets.precompile << "activeadmin_favorites/filter_favorite_controller.js"
|
|
33
|
+
app.config.assets.precompile << "activeadmin_favorites/macro_fields_controller.js"
|
|
32
34
|
app.config.assets.precompile << "activeadmin_favorites/personalization_menu.css"
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -36,6 +38,10 @@ module ActiveAdmin
|
|
|
36
38
|
pin_controller = proc do |importmap|
|
|
37
39
|
importmap.pin "controllers/activeadmin_favorites/personalization_controller",
|
|
38
40
|
to: "activeadmin_favorites/personalization_controller.js"
|
|
41
|
+
importmap.pin "controllers/activeadmin_favorites/filter_favorite_controller",
|
|
42
|
+
to: "activeadmin_favorites/filter_favorite_controller.js"
|
|
43
|
+
importmap.pin "controllers/activeadmin_favorites/macro_fields_controller",
|
|
44
|
+
to: "activeadmin_favorites/macro_fields_controller.js"
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
application_importmap = Rails.application.importmap if Rails.application.respond_to?(:importmap)
|
|
@@ -96,7 +96,16 @@ module ActiveAdmin
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
render partial: "active_admin/favorites/filter_favorite_button",
|
|
99
|
-
locals: {
|
|
99
|
+
locals: {
|
|
100
|
+
label: label,
|
|
101
|
+
destination: destination,
|
|
102
|
+
favorited: favorited,
|
|
103
|
+
quick_create_url: quick_create_admin_favorites_path,
|
|
104
|
+
path: request.path,
|
|
105
|
+
query_string: sanitized_query,
|
|
106
|
+
resource_key: active_admin_config.resource_name.route_key,
|
|
107
|
+
action_name: "index"
|
|
108
|
+
}
|
|
100
109
|
end
|
|
101
110
|
end
|
|
102
111
|
|
|
@@ -19,6 +19,36 @@ module ActiveAdmin
|
|
|
19
19
|
permit_params :name, :note, :path, :query_string, :resource_key, :published, :macros_json,
|
|
20
20
|
:use_advanced_macros, :kind, :type, :action, :include_layout, layout: {}
|
|
21
21
|
|
|
22
|
+
collection_action :quick_create, method: :post do
|
|
23
|
+
user = current_favorites_user
|
|
24
|
+
path = params.require(:path)
|
|
25
|
+
query_string = Favorite.sanitize_query_string(params[:query_string])
|
|
26
|
+
resource_key = params.require(:resource_key)
|
|
27
|
+
action_name = params[:action_name].presence || "index"
|
|
28
|
+
return_to = query_string.present? ? "#{path}?#{query_string}" : path
|
|
29
|
+
|
|
30
|
+
bookmark = FiltersFavorite.new(
|
|
31
|
+
name: Favorite.suggested_name(
|
|
32
|
+
resource_key: resource_key,
|
|
33
|
+
query_string: query_string,
|
|
34
|
+
kind: "filters"
|
|
35
|
+
),
|
|
36
|
+
path: path,
|
|
37
|
+
query_string: query_string,
|
|
38
|
+
resource_key: resource_key,
|
|
39
|
+
action: action_name,
|
|
40
|
+
published: false
|
|
41
|
+
)
|
|
42
|
+
bookmark.public_send(:"#{ActiveAdmin::Favorites.config.user_foreign_key}=", user.id)
|
|
43
|
+
authorize! ActiveAdmin::Auth::CREATE, bookmark
|
|
44
|
+
|
|
45
|
+
if bookmark.save
|
|
46
|
+
redirect_to return_to, notice: I18n.t("active_admin.favorites.created")
|
|
47
|
+
else
|
|
48
|
+
redirect_to return_to, alert: bookmark.errors.full_messages.to_sentence
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
22
52
|
controller do
|
|
23
53
|
helper_method :current_favorites_user, :favorites_kind_tab_active?
|
|
24
54
|
|
|
@@ -37,7 +67,8 @@ module ActiveAdmin
|
|
|
37
67
|
get_resource_ivar || begin
|
|
38
68
|
kind = params.dig(:favorite, :kind).presence || params[:kind].presence || "filters"
|
|
39
69
|
record = Favorite.sti_class_for_kind(kind).new
|
|
40
|
-
|
|
70
|
+
assign_new_favorite_defaults(record)
|
|
71
|
+
record = assign_attributes(record, resource_params) if params[:favorite].present?
|
|
41
72
|
authorize_resource!(record)
|
|
42
73
|
set_resource_ivar(record)
|
|
43
74
|
end
|
|
@@ -236,6 +267,7 @@ module ActiveAdmin
|
|
|
236
267
|
f.input :name, input_html: {autofocus: true}
|
|
237
268
|
f.input :note, as: :text, input_html: {rows: 3}
|
|
238
269
|
f.input :published, as: :boolean,
|
|
270
|
+
required: false,
|
|
239
271
|
label: I18n.t("active_admin.favorites.published")
|
|
240
272
|
if f.object.new_record?
|
|
241
273
|
f.input :path, as: :hidden
|
|
@@ -18,6 +18,7 @@ en:
|
|
|
18
18
|
published: Published for everyone
|
|
19
19
|
updated: Favorite updated
|
|
20
20
|
use_advanced_macros: Edit macros as JSON
|
|
21
|
+
use_advanced_macros_hint: When checked, the JSON below replaces template assignments on save.
|
|
21
22
|
use_dynamic_range: Use dynamic range
|
|
22
23
|
visibility:
|
|
23
24
|
mine: Only me
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activeadmin_favorites
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -339,6 +339,8 @@ files:
|
|
|
339
339
|
- README.md
|
|
340
340
|
- SECURITY.md
|
|
341
341
|
- activeadmin_favorites.gemspec
|
|
342
|
+
- app/assets/controllers/activeadmin_favorites/filter_favorite_controller.js
|
|
343
|
+
- app/assets/controllers/activeadmin_favorites/macro_fields_controller.js
|
|
342
344
|
- app/assets/controllers/activeadmin_favorites/personalization_controller.js
|
|
343
345
|
- app/assets/stylesheets/activeadmin_favorites/personalization_menu.css
|
|
344
346
|
- app/models/active_admin/favorites.rb
|