madmin 1.2.11 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/madmin_manifest.js +3 -0
- data/app/assets/stylesheets/madmin/actiontext.css +31 -0
- data/app/assets/stylesheets/madmin/application.css +88 -0
- data/app/assets/stylesheets/madmin/buttons.css +46 -0
- data/app/assets/stylesheets/madmin/forms.css +82 -0
- data/app/assets/stylesheets/madmin/pagination.css +59 -0
- data/app/assets/stylesheets/madmin/reset.css +242 -0
- data/app/assets/stylesheets/madmin/sidebar.css +80 -0
- data/app/assets/stylesheets/madmin/tables.css +56 -0
- data/app/controllers/madmin/application_controller.rb +7 -12
- data/app/controllers/madmin/base_controller.rb +1 -0
- data/app/helpers/madmin/application_helper.rb +1 -12
- data/app/helpers/madmin/sort_helper.rb +17 -1
- data/app/javascript/madmin/application.js +4 -0
- data/app/javascript/madmin/controllers/application.js +12 -0
- data/app/javascript/madmin/controllers/index.js +5 -0
- data/app/javascript/madmin/controllers/nested_form_controller.js +34 -0
- data/app/javascript/madmin/controllers/select_controller.js +32 -0
- data/app/views/layouts/madmin/application.html.erb +11 -13
- data/app/views/madmin/application/_form.html.erb +13 -12
- data/app/views/madmin/application/_javascript.html.erb +3 -136
- data/app/views/madmin/application/_navigation.html.erb +22 -27
- data/app/views/madmin/application/edit.html.erb +9 -5
- data/app/views/madmin/application/index.html.erb +37 -31
- data/app/views/madmin/application/new.html.erb +9 -5
- data/app/views/madmin/application/show.html.erb +28 -22
- data/app/views/madmin/dashboard/show.html.erb +4 -1
- data/app/views/madmin/fields/attachment/_form.html.erb +11 -4
- data/app/views/madmin/fields/attachment/_index.html.erb +5 -1
- data/app/views/madmin/fields/attachment/_show.html.erb +4 -4
- data/app/views/madmin/fields/attachments/_form.html.erb +1 -4
- data/app/views/madmin/fields/belongs_to/_form.html.erb +1 -4
- data/app/views/madmin/fields/belongs_to/_index.html.erb +2 -1
- data/app/views/madmin/fields/boolean/_form.html.erb +3 -4
- data/app/views/madmin/fields/currency/_form.html.erb +1 -0
- data/app/views/madmin/fields/currency/_index.html.erb +1 -0
- data/app/views/madmin/fields/currency/_show.html.erb +1 -0
- data/app/views/madmin/fields/date/_form.html.erb +1 -4
- data/app/views/madmin/fields/date_time/_form.html.erb +1 -4
- data/app/views/madmin/fields/decimal/_form.html.erb +1 -4
- data/app/views/madmin/fields/enum/_form.html.erb +1 -4
- data/app/views/madmin/fields/file/_form.html.erb +1 -4
- data/app/views/madmin/fields/float/_form.html.erb +1 -4
- data/app/views/madmin/fields/has_many/_form.html.erb +1 -4
- data/app/views/madmin/fields/has_one/_form.html.erb +0 -3
- data/app/views/madmin/fields/integer/_form.html.erb +1 -4
- data/app/views/madmin/fields/integer/_index.html.erb +1 -5
- data/app/views/madmin/fields/json/_form.html.erb +1 -4
- data/app/views/madmin/fields/nested_has_many/_fields.html.erb +4 -5
- data/app/views/madmin/fields/nested_has_many/_form.html.erb +0 -4
- data/app/views/madmin/fields/password/_form.html.erb +1 -4
- data/app/views/madmin/fields/polymorphic/_form.html.erb +1 -4
- data/app/views/madmin/fields/rich_text/_form.html.erb +1 -6
- data/app/views/madmin/fields/select/_form.html.erb +1 -0
- data/app/views/madmin/fields/select/_index.html.erb +1 -0
- data/app/views/madmin/fields/select/_show.html.erb +1 -0
- data/app/views/madmin/fields/string/_form.html.erb +1 -4
- data/app/views/madmin/fields/text/_form.html.erb +1 -4
- data/app/views/madmin/shared/_label.html.erb +2 -2
- data/config/importmap.rb +10 -0
- data/lib/generators/madmin/field/templates/_form.html.erb +1 -4
- data/lib/generators/madmin/install/templates/controller.rb.tt +5 -12
- data/lib/generators/madmin/resource/templates/resource.rb.tt +12 -10
- data/lib/madmin/engine.rb +20 -0
- data/lib/madmin/field.rb +17 -5
- data/lib/madmin/fields/belongs_to.rb +10 -5
- data/lib/madmin/fields/currency.rb +15 -0
- data/lib/madmin/fields/polymorphic.rb +1 -1
- data/lib/madmin/fields/select.rb +9 -0
- data/lib/madmin/menu.rb +70 -0
- data/lib/madmin/resource.rb +56 -24
- data/lib/madmin/search.rb +1 -1
- data/lib/madmin/version.rb +1 -1
- data/lib/madmin.rb +22 -1
- metadata +61 -13
- data/app/assets/config/manifest.js +0 -2
- data/app/assets/stylesheets/actiontext.scss +0 -36
- data/app/assets/stylesheets/application.css +0 -15
- data/app/views/madmin/application/_menu_resources.html.erb +0 -7
@@ -1,22 +1,17 @@
|
|
1
1
|
module Madmin
|
2
2
|
class ApplicationController < Madmin::BaseController
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
|
3
5
|
before_action :authenticate_admin_user
|
4
6
|
|
5
7
|
def authenticate_admin_user
|
6
8
|
# TODO: Add your authentication logic here
|
7
9
|
|
8
|
-
# For example,
|
9
|
-
# redirect_to "/", alert: "Not authorized." unless
|
10
|
-
end
|
11
|
-
|
12
|
-
# Authenticate with Clearance
|
13
|
-
# include Clearance::Controller
|
14
|
-
# before_action :require_login
|
10
|
+
# For example, with Rails 8 authentication
|
11
|
+
# redirect_to "/", alert: "Not authorized." unless authenticated? && Current.user.admin?
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# Authenticate with Basic Auth
|
20
|
-
# http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
|
13
|
+
# Or with Devise
|
14
|
+
# redirect_to "/", alert: "Not authorized." unless current_user&.admin?
|
15
|
+
end
|
21
16
|
end
|
22
17
|
end
|
@@ -1,18 +1,7 @@
|
|
1
1
|
module Madmin
|
2
2
|
module ApplicationHelper
|
3
3
|
include Pagy::Frontend
|
4
|
-
|
5
|
-
# Converts a Rails version to a NPM version
|
6
|
-
def npm_rails_version
|
7
|
-
version = [
|
8
|
-
Rails::VERSION::MAJOR,
|
9
|
-
Rails::VERSION::MINOR,
|
10
|
-
Rails::VERSION::TINY
|
11
|
-
].join(".")
|
12
|
-
|
13
|
-
version += "-#{Rails::VERSION::PRE}" if Rails::VERSION::PRE
|
14
|
-
version
|
15
|
-
end
|
4
|
+
include Rails.application.routes.url_helpers
|
16
5
|
|
17
6
|
def clear_search_params
|
18
7
|
resource.index_path(sort: params[:sort], direction: params[:direction])
|
@@ -8,7 +8,7 @@ module Madmin
|
|
8
8
|
concat title
|
9
9
|
if matching_column
|
10
10
|
concat " "
|
11
|
-
concat tag.
|
11
|
+
concat tag.span((sort_direction == "asc") ? asc_icon : desc_icon)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -28,5 +28,21 @@ module Madmin
|
|
28
28
|
def default_sort_direction
|
29
29
|
resource.try(:default_sort_direction) || "desc"
|
30
30
|
end
|
31
|
+
|
32
|
+
def asc_icon
|
33
|
+
<<~SVG.html_safe
|
34
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" height="1rem" width="1rem">
|
35
|
+
<path fill-rule="evenodd" d="M11.78 9.78a.75.75 0 0 1-1.06 0L8 7.06 5.28 9.78a.75.75 0 0 1-1.06-1.06l3.25-3.25a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06Z" clip-rule="evenodd" />
|
36
|
+
</svg>
|
37
|
+
SVG
|
38
|
+
end
|
39
|
+
|
40
|
+
def desc_icon
|
41
|
+
<<~SVG.html_safe
|
42
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" height="1rem" width="1rem">
|
43
|
+
<path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
44
|
+
</svg>
|
45
|
+
SVG
|
46
|
+
end
|
31
47
|
end
|
32
48
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { Application } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
const application = Application.start()
|
4
|
+
|
5
|
+
// Configure Stimulus development experience
|
6
|
+
application.debug = false
|
7
|
+
window.Stimulus = application
|
8
|
+
|
9
|
+
export { application }
|
10
|
+
|
11
|
+
import { Dropdown } from "tailwindcss-stimulus-components"
|
12
|
+
application.register("dropdown", Dropdown)
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import { application } from "controllers/application"
|
2
|
+
|
3
|
+
// Eager load all controllers defined in the import map under controllers/**/*_controller
|
4
|
+
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
|
5
|
+
eagerLoadControllersFrom("controllers", application)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static get targets() {
|
5
|
+
return [ "links", "template" ]
|
6
|
+
}
|
7
|
+
|
8
|
+
connect() {
|
9
|
+
this.wrapperClass = this.data.get("wrapperClass") || "nested-fields"
|
10
|
+
}
|
11
|
+
|
12
|
+
add_association(event) {
|
13
|
+
event.preventDefault()
|
14
|
+
|
15
|
+
var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
|
16
|
+
this.linksTarget.insertAdjacentHTML('beforebegin', content)
|
17
|
+
}
|
18
|
+
|
19
|
+
remove_association(event) {
|
20
|
+
event.preventDefault()
|
21
|
+
|
22
|
+
let wrapper = event.target.closest("." + this.wrapperClass)
|
23
|
+
|
24
|
+
// New records are simply removed from the page
|
25
|
+
if (wrapper.dataset.newRecord == "true") {
|
26
|
+
wrapper.remove()
|
27
|
+
|
28
|
+
// Existing records are hidden and flagged for deletion
|
29
|
+
} else {
|
30
|
+
wrapper.querySelector("input[name*='_destroy']").value = 1
|
31
|
+
wrapper.style.display = 'none'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import TomSelect from "tom-select"
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static values = {
|
6
|
+
options: Object,
|
7
|
+
url: String
|
8
|
+
}
|
9
|
+
|
10
|
+
connect() {
|
11
|
+
this.select = new TomSelect(this.element, {
|
12
|
+
plugins: ['remove_button'],
|
13
|
+
valueField: 'id',
|
14
|
+
labelField: 'name',
|
15
|
+
searchField: 'name',
|
16
|
+
load: (search, callback) => {
|
17
|
+
let url = search ? `${this.urlValue}?q=${search}` : this.urlValue;
|
18
|
+
fetch(url)
|
19
|
+
.then(response => response.json())
|
20
|
+
.then(json => {
|
21
|
+
callback(json);
|
22
|
+
}).catch(() => {
|
23
|
+
callback();
|
24
|
+
});
|
25
|
+
}
|
26
|
+
})
|
27
|
+
}
|
28
|
+
|
29
|
+
disconnect() {
|
30
|
+
this.select.destroy()
|
31
|
+
}
|
32
|
+
}
|
@@ -5,22 +5,20 @@
|
|
5
5
|
<meta name="ROBOTS" content="NOODP">
|
6
6
|
<meta name="viewport" content="initial-scale=1">
|
7
7
|
<title>
|
8
|
-
|
8
|
+
<% if content_for? :title %>
|
9
|
+
<%= yield(:title) %> -
|
10
|
+
<% end %>
|
11
|
+
<%= Madmin.site_name %> Admin
|
9
12
|
</title>
|
10
|
-
|
11
13
|
<%= csrf_meta_tags %>
|
12
|
-
|
13
14
|
<%= render "javascript" %>
|
14
15
|
</head>
|
15
|
-
<body
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
<%= yield %>
|
23
|
-
</main>
|
24
|
-
</div>
|
16
|
+
<body>
|
17
|
+
<aside id="sidebar">
|
18
|
+
<%= render "navigation" %>
|
19
|
+
</aside>
|
20
|
+
<main>
|
21
|
+
<%= yield %>
|
22
|
+
</main>
|
25
23
|
</body>
|
26
24
|
</html>
|
@@ -1,23 +1,24 @@
|
|
1
1
|
<%= form_with model: [:madmin, record], url: (record.persisted? ? resource.show_path(record) : resource.index_path), local: true do |form| %>
|
2
2
|
<% if form.object.errors.any? %>
|
3
|
-
<div class="
|
4
|
-
<div class="
|
3
|
+
<div class="alert alert-danger">
|
4
|
+
<div class="">There was <%= pluralize form.object.errors.full_messages.count, "error" %> with your submission:</div>
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
<ul>
|
7
|
+
<% form.object.errors.full_messages.each do |message| %>
|
8
|
+
<li><%= message %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
9
11
|
</div>
|
10
12
|
<% end %>
|
11
13
|
|
12
|
-
<% resource.attributes.values.each do |attribute| %>
|
13
|
-
|
14
|
-
|
15
|
-
<% next unless attribute.field.visible?(:form) %>
|
16
|
-
|
17
|
-
<div class="mb-4 md:flex">
|
14
|
+
<% resource.attributes.values.select{ _1.field.present? && _1.field.visible?(action_name) }.each do |attribute| %>
|
15
|
+
<div class="form-group">
|
16
|
+
<%= render "madmin/shared/label", form: form, field: attribute.field %>
|
18
17
|
<%= render partial: attribute.field.to_partial_path("form"), locals: { field: attribute.field, record: record, form: form, resource: resource } %>
|
18
|
+
<%= tag.div attribute.field.options.description, class: "form-description" if attribute.field.options.description.present? %>
|
19
19
|
</div>
|
20
20
|
<% end %>
|
21
21
|
|
22
|
-
<%= form.submit class: "
|
22
|
+
<%= form.submit class: "btn btn-primary" %>
|
23
|
+
<%= link_to "Cancel", (record.persisted? ? resource.show_path(record) : resource.index_path), class: "btn" %>
|
23
24
|
<% end %>
|
@@ -1,138 +1,5 @@
|
|
1
|
-
|
1
|
+
<%= javascript_importmap_tags "application", importmap: Madmin.importmap %>
|
2
|
+
|
3
|
+
<%= stylesheet_link_tag "madmin/application", "data-turbo-track": "reload" %>
|
2
4
|
<%= stylesheet_link_tag "https://unpkg.com/flatpickr/dist/flatpickr.min.css", "data-turbo-track": "reload" %>
|
3
|
-
<%= stylesheet_link_tag "https://unpkg.com/trix/dist/trix.css", "data-turbo-track": "reload" %>
|
4
5
|
<%= stylesheet_link_tag "https://unpkg.com/tom-select/dist/css/tom-select.min.css", "data-turbo-track": "reload" %>
|
5
|
-
<style type="text/tailwindcss">
|
6
|
-
.pagy {
|
7
|
-
@apply isolate inline-flex rounded-md;
|
8
|
-
|
9
|
-
a:first-child {
|
10
|
-
@apply rounded-l-md;
|
11
|
-
}
|
12
|
-
a:last-child {
|
13
|
-
@apply rounded-r-md;
|
14
|
-
}
|
15
|
-
|
16
|
-
a {
|
17
|
-
@apply relative -ml-px inline-flex items-center bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-100 focus:z-10;
|
18
|
-
|
19
|
-
&:not([href]) {
|
20
|
-
@apply text-gray-300 cursor-default;
|
21
|
-
}
|
22
|
-
|
23
|
-
&.current {
|
24
|
-
@apply text-white bg-blue-500 ring-blue-500;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
|
28
|
-
label {
|
29
|
-
@apply inline-block whitespace-nowrap bg-gray-200 rounded-lg px-3 py-0.5;
|
30
|
-
input {
|
31
|
-
@apply bg-gray-100 border-none rounded-md;
|
32
|
-
}
|
33
|
-
}
|
34
|
-
}
|
35
|
-
</style>
|
36
|
-
|
37
|
-
<script type="importmap" data-turbo-track="reload">
|
38
|
-
{
|
39
|
-
"imports": {
|
40
|
-
"@hotwired/stimulus": "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js",
|
41
|
-
"@hotwired/turbo": "https://unpkg.com/@hotwired/turbo",
|
42
|
-
"@hotwired/turbo-rails": "https://unpkg.com/@hotwired/turbo-rails",
|
43
|
-
"@rails/actiontext": "https://unpkg.com/@rails/actiontext@<%= npm_rails_version %>/app/assets/javascripts/actiontext.js",
|
44
|
-
"@rails/activestorage": "https://unpkg.com/@rails/activestorage@<%= npm_rails_version %>/app/assets/javascripts/activestorage.esm.js",
|
45
|
-
"flatpickr": "https://unpkg.com/flatpickr/dist/esm/index.js",
|
46
|
-
"stimulus-flatpickr": "https://unpkg.com/stimulus-flatpickr@3.0.0-0/dist/index.m.js",
|
47
|
-
"tailwindcss-stimulus-components": "https://unpkg.com/tailwindcss-stimulus-components/dist/tailwindcss-stimulus-components.module.js",
|
48
|
-
"tom-select": "https://unpkg.com/tom-select/dist/esm/tom-select.complete.js",
|
49
|
-
"trix": "https://unpkg.com/trix"
|
50
|
-
}
|
51
|
-
}
|
52
|
-
</script>
|
53
|
-
<script async src="https://unpkg.com/es-module-shims/dist/es-module-shims.js"></script>
|
54
|
-
|
55
|
-
<script type="module">
|
56
|
-
import * as Turbo from "@hotwired/turbo-rails"
|
57
|
-
|
58
|
-
import * as ActiveStorage from "@rails/activestorage"
|
59
|
-
ActiveStorage.start()
|
60
|
-
import "trix"
|
61
|
-
import "@rails/actiontext"
|
62
|
-
|
63
|
-
import { Application, Controller } from '@hotwired/stimulus'
|
64
|
-
const application = Application.start()
|
65
|
-
|
66
|
-
import { Dropdown } from "tailwindcss-stimulus-components"
|
67
|
-
application.register("dropdown", Dropdown)
|
68
|
-
|
69
|
-
import StimulusFlatpickr from "stimulus-flatpickr"
|
70
|
-
application.register("flatpickr", StimulusFlatpickr)
|
71
|
-
|
72
|
-
import TomSelect from "tom-select"
|
73
|
-
|
74
|
-
(() => {
|
75
|
-
application.register('select', class extends Controller {
|
76
|
-
static values = {
|
77
|
-
options: Object,
|
78
|
-
url: String
|
79
|
-
}
|
80
|
-
|
81
|
-
connect() {
|
82
|
-
this.select = new TomSelect(this.element, {
|
83
|
-
plugins: ['remove_button'],
|
84
|
-
valueField: 'id',
|
85
|
-
labelField: 'name',
|
86
|
-
searchField: 'name',
|
87
|
-
load: (search, callback) => {
|
88
|
-
let url = search ? `${this.urlValue}?q=${search}` : this.urlValue;
|
89
|
-
fetch(url)
|
90
|
-
.then(response => response.json())
|
91
|
-
.then(json => {
|
92
|
-
callback(json);
|
93
|
-
}).catch(() => {
|
94
|
-
callback();
|
95
|
-
});
|
96
|
-
}
|
97
|
-
})
|
98
|
-
}
|
99
|
-
|
100
|
-
disconnect() {
|
101
|
-
this.select.destroy()
|
102
|
-
}
|
103
|
-
})
|
104
|
-
|
105
|
-
application.register('nested-form', class extends Controller {
|
106
|
-
static get targets() {
|
107
|
-
return [ "links", "template" ]
|
108
|
-
}
|
109
|
-
|
110
|
-
connect() {
|
111
|
-
this.wrapperClass = this.data.get("wrapperClass") || "nested-fields"
|
112
|
-
}
|
113
|
-
|
114
|
-
add_association(event) {
|
115
|
-
event.preventDefault()
|
116
|
-
|
117
|
-
var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
|
118
|
-
this.linksTarget.insertAdjacentHTML('beforebegin', content)
|
119
|
-
}
|
120
|
-
|
121
|
-
remove_association(event) {
|
122
|
-
event.preventDefault()
|
123
|
-
|
124
|
-
let wrapper = event.target.closest("." + this.wrapperClass)
|
125
|
-
|
126
|
-
// New records are simply removed from the page
|
127
|
-
if (wrapper.dataset.newRecord == "true") {
|
128
|
-
wrapper.remove()
|
129
|
-
|
130
|
-
// Existing records are hidden and flagged for deletion
|
131
|
-
} else {
|
132
|
-
wrapper.querySelector("input[name*='_destroy']").value = 1
|
133
|
-
wrapper.style.display = 'none'
|
134
|
-
}
|
135
|
-
}
|
136
|
-
})
|
137
|
-
})()
|
138
|
-
</script>
|
@@ -1,29 +1,24 @@
|
|
1
|
-
<
|
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>
|
1
|
+
<h1><%= link_to_if respond_to?(:root_url), Madmin.site_name, root_url, data: {turbo: false} %></h1>
|
11
2
|
|
12
|
-
|
13
|
-
|
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>
|
3
|
+
<nav>
|
4
|
+
<%= nav_link_to "Dashboard", madmin_root_path %>
|
20
5
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
6
|
+
<% Madmin.menu.render do |item| %>
|
7
|
+
<% if item.url %>
|
8
|
+
<%= nav_link_to item.label, item.url, starts_with: item.url %>
|
9
|
+
<% else %>
|
10
|
+
<h4><%= item.label %></h4>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% item.items.each do |item| %>
|
14
|
+
<%= nav_link_to item.label, item.url, starts_with: item.url %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
</nav>
|
18
|
+
|
19
|
+
<footer>
|
20
|
+
<%= link_to "https://github.com/excid3/madmin", target: :_blank do %>
|
21
|
+
<svg viewBox="0 0 16 16" height="1rem" width="1rem" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>
|
22
|
+
Madmin on GitHub
|
23
|
+
<% end %>
|
24
|
+
</footer>
|
@@ -1,7 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<
|
5
|
-
|
1
|
+
<%= content_for :title, "New #{resource.display_name(@record)}" %>
|
2
|
+
|
3
|
+
<header class="header">
|
4
|
+
<h1>
|
5
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path %>
|
6
|
+
/
|
7
|
+
<strong>Edit <%= link_to resource.display_name(@record), resource.show_path(@record) %></strong>
|
8
|
+
</h1>
|
9
|
+
</header>
|
6
10
|
|
7
11
|
<%= render partial: "form", locals: { record: @record, resource: resource } %>
|
@@ -1,62 +1,68 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
<%=
|
9
|
-
|
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 %>
|
1
|
+
<%= content_for :title, resource.friendly_name.pluralize %>
|
2
|
+
|
3
|
+
<header class="header">
|
4
|
+
<h1><%= resource.friendly_name.pluralize %></h1>
|
5
|
+
|
6
|
+
<div class="actions">
|
7
|
+
<form class="search">
|
8
|
+
<%= hidden_field_tag :page, params[:page], value: 1 %>
|
9
|
+
<%= search_field_tag :q, params[:q], placeholder: "Search" %>
|
13
10
|
</form>
|
14
11
|
|
15
|
-
<%= link_to
|
16
|
-
|
17
|
-
|
12
|
+
<%= link_to clear_search_params, class: "btn btn-secondary" do %>
|
13
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="1rem" width="1rem" viewBox="0 0 20 20" fill="currentColor">
|
14
|
+
<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" />
|
15
|
+
</svg>
|
16
|
+
<% end if params[:q].present? %>
|
17
|
+
|
18
|
+
<%= link_to "New #{resource.friendly_name}", resource.new_path, class: "btn btn-secondary" %>
|
18
19
|
</div>
|
19
|
-
</
|
20
|
+
</header>
|
20
21
|
|
21
|
-
<
|
22
|
+
<nav class="scopes">
|
22
23
|
<% if resource.scopes.any? %>
|
23
|
-
<%= link_to "All", resource.index_path, class: class_names("
|
24
|
+
<%= link_to "All", resource.index_path, class: class_names("btn btn-secondary", {"active" => params[:scope].blank?}) %>
|
24
25
|
<% end %>
|
25
26
|
|
26
27
|
<% resource.scopes.each do |scope| %>
|
27
|
-
<%= link_to scope.to_s.humanize, resource.index_path(scope: scope), class: class_names("
|
28
|
+
<%= link_to scope.to_s.humanize, resource.index_path(scope: scope), class: class_names("btn btn-secondary", {"active" => params[:scope] == scope.to_s}) %>
|
28
29
|
<% end %>
|
29
|
-
</
|
30
|
-
|
31
|
-
|
30
|
+
</nav>
|
31
|
+
|
32
|
+
<div class="table-scroll">
|
33
|
+
<table>
|
32
34
|
<thead>
|
33
|
-
<tr
|
35
|
+
<tr>
|
34
36
|
<% resource.attributes.values.each do |attribute| %>
|
35
37
|
<% next if attribute.field.nil? %>
|
36
38
|
<% next unless attribute.field.visible?(action_name) %>
|
37
39
|
|
38
|
-
<th
|
40
|
+
<th><%= sortable attribute.name, attribute.name.to_s.titleize %></th>
|
39
41
|
<% end %>
|
40
|
-
<th
|
42
|
+
<th></th>
|
41
43
|
</tr>
|
42
44
|
</thead>
|
43
45
|
|
44
|
-
<tbody
|
46
|
+
<tbody>
|
45
47
|
<% @records.each do |record| %>
|
46
48
|
<tr>
|
47
49
|
<% resource.attributes.values.each do |attribute| %>
|
48
50
|
<% next if attribute.field.nil? %>
|
49
51
|
<% next unless attribute.field.visible?(action_name) %>
|
50
|
-
<td
|
52
|
+
<td><%= render partial: attribute.field.to_partial_path("index"), locals: { field: attribute.field, record: record, resource: resource } %></td>
|
51
53
|
<% end %>
|
52
54
|
|
53
|
-
<td
|
54
|
-
<%= link_to "View", resource.show_path(record)
|
55
|
-
<%= link_to "Edit", resource.edit_path(record)
|
55
|
+
<td>
|
56
|
+
<%= link_to "View", resource.show_path(record) %>
|
57
|
+
<%= link_to "Edit", resource.edit_path(record) %>
|
56
58
|
</td>
|
57
59
|
</tr>
|
58
60
|
<% end %>
|
59
61
|
</tbody>
|
60
62
|
</table>
|
61
63
|
</div>
|
62
|
-
|
64
|
+
|
65
|
+
<div class="pagination">
|
66
|
+
<%== pagy_nav @pagy if @pagy.pages > 1 %>
|
67
|
+
<span>Showing <%= tag.strong @pagy.in %> of <%= tag.strong @pagy.count %></span>
|
68
|
+
</div>
|
@@ -1,7 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
<
|
5
|
-
|
1
|
+
<%= content_for :title, "New #{resource.friendly_name}" %>
|
2
|
+
|
3
|
+
<header class="header">
|
4
|
+
<h1>
|
5
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path %>
|
6
|
+
/
|
7
|
+
<strong>New <%= resource.friendly_name %></strong>
|
8
|
+
</h1>
|
9
|
+
</header>
|
6
10
|
|
7
11
|
<%= render partial: "form", locals: { record: @record, resource: resource } %>
|