madmin 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -0
- data/app/controllers/madmin/base_controller.rb +0 -5
- data/app/controllers/madmin/resource_controller.rb +20 -1
- data/app/helpers/madmin/application_helper.rb +4 -0
- data/app/helpers/madmin/nav_helper.rb +30 -0
- data/app/helpers/madmin/sort_helper.rb +3 -2
- data/app/views/layouts/madmin/application.html.erb +5 -5
- data/app/views/madmin/application/_form.html.erb +6 -8
- data/app/views/madmin/application/_javascript.html.erb +34 -3
- data/app/views/madmin/application/_navigation.html.erb +31 -5
- data/app/views/madmin/application/edit.html.erb +5 -1
- data/app/views/madmin/application/index.html.erb +34 -22
- data/app/views/madmin/application/new.html.erb +5 -1
- data/app/views/madmin/application/show.html.erb +24 -17
- data/app/views/madmin/fields/attachment/_form.html.erb +3 -1
- data/app/views/madmin/fields/attachment/_show.html.erb +7 -1
- data/app/views/madmin/fields/attachments/_form.html.erb +3 -1
- data/app/views/madmin/fields/attachments/_show.html.erb +7 -3
- data/app/views/madmin/fields/belongs_to/_form.html.erb +4 -2
- data/app/views/madmin/fields/belongs_to/_show.html.erb +1 -1
- data/app/views/madmin/fields/boolean/_form.html.erb +3 -1
- data/app/views/madmin/fields/date/_form.html.erb +3 -1
- data/app/views/madmin/fields/date_time/_form.html.erb +3 -1
- data/app/views/madmin/fields/decimal/_form.html.erb +3 -1
- data/app/views/madmin/fields/enum/_form.html.erb +4 -2
- data/app/views/madmin/fields/float/_form.html.erb +3 -1
- data/app/views/madmin/fields/has_many/_form.html.erb +4 -2
- data/app/views/madmin/fields/has_many/_show.html.erb +1 -1
- data/app/views/madmin/fields/has_one/_form.html.erb +3 -2
- data/app/views/madmin/fields/integer/_form.html.erb +3 -1
- data/app/views/madmin/fields/json/_form.html.erb +3 -1
- data/app/views/madmin/fields/nested_has_many/_form.html.erb +3 -1
- data/app/views/madmin/fields/nested_has_many/_show.html.erb +1 -1
- data/app/views/madmin/fields/password/_form.html.erb +3 -1
- data/app/views/madmin/fields/polymorphic/_form.html.erb +3 -1
- data/app/views/madmin/fields/polymorphic/_show.html.erb +1 -1
- data/app/views/madmin/fields/rich_text/_form.html.erb +3 -1
- data/app/views/madmin/fields/string/_form.html.erb +3 -1
- data/app/views/madmin/fields/text/_form.html.erb +3 -1
- data/app/views/madmin/fields/time/_form.html.erb +3 -1
- data/app/views/madmin/shared/_label.html.erb +4 -0
- data/lib/generators/madmin/field/field_generator.rb +31 -0
- data/lib/generators/madmin/field/templates/_form.html.erb +2 -0
- data/lib/generators/madmin/field/templates/_index.html.erb +1 -0
- data/lib/generators/madmin/field/templates/_show.html.erb +1 -0
- data/lib/generators/madmin/field/templates/field.rb.tt +26 -0
- data/lib/generators/madmin/install/install_generator.rb +6 -1
- data/lib/generators/madmin/install/templates/routes.rb.tt +3 -0
- data/lib/generators/madmin/resource/resource_generator.rb +1 -1
- data/lib/generators/madmin/resource/templates/controller.rb.tt +6 -0
- data/lib/madmin/engine.rb +1 -1
- data/lib/madmin/field.rb +4 -0
- data/lib/madmin/fields/belongs_to.rb +9 -6
- data/lib/madmin/fields/has_many.rb +10 -6
- data/lib/madmin/fields/string.rb +3 -0
- data/lib/madmin/fields/text.rb +3 -0
- data/lib/madmin/generator_helpers.rb +22 -4
- data/lib/madmin/resource.rb +19 -13
- data/lib/madmin/search.rb +60 -0
- data/lib/madmin/version.rb +1 -1
- data/lib/madmin.rb +19 -5
- metadata +14 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f3bd8e986e4859620b06401c531dc24ca84bb02e4e2284a34918b5a088c126c
|
4
|
+
data.tar.gz: 9bf59b4f93849feda832005caa748e02b4227ea2552cd6e94264d3b7d170f5a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3181e8f05aad7af36b905a4a04ffb2ddd63419b347e699b0b9ea6d8d2fb9a880f12ebbd7b12d05770e02dc7508e4789a1cb8250b11b6eed26878b6ef71d7fc1b
|
7
|
+
data.tar.gz: '0019a725b02cde9e007190917381da718a139662d1d9094a0e49ccc69b799437865a4170658b99492947ce1d6d2ae04f71dde97886212a8dd728c3a9aa2275f3'
|
data/README.md
CHANGED
@@ -79,6 +79,31 @@ rails generate madmin:views:index Book
|
|
79
79
|
# -> app/views/madmin/books/index.html.erb
|
80
80
|
```
|
81
81
|
|
82
|
+
## Custom Fields
|
83
|
+
|
84
|
+
You can generate a custom field with:
|
85
|
+
|
86
|
+
```bash
|
87
|
+
rails g madmin:field Custom
|
88
|
+
```
|
89
|
+
|
90
|
+
This will create a `CustomField` class in `app/madmin/fields/custom_field.rb`
|
91
|
+
And the related views:
|
92
|
+
|
93
|
+
```bash
|
94
|
+
# -> app/views/madmin/fields/custom_field/_form.html.erb
|
95
|
+
# -> app/views/madmin/fields/custom_field/_index.html.erb
|
96
|
+
# -> app/views/madmin/fields/custom_field/_show.html.erb
|
97
|
+
```
|
98
|
+
|
99
|
+
You can then use this field on our resource:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
class PostResource < Madmin::Resource
|
103
|
+
attribute :title, field: CustomField
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
82
107
|
## Authentication
|
83
108
|
|
84
109
|
You can use a couple of strategies to authenticate users who are trying to
|
@@ -4,8 +4,21 @@ module Madmin
|
|
4
4
|
|
5
5
|
before_action :set_record, except: [:index, :new, :create]
|
6
6
|
|
7
|
+
# Assign current_user for paper_trail gem
|
8
|
+
before_action :set_paper_trail_whodunnit, if: -> { respond_to?(:set_paper_trail_whodunnit, true) }
|
9
|
+
|
7
10
|
def index
|
8
11
|
@pagy, @records = pagy(scoped_resources)
|
12
|
+
|
13
|
+
respond_to do |format|
|
14
|
+
format.html
|
15
|
+
format.json {
|
16
|
+
render json: @records.map { |r| {name: @resource.display_name(r), id: r.id} }
|
17
|
+
}
|
18
|
+
end
|
19
|
+
rescue Pagy::OverflowError
|
20
|
+
params[:page] = 1
|
21
|
+
retry
|
9
22
|
end
|
10
23
|
|
11
24
|
def show
|
@@ -56,7 +69,9 @@ module Madmin
|
|
56
69
|
end
|
57
70
|
|
58
71
|
def scoped_resources
|
59
|
-
resource.model.send(valid_scope)
|
72
|
+
resources = resource.model.send(valid_scope)
|
73
|
+
resources = Madmin::Search.new(resources, resource, search_term).run
|
74
|
+
resources.reorder(sort_column => sort_direction)
|
60
75
|
end
|
61
76
|
|
62
77
|
def valid_scope
|
@@ -79,5 +94,9 @@ module Madmin
|
|
79
94
|
raise "Unrecognised param data: #{data.inspect}"
|
80
95
|
end
|
81
96
|
end
|
97
|
+
|
98
|
+
def search_term
|
99
|
+
@search_term ||= params[:q].to_s.strip
|
100
|
+
end
|
82
101
|
end
|
83
102
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Madmin::NavHelper
|
2
|
+
def nav_link_to(name = nil, options = {}, html_options = {}, &block)
|
3
|
+
if block
|
4
|
+
html_options = options
|
5
|
+
options = name
|
6
|
+
name = block
|
7
|
+
end
|
8
|
+
|
9
|
+
url = url_for(options)
|
10
|
+
starts_with = html_options.delete(:starts_with)
|
11
|
+
html_options[:class] = Array.wrap(html_options[:class])
|
12
|
+
active_class = html_options.delete(:active_class) || "active"
|
13
|
+
inactive_class = html_options.delete(:inactive_class) || ""
|
14
|
+
|
15
|
+
active = if (paths = Array.wrap(starts_with)) && paths.present?
|
16
|
+
paths.any? { |path| request.path.start_with?(path) }
|
17
|
+
else
|
18
|
+
request.path == url
|
19
|
+
end
|
20
|
+
|
21
|
+
classes = active ? active_class : inactive_class
|
22
|
+
html_options[:class] << classes unless classes.empty?
|
23
|
+
|
24
|
+
html_options.except!(:class) if html_options[:class].empty?
|
25
|
+
|
26
|
+
return link_to url, html_options, &block if block
|
27
|
+
|
28
|
+
link_to name, url, html_options
|
29
|
+
end
|
30
|
+
end
|
@@ -2,8 +2,9 @@ module Madmin
|
|
2
2
|
module SortHelper
|
3
3
|
def sortable(column, title, options = {})
|
4
4
|
matching_column = (column.to_s == sort_column)
|
5
|
+
direction = sort_direction == "asc" ? "desc" : "asc"
|
5
6
|
|
6
|
-
link_to request.params.merge(sort: column, direction:
|
7
|
+
link_to request.params.merge(sort: column, direction: direction), options do
|
7
8
|
concat title
|
8
9
|
if matching_column
|
9
10
|
concat " "
|
@@ -21,7 +22,7 @@ module Madmin
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def default_sort_column
|
24
|
-
resource.try(:default_sort_column) || "created_at"
|
25
|
+
resource.try(:default_sort_column) || (["created_at", "id", "uuid"] & resource.model.column_names).first
|
25
26
|
end
|
26
27
|
|
27
28
|
def default_sort_direction
|
@@ -7,19 +7,19 @@
|
|
7
7
|
<title>
|
8
8
|
Madmin: <%= Rails.application.class %>
|
9
9
|
</title>
|
10
|
-
<link href="https://unpkg.com/tailwindcss@^2.0/dist/tailwind.min.css" rel="stylesheet" />
|
11
10
|
<link href="https://unpkg.com/@tailwindcss/forms/dist/forms.min.css" rel="stylesheet" />
|
11
|
+
<link href="https://unpkg.com/tailwindcss@^2.0/dist/tailwind.min.css" rel="stylesheet" />
|
12
12
|
<link href="https://unpkg.com/@tailwindcss/typography/dist/typography.min.css" rel="stylesheet" />
|
13
13
|
<%= csrf_meta_tags %>
|
14
14
|
|
15
15
|
<%= render "javascript" %>
|
16
16
|
</head>
|
17
|
-
<body class="
|
18
|
-
<div class="flex w-full
|
19
|
-
<div id="sidebar" class="w-64 flex-shrink-0">
|
17
|
+
<body class="min-h-screen">
|
18
|
+
<div class="md:flex w-full min-h-screen">
|
19
|
+
<div id="sidebar" class="md:w-64 p-4 flex-shrink-0 border-r">
|
20
20
|
<%= render "navigation" -%>
|
21
21
|
</div>
|
22
|
-
<main class="
|
22
|
+
<main class="flex-grow p-4" role="main">
|
23
23
|
<%#= render "flashes" -%>
|
24
24
|
<%= yield %>
|
25
25
|
</main>
|
@@ -9,15 +9,13 @@
|
|
9
9
|
</div>
|
10
10
|
<% end %>
|
11
11
|
|
12
|
-
<% resource.attributes.each do |attribute| %>
|
13
|
-
<% next if attribute
|
14
|
-
<% next unless attribute
|
15
|
-
<% next unless attribute
|
12
|
+
<% resource.attributes.values.each do |attribute| %>
|
13
|
+
<% next if attribute.field.nil? %>
|
14
|
+
<% next unless attribute.field.visible?(action_name) %>
|
15
|
+
<% next unless attribute.field.visible?(:form) %>
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
<div class="mb-4 flex">
|
20
|
-
<%= render partial: field.to_partial_path("form"), locals: { field: field, record: record, form: form, resource: resource } %>
|
17
|
+
<div class="mb-4 md:flex">
|
18
|
+
<%= render partial: attribute.field.to_partial_path("form"), locals: { field: attribute.field, record: record, form: form, resource: resource } %>
|
21
19
|
</div>
|
22
20
|
<% end %>
|
23
21
|
|
@@ -1,16 +1,18 @@
|
|
1
1
|
<%= stylesheet_link_tag "https://unpkg.com/flatpickr/dist/flatpickr.min.css", "data-turbo-track": "reload" %>
|
2
2
|
<%= stylesheet_link_tag "https://unpkg.com/trix/dist/trix.css", "data-turbo-track": "reload" %>
|
3
|
-
<%= stylesheet_link_tag "https://unpkg.com/
|
3
|
+
<%= stylesheet_link_tag "https://unpkg.com/tom-select/dist/css/tom-select.min.css", "data-turbo-track": "reload" %>
|
4
4
|
|
5
5
|
<script type="module">
|
6
6
|
import { Application, Controller } from 'https://cdn.skypack.dev/stimulus'
|
7
7
|
const application = Application.start()
|
8
8
|
|
9
|
+
import { Dropdown } from "https://cdn.skypack.dev/tailwindcss-stimulus-components"
|
10
|
+
application.register("dropdown", Dropdown)
|
11
|
+
|
9
12
|
import stimulusFlatpickr from 'https://cdn.skypack.dev/stimulus-flatpickr'
|
10
13
|
application.register("flatpickr", stimulusFlatpickr)
|
11
14
|
|
12
|
-
import
|
13
|
-
application.register("slimselect", stimulusSlimselect)
|
15
|
+
import TomSelect from 'https://cdn.skypack.dev/tom-select'
|
14
16
|
|
15
17
|
import Rails from 'https://cdn.skypack.dev/@rails/ujs@<%= npm_rails_version %>'
|
16
18
|
import * as ActiveStorage from 'https://cdn.skypack.dev/@rails/activestorage@<%= npm_rails_version %>'
|
@@ -23,6 +25,35 @@
|
|
23
25
|
import * as Turbo from "https://cdn.skypack.dev/@hotwired/turbo"
|
24
26
|
|
25
27
|
(() => {
|
28
|
+
application.register('select', class extends Controller {
|
29
|
+
static values = {
|
30
|
+
options: Object,
|
31
|
+
url: String
|
32
|
+
}
|
33
|
+
|
34
|
+
connect() {
|
35
|
+
this.select = new TomSelect(this.element, {
|
36
|
+
plugins: ['remove_button'],
|
37
|
+
valueField: 'id',
|
38
|
+
labelField: 'name',
|
39
|
+
searchField: 'name',
|
40
|
+
load: (search, callback) => {
|
41
|
+
fetch(this.urlValue)
|
42
|
+
.then(response => response.json())
|
43
|
+
.then(json => {
|
44
|
+
callback(json);
|
45
|
+
}).catch(() => {
|
46
|
+
callback();
|
47
|
+
});
|
48
|
+
}
|
49
|
+
})
|
50
|
+
}
|
51
|
+
|
52
|
+
disconnect() {
|
53
|
+
this.select.destroy()
|
54
|
+
}
|
55
|
+
})
|
56
|
+
|
26
57
|
application.register('nested-form', class extends Controller {
|
27
58
|
static get targets() {
|
28
59
|
return [ "links", "template" ]
|
@@ -1,6 +1,32 @@
|
|
1
|
-
<div class="text-sm">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
<div class="flex flex-col h-full text-sm" data-controller="dropdown">
|
2
|
+
<div class="flex md:block justify-between items-center">
|
3
|
+
<div class="flex md:block items-center">
|
4
|
+
<h1 class="mr-2 md:p-2 text-xl font-semibold">Madmin</h1>
|
5
|
+
<% if main_app.respond_to?(:root_url) %>
|
6
|
+
<%= link_to main_app.root_url, class: "block p-2 rounded hover:bg-gray-200", data: { turbo: false } do %>
|
7
|
+
← Back <span class="hidden md:inline">to App</span>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<div class="-mr-2 flex items-center md:hidden">
|
13
|
+
<button data-action="click->dropdown#toggle touch->dropdown#toggle click@window->dropdown#hide touch@window#dropdown->hide" type="button" class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:bg-gray-200 focus:outline-none focus:ring-2 focus-ring-inset focus:ring-white" id="main-menu" aria-haspopup="true">
|
14
|
+
<span class="sr-only">Open main menu</span>
|
15
|
+
<!-- Heroicon name: outline/menu -->
|
16
|
+
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
17
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
18
|
+
</svg>
|
19
|
+
</button>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="hidden md:flex flex-col flex-grow justify-between" data-dropdown-target="menu">
|
24
|
+
<% Madmin.resources.each do |resource| %>
|
25
|
+
<%= nav_link_to resource.friendly_name.pluralize, resource.index_path, class: "block p-2 rounded hover:bg-gray-100", starts_with: resource.index_path, active_class: "font-bold text-black" %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<div class="mt-auto">
|
29
|
+
<%= link_to "View Madmin on GitHub", "https://github.com/excid3/madmin", target: :_blank, class: "block p-2 rounded text-gray-500 hover:bg-gray-100" %>
|
30
|
+
</div>
|
31
|
+
</div>
|
6
32
|
</div>
|
@@ -1,3 +1,7 @@
|
|
1
|
-
<h1
|
1
|
+
<h1 class="text-xl mb-4">
|
2
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path, class: "text-indigo-500" %>
|
3
|
+
/
|
4
|
+
<strong>Edit <%= link_to resource.display_name(@record), resource.show_path(@record), class: "text-indigo-500" %></strong>
|
5
|
+
</h1>
|
2
6
|
|
3
7
|
<%= render partial: "form", locals: { record: @record, resource: resource } %>
|
@@ -1,44 +1,56 @@
|
|
1
|
-
<div class="flex justify-between">
|
2
|
-
<h1><%= resource.friendly_name.pluralize %></h1>
|
3
|
-
|
1
|
+
<div class="md:flex justify-between items-center space-y-4 md:space-y-0">
|
2
|
+
<h1 class="text-xl font-semibold"><%= resource.friendly_name.pluralize %></h1>
|
3
|
+
|
4
|
+
<div class="flex-grow flex md:justify-end gap-4">
|
5
|
+
<form class="flex items-center gap-2 relative">
|
6
|
+
<%= hidden_field_tag :page, params[:page], value: 1, class: "hidden" %>
|
7
|
+
<%= search_field_tag :q, params[:q], placeholder: "Search", class: "rounded-full px-4 focus:bg-white focus:border-indigo-500" %>
|
8
|
+
<%= link_to clear_search_params, class: "absolute top-1/2 right-3 text-gray-500 bg-white transform -translate-y-1/2" do %>
|
9
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
10
|
+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
|
11
|
+
</svg>
|
12
|
+
<% end %>
|
13
|
+
</form>
|
14
|
+
|
15
|
+
<%= link_to resource.new_path, class: "bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow" do %>
|
16
|
+
New <span class="hidden md:inline"><%= resource.friendly_name %></span>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
4
19
|
</div>
|
5
20
|
|
6
|
-
<div>
|
21
|
+
<div class="mb-4">
|
7
22
|
<% if resource.scopes.any? %>
|
8
|
-
<%= link_to "All", resource.index_path %>
|
23
|
+
<%= link_to "All", resource.index_path, class: class_names("p-2 rounded", {"bg-gray-100" => params[:scope].blank?}) %>
|
9
24
|
<% end %>
|
10
25
|
|
11
26
|
<% resource.scopes.each do |scope| %>
|
12
|
-
<%= link_to scope.to_s.humanize, resource.index_path(scope: scope) %>
|
27
|
+
<%= link_to scope.to_s.humanize, resource.index_path(scope: scope), class: class_names("p-2 rounded", {"bg-gray-100" => params[:scope] == scope.to_s}) %>
|
13
28
|
<% end %>
|
14
29
|
</div>
|
15
30
|
|
16
|
-
<table class="
|
31
|
+
<table class="min-w-full divide-y divide-gray-200">
|
17
32
|
<thead>
|
18
|
-
<tr>
|
19
|
-
<% resource.attributes.each do |attribute| %>
|
20
|
-
<% next if attribute
|
21
|
-
<% next unless attribute
|
33
|
+
<tr class="border-b border-gray-200">
|
34
|
+
<% resource.attributes.values.each do |attribute| %>
|
35
|
+
<% next if attribute.field.nil? %>
|
36
|
+
<% next unless attribute.field.visible?(action_name) %>
|
22
37
|
|
23
|
-
<th><%= sortable attribute
|
38
|
+
<th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase whitespace-nowrap"><%= sortable attribute.name, attribute.name.to_s.titleize %></th>
|
24
39
|
<% end %>
|
25
|
-
<th>Actions</th>
|
40
|
+
<th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase">Actions</th>
|
26
41
|
</tr>
|
27
42
|
</thead>
|
28
43
|
|
29
|
-
<tbody>
|
44
|
+
<tbody class="text-sm divide-y">
|
30
45
|
<% @records.each do |record| %>
|
31
46
|
<tr>
|
32
|
-
<% resource.attributes.each do |attribute| %>
|
33
|
-
<% next if attribute
|
34
|
-
<% next unless attribute
|
35
|
-
|
36
|
-
<% field = attribute[:field] %>
|
37
|
-
|
38
|
-
<td><%= render partial: field.to_partial_path("index"), locals: { field: field, record: record } %></td>
|
47
|
+
<% resource.attributes.values.each do |attribute| %>
|
48
|
+
<% next if attribute.field.nil? %>
|
49
|
+
<% next unless attribute.field.visible?(action_name) %>
|
50
|
+
<td class="px-4 py-2"><%= render partial: attribute.field.to_partial_path("index"), locals: { field: attribute.field, record: record } %></td>
|
39
51
|
<% end %>
|
40
52
|
|
41
|
-
<td><%= link_to "View", resource.show_path(record) %></td>
|
53
|
+
<td class="px-4 py-2 text-center"><%= link_to "View", resource.show_path(record), class: "text-indigo-500" %></td>
|
42
54
|
</tr>
|
43
55
|
<% end %>
|
44
56
|
</tbody>
|
@@ -1,3 +1,7 @@
|
|
1
|
-
<h1
|
1
|
+
<h1 class="text-xl mb-4">
|
2
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path, class: "text-indigo-500" %>
|
3
|
+
/
|
4
|
+
<strong>New <%= resource.friendly_name %></strong>
|
5
|
+
</h1>
|
2
6
|
|
3
7
|
<%= render partial: "form", locals: { record: @record, resource: resource } %>
|
@@ -1,24 +1,31 @@
|
|
1
|
-
<div class="flex justify-between">
|
2
|
-
<h1
|
1
|
+
<div class="md:flex items-center justify-between mb-4">
|
2
|
+
<h1 class="text-xl">
|
3
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path, class: "text-indigo-500" %>
|
4
|
+
/
|
5
|
+
<%= link_to resource.display_name(@record), resource.show_path(@record), class: "text-indigo-500 font-bold" %>
|
6
|
+
</h1>
|
3
7
|
|
4
|
-
<div class="flex px-4">
|
5
|
-
|
6
|
-
|
8
|
+
<div class="flex items-center px-4">
|
9
|
+
<div class="mr-2">
|
10
|
+
<%= link_to "Edit", resource.edit_path(@record), class: "block bg-white hover:bg-gray-100 text-gray-800 font-semibold py-2 px-4 border border-gray-400 rounded shadow" %>
|
11
|
+
</div>
|
12
|
+
<%= button_to "Delete", resource.show_path(@record), method: :delete, data: { confirm: "Are you sure?" }, class: "bg-white hover:bg-gray-100 text-red-500 font-semibold py-2 px-4 border border-red-500 rounded shadow pointer-cursor" %>
|
7
13
|
</div>
|
8
14
|
</div>
|
9
15
|
|
10
|
-
|
11
|
-
<%
|
12
|
-
|
13
|
-
|
16
|
+
<div class="divide-y">
|
17
|
+
<% resource.attributes.values.each do |attribute| %>
|
18
|
+
<% next if attribute.field.nil? %>
|
19
|
+
<% next unless attribute.field.visible?(action_name) %>
|
14
20
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
<div class="px-4 py-3 md:grid md:grid-cols-4 md:gap-4 md:px-6">
|
22
|
+
<div class="text-sm font-medium text-gray-500">
|
23
|
+
<%= attribute.field.attribute_name.to_s.titleize %>
|
24
|
+
</div>
|
19
25
|
|
20
|
-
|
21
|
-
|
26
|
+
<div class="md:col-span-3">
|
27
|
+
<%= render partial: attribute.field.to_partial_path("show"), locals: { field: attribute.field, record: @record } %>
|
28
|
+
</div>
|
22
29
|
</div>
|
23
|
-
|
24
|
-
|
30
|
+
<% end %>
|
31
|
+
</div>
|