thecore_ui_rails_admin 3.6.1 → 3.8.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 +4 -4
- data/README.md +35 -0
- data/app/views/rails_admin/main/push_notification_test.html.erb +92 -32
- data/config/initializers/concern_default_navigation.rb +64 -0
- data/config/locales/en.thecore_ui_ra.yml +16 -0
- data/config/locales/it.thecore_ui_ra.yml +16 -0
- data/lib/root_actions/push_notification_test.rb +12 -1
- data/lib/thecore_ui_rails_admin/version.rb +1 -1
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 68bdc2c266f2da01e7c620cad865a2a41960dd7be738643d8a97bb52e09bc164
|
|
4
|
+
data.tar.gz: 60447392948bb9d54f028b2a8eb19d7fd5e8664e1202959de8ad0390cafcf55f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4230e1a6cb30a8af5bca7ef1424c862ff8d235be31d17f6fa86163c12e3940d089e2b11cfe169021c3bed18ea576e3b932b85f05719319868267707b4e7733d1
|
|
7
|
+
data.tar.gz: ade89d04b3ab490a86c8753cb92c8a560ea2fe9da16248ffbcb8c30c9ac1251f13f7955bd386db9cc627b0d9c31fdc91832fb2ddcd0968cf3a5efaa12f16d452
|
data/README.md
CHANGED
|
@@ -2,6 +2,41 @@ This is part of [Thecore framework](https://github.com/gabrieletassoni/thecore/t
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
## Default `navigation_label`/icon for models without a `RailsAdmin::ModelName` concern
|
|
6
|
+
|
|
7
|
+
Per [ADR 0001](https://github.com/gabrieletassoni/thecore/blob/release/3/docs/adr/0001-application-record-defaults-over-generated-concerns.md)
|
|
8
|
+
(host app), any `ApplicationRecord` subclass that does **not** define its own
|
|
9
|
+
`RailsAdmin::ModelName` concern still gets a sensible `navigation_label` and
|
|
10
|
+
a real default icon (`fa fa-table`) in the RailsAdmin sidebar, instead of
|
|
11
|
+
falling back to RailsAdmin's own unconfigured default (no group / no icon).
|
|
12
|
+
|
|
13
|
+
This is provided by `ThecoreUiRailsAdminDefaultNavigationConcern`
|
|
14
|
+
(`config/initializers/concern_default_navigation.rb`), registered into
|
|
15
|
+
[`ThecoreBackendCommons::DefaultModuleRegistry`](../thecore_backend_commons/README.md)
|
|
16
|
+
so it is included automatically into every model at class-definition time —
|
|
17
|
+
no generated concern file required.
|
|
18
|
+
|
|
19
|
+
The default `navigation_label` reuses the exact same i18n key
|
|
20
|
+
(`I18n.t('admin.registries.label')`) that the Thecore VS Code extension's
|
|
21
|
+
`addModel` command already hardcodes into every freshly generated
|
|
22
|
+
`RailsAdmin::ModelName` concern, so a model relying on this default reads
|
|
23
|
+
identically, to an end user, to one whose generated-and-never-customized
|
|
24
|
+
concern was kept around.
|
|
25
|
+
|
|
26
|
+
**Field-level configuration is never defaulted** — `hide`, `sticky`,
|
|
27
|
+
`configure :field`, custom `list`/`edit` blocks, etc. stay exclusively in
|
|
28
|
+
hand-written `RailsAdmin::ModelName` concerns. A model that already has its
|
|
29
|
+
own concern is unaffected: its own `navigation_label`/`navigation_icon` (if
|
|
30
|
+
set) and all field-level config still win over/apply alongside the default.
|
|
31
|
+
|
|
32
|
+
> **Temporary dependency note**: this feature requires
|
|
33
|
+
> `ThecoreBackendCommons::DefaultModuleRegistry`, merged into
|
|
34
|
+
> `thecore_backend_commons`'s `release/3` branch but not yet published to
|
|
35
|
+
> RubyGems. The `Gemfile` pins a git source for this
|
|
36
|
+
> (`github: "gabrieletassoni/thecore_backend_commons", branch: "release/3"`)
|
|
37
|
+
> until a real release ships — remove it once `thecore_backend_commons`
|
|
38
|
+
> cuts a version satisfying the gemspec's `>= 3.4` constraint.
|
|
39
|
+
|
|
5
40
|
## Push Notification Test (RailsAdmin root action)
|
|
6
41
|
|
|
7
42
|
A built-in admin UI for sending Web Push test notifications. It lets you pick one or more active subscribers and fire a real notification immediately — useful for verifying the end-to-end VAPID setup without writing any code.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<span class="hide-toolbar"></span>
|
|
2
2
|
|
|
3
3
|
<div class="container mt-4">
|
|
4
|
-
<h2
|
|
4
|
+
<h2><%= t("admin.actions.push_notification_test.title") %></h2>
|
|
5
5
|
|
|
6
6
|
<% if flash[:success].present? %>
|
|
7
7
|
<div class="alert alert-success"><%= flash[:success] %></div>
|
|
@@ -10,10 +10,41 @@
|
|
|
10
10
|
<div class="alert alert-danger"><%= flash[:error] %></div>
|
|
11
11
|
<% end %>
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
<datalist id="subscriber-email-list">
|
|
14
|
+
<% @subscriber_emails.each do |email| %>
|
|
15
|
+
<option value="<%= email %>">
|
|
16
|
+
<% end %>
|
|
17
|
+
</datalist>
|
|
18
|
+
|
|
19
|
+
<%= form_with url: push_notification_test_path, method: :get, local: true do |f| %>
|
|
20
|
+
<div class="card mb-4">
|
|
21
|
+
<div class="card-header d-flex align-items-center justify-content-between">
|
|
22
|
+
<h5 class="mb-0"><%= t("admin.actions.push_notification_test.filter_title") %></h5>
|
|
23
|
+
<span class="badge bg-secondary">
|
|
24
|
+
<%= t("admin.actions.push_notification_test.total_count", count: @total_count) %>
|
|
25
|
+
</span>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="card-body">
|
|
28
|
+
<div class="input-group">
|
|
29
|
+
<%= f.text_field :q,
|
|
30
|
+
value: params[:q],
|
|
31
|
+
class: "form-control",
|
|
32
|
+
placeholder: t("admin.actions.push_notification_test.filter_placeholder"),
|
|
33
|
+
list: "subscriber-email-list",
|
|
34
|
+
autocomplete: "off" %>
|
|
35
|
+
<%= f.submit t("admin.actions.push_notification_test.filter_button"),
|
|
36
|
+
class: "btn btn-secondary" %>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
<% end %>
|
|
41
|
+
|
|
42
|
+
<%= form_with url: push_notification_test_path, method: :post, local: true, id: "send-push-form" do |form| %>
|
|
43
|
+
<%= hidden_field_tag :q, params[:q] %>
|
|
44
|
+
|
|
14
45
|
<div class="card mb-4">
|
|
15
46
|
<div class="card-header">
|
|
16
|
-
<h5 class="mb-0"
|
|
47
|
+
<h5 class="mb-0"><%= t("admin.actions.push_notification_test.select_subscribers") %></h5>
|
|
17
48
|
</div>
|
|
18
49
|
<div class="card-body">
|
|
19
50
|
<% if @subscribers.any? %>
|
|
@@ -22,7 +53,7 @@
|
|
|
22
53
|
<%= check_box_tag "subscriber_ids[]",
|
|
23
54
|
subscriber.id,
|
|
24
55
|
false,
|
|
25
|
-
class: "form-check-input",
|
|
56
|
+
class: "form-check-input subscriber-checkbox",
|
|
26
57
|
id: "subscriber_#{subscriber.id}" %>
|
|
27
58
|
<label class="form-check-label" for="subscriber_<%= subscriber.id %>">
|
|
28
59
|
<strong><%= subscriber.user&.email || "user ##{subscriber.user_id}" %></strong>
|
|
@@ -33,44 +64,73 @@
|
|
|
33
64
|
</label>
|
|
34
65
|
</div>
|
|
35
66
|
<% end %>
|
|
67
|
+
<% elsif params[:q].present? %>
|
|
68
|
+
<p class="text-muted"><%= t("admin.actions.push_notification_test.no_results") %></p>
|
|
36
69
|
<% else %>
|
|
37
|
-
<p class="text-muted">
|
|
70
|
+
<p class="text-muted">
|
|
71
|
+
<%= t("admin.actions.push_notification_test.disclaimer_no_filter", count: @total_count) %>
|
|
72
|
+
</p>
|
|
38
73
|
<% end %>
|
|
39
74
|
</div>
|
|
40
75
|
</div>
|
|
41
76
|
|
|
42
|
-
|
|
43
|
-
<div class="card-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
<div class="card-body">
|
|
47
|
-
<div class="mb-3">
|
|
48
|
-
<%= form.label :title, "Title", class: "form-label" %>
|
|
49
|
-
<%= form.text_field :title, class: "form-control", required: true,
|
|
50
|
-
placeholder: "Notification title" %>
|
|
77
|
+
<% if @subscribers.any? %>
|
|
78
|
+
<div class="card mb-4">
|
|
79
|
+
<div class="card-header">
|
|
80
|
+
<h5 class="mb-0"><%= t("admin.actions.push_notification_test.message_title") %></h5>
|
|
51
81
|
</div>
|
|
82
|
+
<div class="card-body">
|
|
83
|
+
<div class="mb-3">
|
|
84
|
+
<%= form.label :title, t("admin.actions.push_notification_test.title_label"), class: "form-label" %>
|
|
85
|
+
<%= form.text_field :title, class: "form-control", required: true,
|
|
86
|
+
placeholder: t("admin.actions.push_notification_test.title_placeholder") %>
|
|
87
|
+
</div>
|
|
52
88
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
89
|
+
<div class="mb-3">
|
|
90
|
+
<%= form.label :body, t("admin.actions.push_notification_test.body_label"), class: "form-label" %>
|
|
91
|
+
<%= form.text_area :body, class: "form-control", rows: 3,
|
|
92
|
+
placeholder: t("admin.actions.push_notification_test.body_placeholder") %>
|
|
93
|
+
</div>
|
|
58
94
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
95
|
+
<div class="mb-3">
|
|
96
|
+
<%= form.label :url, t("admin.actions.push_notification_test.url_label"), class: "form-label" %>
|
|
97
|
+
<%= form.url_field :url, class: "form-control",
|
|
98
|
+
placeholder: "https://example.com/target-page" %>
|
|
99
|
+
</div>
|
|
64
100
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
101
|
+
<div class="mb-3">
|
|
102
|
+
<%= form.label :icon, t("admin.actions.push_notification_test.icon_label"), class: "form-label" %>
|
|
103
|
+
<%= form.url_field :icon, class: "form-control",
|
|
104
|
+
placeholder: "https://example.com/icon.png" %>
|
|
105
|
+
</div>
|
|
70
106
|
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
<%= form.submit t("admin.actions.push_notification_test.send_button"),
|
|
108
|
+
class: "btn btn-primary",
|
|
109
|
+
id: "send-push-btn" %>
|
|
110
|
+
</div>
|
|
73
111
|
</div>
|
|
74
|
-
|
|
112
|
+
<% end %>
|
|
75
113
|
<% end %>
|
|
76
114
|
</div>
|
|
115
|
+
|
|
116
|
+
<script>
|
|
117
|
+
(function () {
|
|
118
|
+
var form = document.getElementById("send-push-form");
|
|
119
|
+
if (!form) return;
|
|
120
|
+
|
|
121
|
+
var threshold = <%= @large_subscriber_threshold %>;
|
|
122
|
+
var warningTemplate = "<%= j t('admin.actions.push_notification_test.large_selection_warning',
|
|
123
|
+
count: '__N__',
|
|
124
|
+
threshold: @large_subscriber_threshold) %>";
|
|
125
|
+
|
|
126
|
+
form.addEventListener("submit", function (e) {
|
|
127
|
+
var checked = form.querySelectorAll(".subscriber-checkbox:checked").length;
|
|
128
|
+
if (checked > threshold) {
|
|
129
|
+
var msg = warningTemplate.replace("__N__", checked);
|
|
130
|
+
if (!confirm(msg)) {
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
})();
|
|
136
|
+
</script>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
# Default RailsAdmin `navigation_label`/`navigation_icon` for any
|
|
4
|
+
# `ApplicationRecord` subclass that has no explicit `RailsAdmin::ModelName`
|
|
5
|
+
# concern of its own -- see ADR 0001
|
|
6
|
+
# (vendor/external/thecore/docs/adr/0001-application-record-defaults-over-generated-concerns.md
|
|
7
|
+
# in the host app) and GitHub issue
|
|
8
|
+
# gabrieletassoni/thecore_ui_rails_admin#7.
|
|
9
|
+
#
|
|
10
|
+
# Registered into `ThecoreBackendCommons::DefaultModuleRegistry` below, so
|
|
11
|
+
# it is `include`d automatically into every model at class-definition time
|
|
12
|
+
# (via `ApplicationRecord.inherited`) instead of requiring a per-model
|
|
13
|
+
# `RailsAdmin::ModelName` concern file to be generated just to get these two
|
|
14
|
+
# mechanically-derivable values.
|
|
15
|
+
#
|
|
16
|
+
# Deliberately does NOT default any field-level configuration (`hide`,
|
|
17
|
+
# `sticky`, `configure :field`, custom `list`/`edit` blocks, ...) -- per
|
|
18
|
+
# ADR 0001's research, every existing hand-written `RailsAdmin::ModelName`
|
|
19
|
+
# concern in the `mytask` engine carries real field-level content, so only
|
|
20
|
+
# the navigation bits below are safe to default. Field-level config stays
|
|
21
|
+
# exclusively in hand-written concerns.
|
|
22
|
+
#
|
|
23
|
+
# `navigation_label` intentionally reuses the exact SAME fixed i18n key
|
|
24
|
+
# (`I18n.t('admin.registries.label')`) that the Thecore VS Code extension's
|
|
25
|
+
# `addModel` template
|
|
26
|
+
# (vendor/external/thecore_code_extension/templates/addModel/rails_admin_concern.rb
|
|
27
|
+
# in the host app) already hardcodes into every freshly generated
|
|
28
|
+
# `RailsAdmin::ModelName` concern -- so a model relying on this default
|
|
29
|
+
# looks, to an end user, exactly like one whose generated-and-never-customized
|
|
30
|
+
# concern was kept around. `DEFAULT_ICON` is a real, ready-to-use FontAwesome
|
|
31
|
+
# icon (no "TODO: customize" placeholder needed).
|
|
32
|
+
#
|
|
33
|
+
# == Why an explicit concern's own `navigation_label`/`navigation_icon` wins
|
|
34
|
+
#
|
|
35
|
+
# This module is `include`d into a model class from
|
|
36
|
+
# `ApplicationRecord.inherited`, which fires -- and so evaluates this
|
|
37
|
+
# `included do rails_admin do ... end end` block, registering RailsAdmin's
|
|
38
|
+
# *first* deferred config block for that model -- before the model class
|
|
39
|
+
# body itself runs its own `include RailsAdmin::ModelName` statement, whose
|
|
40
|
+
# block is registered *second*. RailsAdmin evaluates same-origin deferred
|
|
41
|
+
# blocks in registration order (see
|
|
42
|
+
# `RailsAdmin::Config::LazyModel#target` in the `rails_admin` gem), and
|
|
43
|
+
# `navigation_label`/`navigation_icon` are plain last-write-wins setters
|
|
44
|
+
# (see `RailsAdmin::Config::Configurable::ClassMethods#register_instance_option`),
|
|
45
|
+
# so whichever call runs last -- the hand-written concern's, when present --
|
|
46
|
+
# overrides the default set here.
|
|
47
|
+
module ThecoreUiRailsAdminDefaultNavigationConcern
|
|
48
|
+
extend ActiveSupport::Concern
|
|
49
|
+
|
|
50
|
+
DEFAULT_ICON = 'fa fa-table'.freeze
|
|
51
|
+
|
|
52
|
+
included do
|
|
53
|
+
rails_admin do
|
|
54
|
+
navigation_label I18n.t('admin.registries.label')
|
|
55
|
+
navigation_icon ThecoreUiRailsAdminDefaultNavigationConcern::DEFAULT_ICON
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Rails.application.config.to_prepare do
|
|
61
|
+
ThecoreBackendCommons::DefaultModuleRegistry.register(
|
|
62
|
+
ThecoreUiRailsAdminDefaultNavigationConcern
|
|
63
|
+
)
|
|
64
|
+
end
|
|
@@ -60,6 +60,22 @@ en:
|
|
|
60
60
|
breadcrumb: Test Push Notification
|
|
61
61
|
success: "Sent test notification to %{count} subscriber(s)"
|
|
62
62
|
error_blank_title: "Title can't be blank"
|
|
63
|
+
filter_title: "Filter Subscribers"
|
|
64
|
+
filter_placeholder: "Search by email..."
|
|
65
|
+
filter_button: "Search"
|
|
66
|
+
total_count: "%{count} active subscriber(s)"
|
|
67
|
+
disclaimer_no_filter: "There are %{count} active subscriber(s) in the system. Start typing an email address in the search field above to filter and select recipients."
|
|
68
|
+
no_results: "No active subscribers found for this email."
|
|
69
|
+
select_subscribers: "Select Subscribers"
|
|
70
|
+
message_title: "Message"
|
|
71
|
+
title_label: "Title"
|
|
72
|
+
title_placeholder: "Notification title"
|
|
73
|
+
body_label: "Body"
|
|
74
|
+
body_placeholder: "Notification body text"
|
|
75
|
+
url_label: "URL (optional)"
|
|
76
|
+
icon_label: "Icon URL (optional)"
|
|
77
|
+
send_button: "Send Test"
|
|
78
|
+
large_selection_warning: "You are about to send to %{count} subscriber(s). This may take a while. Do you want to continue?"
|
|
63
79
|
scopes:
|
|
64
80
|
_all: All
|
|
65
81
|
flash:
|
|
@@ -60,6 +60,22 @@ it:
|
|
|
60
60
|
breadcrumb: Test Notifica Push
|
|
61
61
|
success: "Notifica di test inviata a %{count} sottoscrittore/i"
|
|
62
62
|
error_blank_title: "Il titolo non può essere vuoto"
|
|
63
|
+
filter_title: "Filtra Subscriber"
|
|
64
|
+
filter_placeholder: "Cerca per email..."
|
|
65
|
+
filter_button: "Cerca"
|
|
66
|
+
total_count: "%{count} subscriber/i attivi"
|
|
67
|
+
disclaimer_no_filter: "Ci sono %{count} subscriber/i attivi nel sistema. Inizia a digitare un indirizzo email nel campo di ricerca per filtrare e selezionare i destinatari."
|
|
68
|
+
no_results: "Nessun subscriber attivo trovato per questa email."
|
|
69
|
+
select_subscribers: "Seleziona Subscriber"
|
|
70
|
+
message_title: "Messaggio"
|
|
71
|
+
title_label: "Titolo"
|
|
72
|
+
title_placeholder: "Titolo della notifica"
|
|
73
|
+
body_label: "Testo"
|
|
74
|
+
body_placeholder: "Testo del messaggio"
|
|
75
|
+
url_label: "URL (opzionale)"
|
|
76
|
+
icon_label: "URL icona (opzionale)"
|
|
77
|
+
send_button: "Invia Test"
|
|
78
|
+
large_selection_warning: "Stai per inviare a %{count} subscriber/i. L'operazione potrebbe richiedere del tempo. Vuoi continuare?"
|
|
63
79
|
scopes:
|
|
64
80
|
_all: Tutti
|
|
65
81
|
flash:
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
LARGE_SUBSCRIBER_THRESHOLD = 10
|
|
2
|
+
|
|
1
3
|
RailsAdmin::Config::Actions.add_action "push_notification_test", :base, :root do
|
|
2
4
|
show_in_sidebar true
|
|
3
5
|
show_in_navigation false
|
|
@@ -12,7 +14,16 @@ RailsAdmin::Config::Actions.add_action "push_notification_test", :base, :root do
|
|
|
12
14
|
|
|
13
15
|
controller do
|
|
14
16
|
proc do
|
|
15
|
-
@
|
|
17
|
+
@large_subscriber_threshold = LARGE_SUBSCRIBER_THRESHOLD
|
|
18
|
+
@total_count = PushSubscriber.active.count
|
|
19
|
+
@subscriber_emails = User.joins(:push_subscribers).merge(PushSubscriber.active).distinct.pluck(:email)
|
|
20
|
+
|
|
21
|
+
filter_query = params[:q].presence
|
|
22
|
+
@subscribers = if filter_query
|
|
23
|
+
PushSubscriber.active.includes(:user).joins(:user).where("users.email ILIKE ?", "%#{filter_query}%")
|
|
24
|
+
else
|
|
25
|
+
[]
|
|
26
|
+
end
|
|
16
27
|
|
|
17
28
|
if request.post?
|
|
18
29
|
params.permit!
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: thecore_ui_rails_admin
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gabriele Tassoni
|
|
@@ -51,6 +51,20 @@ dependencies:
|
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '1.18'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: thecore_backend_commons
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.4'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.4'
|
|
54
68
|
description: Holds all base dependencies and configurations to have a thecore integrated
|
|
55
69
|
with Rails Admin.
|
|
56
70
|
email:
|
|
@@ -103,6 +117,7 @@ files:
|
|
|
103
117
|
- config/initializers/assets.rb
|
|
104
118
|
- config/initializers/concern_action.rb
|
|
105
119
|
- config/initializers/concern_bulk_delete.rb
|
|
120
|
+
- config/initializers/concern_default_navigation.rb
|
|
106
121
|
- config/initializers/concern_export.rb
|
|
107
122
|
- config/initializers/concern_permission.rb
|
|
108
123
|
- config/initializers/concern_permission_role.rb
|