goodmin 0.0.1
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/MIT-LICENSE +20 -0
- data/README.md +1359 -0
- data/Rakefile +56 -0
- data/app/assets/stylesheets/goodmin/application.css +75 -0
- data/app/controllers/goodmin/application_controller.rb +43 -0
- data/app/controllers/goodmin/resource_controller.rb +235 -0
- data/app/helpers/goodmin/application_helper.rb +45 -0
- data/app/javascript/goodmin/application.js +8 -0
- data/app/javascript/goodmin/controllers/batch_actions_controller.js +101 -0
- data/app/javascript/goodmin/controllers/datetimepicker_controller.js +24 -0
- data/app/javascript/goodmin/controllers/navigation_controller.js +30 -0
- data/app/jobs/goodmin/application_job.rb +4 -0
- data/app/mailers/goodmin/application_mailer.rb +6 -0
- data/app/models/goodmin/application_record.rb +5 -0
- data/app/views/goodmin/application/welcome.html.erb +17 -0
- data/app/views/goodmin/fields/association/_form.html.erb +19 -0
- data/app/views/goodmin/fields/association/_index.html.erb +6 -0
- data/app/views/goodmin/fields/association/_show.html.erb +6 -0
- data/app/views/goodmin/fields/boolean/_form.html.erb +7 -0
- data/app/views/goodmin/fields/boolean/_index.html.erb +1 -0
- data/app/views/goodmin/fields/boolean/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date_time/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_show.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_index.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_show.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_form.html.erb +6 -0
- data/app/views/goodmin/fields/nested_has_one/_index.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_show.html.erb +1 -0
- data/app/views/goodmin/fields/number/_form.html.erb +5 -0
- data/app/views/goodmin/fields/number/_index.html.erb +1 -0
- data/app/views/goodmin/fields/number/_show.html.erb +1 -0
- data/app/views/goodmin/fields/password/_form.html.erb +5 -0
- data/app/views/goodmin/fields/password/_index.html.erb +1 -0
- data/app/views/goodmin/fields/password/_show.html.erb +1 -0
- data/app/views/goodmin/fields/select/_form.html.erb +5 -0
- data/app/views/goodmin/fields/select/_index.html.erb +1 -0
- data/app/views/goodmin/fields/select/_show.html.erb +1 -0
- data/app/views/goodmin/fields/string/_form.html.erb +5 -0
- data/app/views/goodmin/fields/string/_index.html.erb +1 -0
- data/app/views/goodmin/fields/string/_show.html.erb +1 -0
- data/app/views/goodmin/fields/text/_form.html.erb +5 -0
- data/app/views/goodmin/fields/text/_index.html.erb +1 -0
- data/app/views/goodmin/fields/text/_show.html.erb +1 -0
- data/app/views/goodmin/resource/_actions.html.erb +9 -0
- data/app/views/goodmin/resource/_batch_actions.html.erb +12 -0
- data/app/views/goodmin/resource/_breadcrumb.html.erb +33 -0
- data/app/views/goodmin/resource/_breadcrumb_actions.html.erb +41 -0
- data/app/views/goodmin/resource/_button_actions.html.erb +3 -0
- data/app/views/goodmin/resource/_errors.html.erb +9 -0
- data/app/views/goodmin/resource/_export_actions.html.erb +15 -0
- data/app/views/goodmin/resource/_filters.html.erb +22 -0
- data/app/views/goodmin/resource/_form.html.erb +26 -0
- data/app/views/goodmin/resource/_pagination.html.erb +40 -0
- data/app/views/goodmin/resource/_scopes.html.erb +14 -0
- data/app/views/goodmin/resource/_table.html.erb +45 -0
- data/app/views/goodmin/resource/columns/_actions.html.erb +28 -0
- data/app/views/goodmin/resource/edit.html.erb +5 -0
- data/app/views/goodmin/resource/index.csv.csvbuilder +5 -0
- data/app/views/goodmin/resource/index.html.erb +10 -0
- data/app/views/goodmin/resource/index.json.jbuilder +3 -0
- data/app/views/goodmin/resource/new.html.erb +5 -0
- data/app/views/goodmin/resource/show.html.erb +11 -0
- data/app/views/goodmin/resource/show.json.jbuilder +1 -0
- data/app/views/goodmin/sessions/new.html.erb +11 -0
- data/app/views/goodmin/shared/_navigation.html.erb +0 -0
- data/app/views/goodmin/shared/_navigation_aside.html.erb +7 -0
- data/app/views/layouts/goodmin/_content.html.erb +13 -0
- data/app/views/layouts/goodmin/_layout.html.erb +22 -0
- data/app/views/layouts/goodmin/application.html.erb +28 -0
- data/app/views/layouts/goodmin/login.html.erb +18 -0
- data/config/importmap.rb +5 -0
- data/config/locales/en.yml +49 -0
- data/config/locales/pl-BR.yml +49 -0
- data/config/locales/pt-BR.yml +49 -0
- data/config/locales/sv.yml +49 -0
- data/config/routes.rb +3 -0
- data/lib/generators/goodmin/authentication/authentication_generator.rb +41 -0
- data/lib/generators/goodmin/authentication/templates/sessions_controller.rb +9 -0
- data/lib/generators/goodmin/install/install_generator.rb +41 -0
- data/lib/generators/goodmin/policy/policy_generator.rb +7 -0
- data/lib/generators/goodmin/policy/templates/policy.rb +23 -0
- data/lib/generators/goodmin/resource/resource_generator.rb +31 -0
- data/lib/generators/goodmin/resource/templates/resource.rb +25 -0
- data/lib/generators/goodmin/resource/templates/resource_controller.rb +9 -0
- data/lib/generators/goodmin/resource/templates/resource_model.rb +4 -0
- data/lib/generators/goodmin/resource/templates/resource_service.rb +23 -0
- data/lib/goodmin/authentication/sessions_controller.rb +46 -0
- data/lib/goodmin/authentication/user.rb +27 -0
- data/lib/goodmin/authentication.rb +35 -0
- data/lib/goodmin/authorization/policy.rb +41 -0
- data/lib/goodmin/authorization.rb +69 -0
- data/lib/goodmin/engine.rb +30 -0
- data/lib/goodmin/fields/association.rb +62 -0
- data/lib/goodmin/fields/base.rb +57 -0
- data/lib/goodmin/fields/boolean.rb +6 -0
- data/lib/goodmin/fields/date.rb +6 -0
- data/lib/goodmin/fields/date_time.rb +6 -0
- data/lib/goodmin/fields/enum.rb +15 -0
- data/lib/goodmin/fields/nested_has_one.rb +41 -0
- data/lib/goodmin/fields/number.rb +6 -0
- data/lib/goodmin/fields/password.rb +6 -0
- data/lib/goodmin/fields/select.rb +19 -0
- data/lib/goodmin/fields/string.rb +6 -0
- data/lib/goodmin/fields/text.rb +6 -0
- data/lib/goodmin/generators/base.rb +49 -0
- data/lib/goodmin/generators/named_base.rb +31 -0
- data/lib/goodmin/helpers/application.rb +47 -0
- data/lib/goodmin/helpers/batch_actions.rb +21 -0
- data/lib/goodmin/helpers/filters.rb +123 -0
- data/lib/goodmin/helpers/forms.rb +42 -0
- data/lib/goodmin/helpers/navigation.rb +52 -0
- data/lib/goodmin/helpers/tables.rb +25 -0
- data/lib/goodmin/helpers/translations.rb +19 -0
- data/lib/goodmin/paginator.rb +55 -0
- data/lib/goodmin/resolver.rb +141 -0
- data/lib/goodmin/resources/attribute.rb +46 -0
- data/lib/goodmin/resources/form_builder.rb +96 -0
- data/lib/goodmin/resources/form_component.rb +65 -0
- data/lib/goodmin/resources/form_components/col.rb +33 -0
- data/lib/goodmin/resources/form_components/row.rb +25 -0
- data/lib/goodmin/resources/form_components/section.rb +51 -0
- data/lib/goodmin/resources/form_components/tab.rb +49 -0
- data/lib/goodmin/resources/resource/associations.rb +23 -0
- data/lib/goodmin/resources/resource/batch_actions.rb +56 -0
- data/lib/goodmin/resources/resource/filters.rb +44 -0
- data/lib/goodmin/resources/resource/ordering.rb +41 -0
- data/lib/goodmin/resources/resource/pagination.rb +22 -0
- data/lib/goodmin/resources/resource/scopes.rb +61 -0
- data/lib/goodmin/resources/resource.rb +199 -0
- data/lib/goodmin/resources/resource_controller/batch_actions.rb +49 -0
- data/lib/goodmin/resources/resource_service/associations.rb +23 -0
- data/lib/goodmin/resources/resource_service/batch_actions.rb +52 -0
- data/lib/goodmin/resources/resource_service/filters.rb +44 -0
- data/lib/goodmin/resources/resource_service/ordering.rb +41 -0
- data/lib/goodmin/resources/resource_service/pagination.rb +22 -0
- data/lib/goodmin/resources/resource_service/scopes.rb +61 -0
- data/lib/goodmin/resources/resource_service.rb +199 -0
- data/lib/goodmin/service_locator.rb +25 -0
- data/lib/goodmin/version.rb +3 -0
- data/lib/goodmin.rb +44 -0
- data/lib/tasks/goodmin_tasks.rake +4 -0
- metadata +461 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<div class="form-group">
|
|
2
|
+
<div class="form-check">
|
|
3
|
+
<%= f.check_box field.attribute, class: "form-check-input" %>
|
|
4
|
+
<%= f.label field.attribute, class: "form-check-label" %>
|
|
5
|
+
</div>
|
|
6
|
+
<%= content_tag(:p, field.hint, class: "help-block") if field.hint.present? %>
|
|
7
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= t(field.value.to_s) %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= t(field.value.to_s) %>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<% value = field.value.try(:strftime, translate_scoped("datetimepickers.datepicker")) %>
|
|
2
|
+
<div class="form-group">
|
|
3
|
+
<%= f.label field.attribute %>
|
|
4
|
+
<%= f.text_field field.attribute, class: "form-control", value: value, data: { behavior: "datepicker" } %>
|
|
5
|
+
<%= content_tag(:p, field.hint, class: "help-block") if field.hint.present? %>
|
|
6
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= l(field.value, format: :long) if field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= l(field.value, format: :long) if field.value %>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<% value = field.value.try(:strftime, translate_scoped("datetimepickers.datetimepicker")) %>
|
|
2
|
+
<div class="form-group">
|
|
3
|
+
<%= f.label field.attribute %>
|
|
4
|
+
<%= f.text_field field.attribute, class: "form-control", value: value, data: { behavior: "datetimepicker" } %>
|
|
5
|
+
<%= content_tag(:p, field.hint, class: "help-block") if field.hint.present? %>
|
|
6
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= l(field.value, format: :long) if field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= l(field.value, format: :long) if field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value&.humanize %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value&.humanize %>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<%= f.fields_for field.attribute, field.associated_record do |nested_f| %>
|
|
2
|
+
<fieldset>
|
|
3
|
+
<legend><%= field.attribute.to_s.humanize %></legend>
|
|
4
|
+
<%= render_form_nodes_for(field.nested_form_nodes, nested_f, record: field.associated_record, resource_service: field.associated_service) %>
|
|
5
|
+
</fieldset>
|
|
6
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= "•" * 8 if field.value.present? %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= "•" * 8 if field.value.present? %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= field.value %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<% if @resource_service.include_batch_actions? %>
|
|
2
|
+
<%= link_to translate_scoped("batch_actions.buttons.select_all"), "#", class: "btn btn-default",
|
|
3
|
+
data: { batch_actions_target: "selectAll", action: "click->batch-actions#toggle" } %>
|
|
4
|
+
<%= link_to translate_scoped("batch_actions.buttons.deselect_all"), "#", class: "btn btn-default hidden",
|
|
5
|
+
data: { batch_actions_target: "selectNone", action: "click->batch-actions#toggle" } %>
|
|
6
|
+
|
|
7
|
+
<div class="btn-group">
|
|
8
|
+
<% @resource_service.batch_action_map.each do |name, options| %>
|
|
9
|
+
<%= batch_action_link(name, options) %>
|
|
10
|
+
<% end %>
|
|
11
|
+
</div>
|
|
12
|
+
<% end %>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<div id="breadcrumb">
|
|
2
|
+
<ol class="breadcrumb">
|
|
3
|
+
<% if @resource_parents %>
|
|
4
|
+
<% @resource_parents.each do |parent| %>
|
|
5
|
+
<li>
|
|
6
|
+
<%= link_to parent.class.model_name.human(count: 2), parent.class %>
|
|
7
|
+
</li>
|
|
8
|
+
<li>
|
|
9
|
+
<%= link_to resource_display_name(parent), parent %>
|
|
10
|
+
</li>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% if action_name == "index" %>
|
|
14
|
+
<li class="active">
|
|
15
|
+
<%= @resource_class.model_name.human(count: 2) %>
|
|
16
|
+
</li>
|
|
17
|
+
<% else %>
|
|
18
|
+
<li>
|
|
19
|
+
<%= link_to @resource_class.model_name.human(count: 2), [*@resource_parents, @resource_class] %>
|
|
20
|
+
</li>
|
|
21
|
+
<li class="active">
|
|
22
|
+
<% if @resource.new_record? %>
|
|
23
|
+
<%= t("helpers.submit.create", model: @resource_class.model_name.human) %>
|
|
24
|
+
<% else %>
|
|
25
|
+
<%= @resource_service.display_name(@resource) %>
|
|
26
|
+
<% end %>
|
|
27
|
+
</li>
|
|
28
|
+
<% if @resource.persisted? %>
|
|
29
|
+
<%= render partial: "breadcrumb_actions" %>
|
|
30
|
+
<% end %>
|
|
31
|
+
<% end %>
|
|
32
|
+
</ol>
|
|
33
|
+
</div>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<li class="dropdown pull-right">
|
|
2
|
+
<a href="#" data-toggle="dropdown">
|
|
3
|
+
<%= translate_scoped("actions.label") %> <span class="caret"></span>
|
|
4
|
+
</a>
|
|
5
|
+
<ul class="dropdown-menu">
|
|
6
|
+
<% if policy(@resource).show? && action_name != "show" %>
|
|
7
|
+
<li>
|
|
8
|
+
<%= link_to translate_scoped("actions.show"), [*@resource_parents, @resource] %>
|
|
9
|
+
</li>
|
|
10
|
+
<% end %>
|
|
11
|
+
<% if policy(@resource).edit? && action_name != "edit" %>
|
|
12
|
+
<li>
|
|
13
|
+
<%= link_to translate_scoped("actions.edit"), [:edit, *@resource_parents, @resource] %>
|
|
14
|
+
</li>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% if policy(@resource).destroy? %>
|
|
17
|
+
<li>
|
|
18
|
+
<%= link_to translate_scoped("actions.destroy"), [*@resource_parents, @resource], method: :delete,
|
|
19
|
+
data: { confirm: translate_scoped("actions.confirm_message") } %>
|
|
20
|
+
</li>
|
|
21
|
+
<% end %>
|
|
22
|
+
</ul>
|
|
23
|
+
</li>
|
|
24
|
+
|
|
25
|
+
<% if @resource_service.has_many_map.present? %>
|
|
26
|
+
<li class="dropdown pull-right">
|
|
27
|
+
<a href="#" data-toggle="dropdown">
|
|
28
|
+
<%= translate_scoped("associations.label") %> <span class="caret"></span>
|
|
29
|
+
</a>
|
|
30
|
+
<ul class="dropdown-menu">
|
|
31
|
+
<% @resource_service.has_many_map.each do |name, options| %>
|
|
32
|
+
<% if policy(options[:class_name].constantize).index? %>
|
|
33
|
+
<li>
|
|
34
|
+
<%= link_to(options[:class_name].constantize.model_name.human(count: 2),
|
|
35
|
+
send("#{@resource_class.name.underscore}_#{name}_path", @resource)) %>
|
|
36
|
+
</li>
|
|
37
|
+
<% end %>
|
|
38
|
+
<% end %>
|
|
39
|
+
</ul>
|
|
40
|
+
</li>
|
|
41
|
+
<% end %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<% if @resource_service.attrs_for_export.present? %>
|
|
2
|
+
<div class="btn-group">
|
|
3
|
+
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
|
4
|
+
<%= translate_scoped("actions.export") %> <span class="caret"></span>
|
|
5
|
+
</button>
|
|
6
|
+
<ul class="dropdown-menu" role="menu">
|
|
7
|
+
<li>
|
|
8
|
+
<%= link_to "#{translate_scoped("actions.export_as")} JSON", url_for(params.to_unsafe_h.merge(only_path: true, format: "json")) %>
|
|
9
|
+
</li>
|
|
10
|
+
<li>
|
|
11
|
+
<%= link_to "#{translate_scoped("actions.export_as")} CSV", url_for(params.to_unsafe_h.merge(only_path: true, format: "csv")) %>
|
|
12
|
+
</li>
|
|
13
|
+
</ul>
|
|
14
|
+
</div>
|
|
15
|
+
<% end %>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<% if @resource_service.filter_map.present? %>
|
|
2
|
+
<div id="filters" class="panel panel-default">
|
|
3
|
+
<div class="panel-body">
|
|
4
|
+
<%= filter_form do |f| %>
|
|
5
|
+
<%= hidden_field_tag :scope, params[:scope] %>
|
|
6
|
+
<%= hidden_field_tag :order, params[:order] %>
|
|
7
|
+
|
|
8
|
+
<% @resource_service.filter_map.each do |name, options| %>
|
|
9
|
+
<%= partial_override "#{controller_path}/filters/#{name}", f: f, name: name, options: options do %>
|
|
10
|
+
<%= f.filter_field(name, options) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
13
|
+
|
|
14
|
+
<div class="form-group pull-right">
|
|
15
|
+
<label class="control-label"> </label><br>
|
|
16
|
+
<%= f.apply_filters_button %>
|
|
17
|
+
<%= f.clear_filters_button %>
|
|
18
|
+
</div>
|
|
19
|
+
<% end %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<% end %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<% form_tabs = @resource_service.form_tabs %>
|
|
2
|
+
<% if form_tabs.any? %>
|
|
3
|
+
<% active_tab = form_tabs.find { |t| t.key == params[:tab] } || form_tabs.first %>
|
|
4
|
+
<div class="row">
|
|
5
|
+
<div class="col-md-2">
|
|
6
|
+
<ul class="nav nav-pills nav-stacked">
|
|
7
|
+
<% form_tabs.each do |tab| %>
|
|
8
|
+
<li class="<%= "active" if tab == active_tab %>">
|
|
9
|
+
<%= link_to tab.title, request.path + "?tab=#{CGI.escape(tab.key)}" %>
|
|
10
|
+
</li>
|
|
11
|
+
<% end %>
|
|
12
|
+
</ul>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="col-md-10">
|
|
15
|
+
<%= form_for @resource do |f| %>
|
|
16
|
+
<%= render_form_nodes(active_tab.children, f) %>
|
|
17
|
+
<%= f.submit class: "btn btn-primary" %>
|
|
18
|
+
<% end %>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<% else %>
|
|
22
|
+
<%= form_for @resource do |f| %>
|
|
23
|
+
<%= render_form_nodes(@resource_service.form_nodes, f) %>
|
|
24
|
+
<%= f.submit class: "btn btn-primary" %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<% end %>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<div class="pull-left">
|
|
2
|
+
<% if @resource_service.paginator.total_pages > 1 %>
|
|
3
|
+
<nav>
|
|
4
|
+
<ul class="pagination">
|
|
5
|
+
<% unless @resource_service.paginator.pages.first == 1 && @resource_service.paginator.current_page == @resource_service.paginator.pages.first %>
|
|
6
|
+
<li><%= link_to translate_scoped("pagination.first"), params.to_unsafe_h.merge(page: 1) %></li>
|
|
7
|
+
<li><%= link_to "«", params.to_unsafe_h.merge(page: @resource_service.paginator.current_page - 1) %></li>
|
|
8
|
+
<% end %>
|
|
9
|
+
<% unless @resource_service.paginator.pages.first == 1 %>
|
|
10
|
+
<li class="disabled"><%= link_to "…" %></li>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% @resource_service.paginator.pages.each do |page| %>
|
|
13
|
+
<li class="<%= "active" if page == @resource_service.paginator.current_page %>">
|
|
14
|
+
<%= link_to page, params.to_unsafe_h.merge(page: page) %>
|
|
15
|
+
</li>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% unless @resource_service.paginator.pages.last == @resource_service.paginator.total_pages %>
|
|
18
|
+
<li class="disabled"><%= link_to "…" %></li>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% unless @resource_service.paginator.pages.last == @resource_service.paginator.total_pages && @resource_service.paginator.current_page == @resource_service.paginator.pages.last %>
|
|
21
|
+
<li><%= link_to "»", params.to_unsafe_h.merge(page: @resource_service.paginator.current_page + 1) %></li>
|
|
22
|
+
<li><%= link_to translate_scoped("pagination.last"), params.to_unsafe_h.merge(page: @resource_service.paginator.total_pages) %></li>
|
|
23
|
+
<% end %>
|
|
24
|
+
</ul>
|
|
25
|
+
</nav>
|
|
26
|
+
<% end %>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="pagination-entries pull-right hidden-xs">
|
|
29
|
+
<% if @resources.length == 0 %>
|
|
30
|
+
<%= translate_scoped("pagination.entries.zero",
|
|
31
|
+
resource: @resource_class.model_name.human(count: @resources.length).downcase
|
|
32
|
+
) %>
|
|
33
|
+
<% else %>
|
|
34
|
+
<%= translate_scoped("pagination.entries.other",
|
|
35
|
+
resource: @resource_class.model_name.human(count: @resources.length).downcase,
|
|
36
|
+
count: @resources.length,
|
|
37
|
+
total: @resource_service.paginator.total_resources
|
|
38
|
+
) %>
|
|
39
|
+
<% end %>
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<% unless @resource_service.scope_map.empty? %>
|
|
2
|
+
<div id="scopes">
|
|
3
|
+
<ul class="nav nav-tabs">
|
|
4
|
+
<% @resource_service.scope_map.each do |name, options| %>
|
|
5
|
+
<li class="<%= "active" if @resource_service.scoped_by?(name) %>">
|
|
6
|
+
<%= link_to url_for(params.to_unsafe_h.merge(scope: name, only_path: true).except(:page)) do %>
|
|
7
|
+
<%= translate_scoped("scopes.labels.#{name.to_s.underscore}", default: name.to_s.titleize) %>
|
|
8
|
+
<span class="text-muted"> (<%= @resource_service.scope_count(name) %>)</span>
|
|
9
|
+
<% end %>
|
|
10
|
+
</li>
|
|
11
|
+
<% end %>
|
|
12
|
+
</ul>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<div id="table" class="table-responsive">
|
|
2
|
+
<table class="table table-bordered table-hover">
|
|
3
|
+
<caption class="hide">
|
|
4
|
+
<%= @resource_class.model_name.human(count: 2) %>
|
|
5
|
+
</caption>
|
|
6
|
+
<thead>
|
|
7
|
+
<tr>
|
|
8
|
+
<% if @resource_service.include_batch_actions? %>
|
|
9
|
+
<th></th>
|
|
10
|
+
<% end %>
|
|
11
|
+
<% @resource_service.attrs_for_index.each do |attribute| %>
|
|
12
|
+
<th class="column-<%= attribute.name %>">
|
|
13
|
+
<%= column_header attribute %>
|
|
14
|
+
</th>
|
|
15
|
+
<% end %>
|
|
16
|
+
<th></th>
|
|
17
|
+
</tr>
|
|
18
|
+
</thead>
|
|
19
|
+
<tbody>
|
|
20
|
+
<% @resources.each do |resource| %>
|
|
21
|
+
<tr data-resource-id="<%= resource.id %>" class="<%= "highlight" if flash[:updated_ids] && flash[:updated_ids].include?(resource.id) %>">
|
|
22
|
+
<% if @resource_service.include_batch_actions? %>
|
|
23
|
+
<td align="center"
|
|
24
|
+
data-batch-actions-target="checkboxContainer"
|
|
25
|
+
data-action="click->batch-actions#containerClick">
|
|
26
|
+
<%= check_box_tag "batch_action[items][#{resource.id}]", nil, nil,
|
|
27
|
+
data: { batch_actions_target: "checkbox", action: "change->batch-actions#checkboxChange" } %>
|
|
28
|
+
</td>
|
|
29
|
+
<% end %>
|
|
30
|
+
<% @resource_service.attrs_for_index.each do |attribute| %>
|
|
31
|
+
<td>
|
|
32
|
+
<% field = attribute.to_field(record: resource, resource_service: @resource_service) %>
|
|
33
|
+
<%= partial_override "#{controller_path}/columns/#{attribute.name}", resource: resource do %>
|
|
34
|
+
<%= render partial: field.class.partial_index, locals: { field: field } %>
|
|
35
|
+
<% end %>
|
|
36
|
+
</td>
|
|
37
|
+
<% end %>
|
|
38
|
+
<td>
|
|
39
|
+
<%= render partial: "#{controller_path}/columns/actions", locals: { resource: resource } %>
|
|
40
|
+
</td>
|
|
41
|
+
</tr>
|
|
42
|
+
<% end %>
|
|
43
|
+
</tbody>
|
|
44
|
+
</table>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<div class="btn-group btn-group-sm pull-right">
|
|
2
|
+
<% if policy(resource).show? %>
|
|
3
|
+
<%= link_to(
|
|
4
|
+
translate_scoped("actions.show"),
|
|
5
|
+
[*@resource_parents, resource],
|
|
6
|
+
class: "btn btn-default",
|
|
7
|
+
title: translate_scoped("actions.show_title", resource: resource)
|
|
8
|
+
) %>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% if policy(resource).edit? %>
|
|
11
|
+
<%= link_to(
|
|
12
|
+
translate_scoped("actions.edit"),
|
|
13
|
+
[:edit, *@resource_parents, resource],
|
|
14
|
+
class: "btn btn-default",
|
|
15
|
+
title: translate_scoped("actions.edit_title", resource: resource)
|
|
16
|
+
) %>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% if policy(resource).destroy? %>
|
|
19
|
+
<%= link_to(
|
|
20
|
+
translate_scoped("actions.destroy"),
|
|
21
|
+
[*@resource_parents, resource],
|
|
22
|
+
method: :delete,
|
|
23
|
+
class: "btn btn-default",
|
|
24
|
+
title: translate_scoped("actions.destroy_title", resource: resource),
|
|
25
|
+
data: { confirm: translate_scoped("actions.confirm_message") }
|
|
26
|
+
) %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%= render partial: "breadcrumb" %>
|
|
2
|
+
<%= render partial: "scopes" %>
|
|
3
|
+
<%= render partial: "filters" %>
|
|
4
|
+
|
|
5
|
+
<div data-controller="batch-actions">
|
|
6
|
+
<%= render partial: "actions" %>
|
|
7
|
+
<%= render partial: "table" %>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<%= render partial: "pagination" %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<%= render partial: "breadcrumb" %>
|
|
2
|
+
|
|
3
|
+
<table class="table">
|
|
4
|
+
<% @resource_service.attrs_for_show.each do |attribute| %>
|
|
5
|
+
<% field = attribute.to_field(record: @resource, resource_service: @resource_service) %>
|
|
6
|
+
<tr>
|
|
7
|
+
<th><%= @resource_class.human_attribute_name(attribute.name) %></th>
|
|
8
|
+
<td><%= render partial: field.class.partial_show, locals: { field: field } %></td>
|
|
9
|
+
</tr>
|
|
10
|
+
<% end %>
|
|
11
|
+
</table>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.extract! @resource, *@resource_service.attrs_for_export.map(&:name)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<%= form_for(@admin_user, url: session_path) do |f| %>
|
|
2
|
+
<div class="form-group">
|
|
3
|
+
<%= f.label @admin_user.class.login_column %>
|
|
4
|
+
<%= f.text_field @admin_user.class.login_column, class: "form-control" %>
|
|
5
|
+
</div>
|
|
6
|
+
<div class="form-group">
|
|
7
|
+
<%= f.label :password %>
|
|
8
|
+
<%= f.password_field :password, class: "form-control" %>
|
|
9
|
+
</div>
|
|
10
|
+
<%= f.submit translate_scoped("sessions.sign_in"), class: "btn btn-block btn-primary" %>
|
|
11
|
+
<% end %>
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title><%= t("goodmin.title") %></title>
|
|
5
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
|
6
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css">
|
|
7
|
+
<%= stylesheet_link_tag "goodmin/application", media: "all" %>
|
|
8
|
+
|
|
9
|
+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
10
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
|
11
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
|
|
12
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
|
|
13
|
+
<%= javascript_importmap_tags "goodmin/application", importmap: Goodmin.importmap %>
|
|
14
|
+
|
|
15
|
+
<%= csrf_meta_tags %>
|
|
16
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
17
|
+
<%= yield :head %>
|
|
18
|
+
</head>
|
|
19
|
+
<body data-controller="navigation">
|
|
20
|
+
<%= yield :body %>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<% content_for :body do %>
|
|
2
|
+
<nav class="navbar navbar-default navbar-static-top" role="navigation">
|
|
3
|
+
<div class="container">
|
|
4
|
+
<div class="navbar-header">
|
|
5
|
+
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#goodmin-navbar-collapse" aria-expanded="false">
|
|
6
|
+
<span class="sr-only">Toggle navigation</span>
|
|
7
|
+
<span class="icon-bar"></span>
|
|
8
|
+
<span class="icon-bar"></span>
|
|
9
|
+
<span class="icon-bar"></span>
|
|
10
|
+
</button>
|
|
11
|
+
<%= link_to t("goodmin.title"), root_path, class: "navbar-brand" %>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="collapse navbar-collapse" id="goodmin-navbar-collapse">
|
|
14
|
+
<ul class="nav navbar-nav">
|
|
15
|
+
<%= render 'goodmin/shared/navigation' %>
|
|
16
|
+
</ul>
|
|
17
|
+
<ul class="nav navbar-nav navbar-right">
|
|
18
|
+
<%= render 'goodmin/shared/navigation_aside' %>
|
|
19
|
+
</ul>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</nav>
|
|
23
|
+
<div class="container">
|
|
24
|
+
<%= render "layouts/goodmin/content" %>
|
|
25
|
+
</div>
|
|
26
|
+
<% end %>
|
|
27
|
+
|
|
28
|
+
<%= render "layouts/goodmin/layout" %>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<% content_for :body do %>
|
|
2
|
+
<div id="login" class="container">
|
|
3
|
+
<div class="row">
|
|
4
|
+
<div class="col-md-4 col-md-offset-4">
|
|
5
|
+
<div class="panel panel-default">
|
|
6
|
+
<div class="panel-heading">
|
|
7
|
+
<h3 class="panel-title"><%= t("goodmin.title") %></h3>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="panel-body">
|
|
10
|
+
<%= render "layouts/goodmin/content" %>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
<% end %>
|
|
17
|
+
|
|
18
|
+
<%= render "layouts/goodmin/layout" %>
|
data/config/importmap.rb
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
|
|
2
|
+
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
|
|
3
|
+
|
|
4
|
+
pin "goodmin/application", to: "goodmin/application.js", preload: true
|
|
5
|
+
pin_all_from Goodmin::Engine.root.join("app/javascript/goodmin/controllers"), under: "controllers", to: "goodmin/controllers"
|