django-admin-inline-controls 0.1.0__py3-none-any.whl
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.
- django_admin_inline_controls/__init__.py +1 -0
- django_admin_inline_controls/actions.py +176 -0
- django_admin_inline_controls/apps.py +7 -0
- django_admin_inline_controls/checks.py +212 -0
- django_admin_inline_controls/contrib/__init__.py +4 -0
- django_admin_inline_controls/contrib/filters.py +69 -0
- django_admin_inline_controls/contrib/nested.py +77 -0
- django_admin_inline_controls/contrib/unfold.py +85 -0
- django_admin_inline_controls/controls.py +684 -0
- django_admin_inline_controls/locale/es/LC_MESSAGES/django.mo +0 -0
- django_admin_inline_controls/locale/es/LC_MESSAGES/django.po +232 -0
- django_admin_inline_controls/mixins.py +932 -0
- django_admin_inline_controls/py.typed +0 -0
- django_admin_inline_controls/row_actions.py +173 -0
- django_admin_inline_controls/static/django_admin_inline_controls/css/contrib/unfold.css +111 -0
- django_admin_inline_controls/static/django_admin_inline_controls/css/core.css +294 -0
- django_admin_inline_controls/static/django_admin_inline_controls/js/actions.js +330 -0
- django_admin_inline_controls/static/django_admin_inline_controls/js/contrib/unfold.js +21 -0
- django_admin_inline_controls/static/django_admin_inline_controls/js/core.js +570 -0
- django_admin_inline_controls/static/django_admin_inline_controls/js/save.js +109 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/footer.html +99 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/inline.html +34 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/inline_response.html +14 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/row_actions.html +19 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/tfoot.html +36 -0
- django_admin_inline_controls/templates/django_admin_inline_controls/toolbar.html +93 -0
- django_admin_inline_controls/templatetags/__init__.py +0 -0
- django_admin_inline_controls/templatetags/inline_controls.py +72 -0
- django_admin_inline_controls/types.py +40 -0
- django_admin_inline_controls-0.1.0.dist-info/METADATA +823 -0
- django_admin_inline_controls-0.1.0.dist-info/RECORD +33 -0
- django_admin_inline_controls-0.1.0.dist-info/WHEEL +4 -0
- django_admin_inline_controls-0.1.0.dist-info/licenses/LICENSE +21 -0
|
File without changes
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Row actions: buttons on each saved row of an inline.
|
|
2
|
+
|
|
3
|
+
An action is a method of the inline (or a callable) in one of two forms:
|
|
4
|
+
|
|
5
|
+
- for one row, ``action(inline, request, obj, parent_obj=None)`` — the
|
|
6
|
+
signature of django-inline-actions, so its actions can be reused as they
|
|
7
|
+
are;
|
|
8
|
+
- for a queryset, ``action(inline, request, queryset)`` — an inline action
|
|
9
|
+
(``@inline_action``), run on a queryset with only that row.
|
|
10
|
+
|
|
11
|
+
Both return ``None`` to re-render the inline with the messages sent through
|
|
12
|
+
``inline.message_user()``, or an ``HttpResponse`` (a file download or a
|
|
13
|
+
redirect). Per-row label, CSS classes and HTML attributes come from the
|
|
14
|
+
action's ``short_description`` / ``css_classes`` / ``attribute_properties``
|
|
15
|
+
or from ``get_<action>_label(obj)`` / ``get_<action>_css(obj)`` /
|
|
16
|
+
``get_<action>_attr(obj)`` on the inline, as in django-inline-actions.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import inspect
|
|
22
|
+
from collections.abc import Callable
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
from django.contrib import messages
|
|
27
|
+
from django.contrib.admin.utils import model_format_dict, quote
|
|
28
|
+
from django.http import HttpRequest, HttpResponseRedirect
|
|
29
|
+
from django.urls import NoReverseMatch, reverse
|
|
30
|
+
from django.utils.html import format_html_join
|
|
31
|
+
from django.utils.safestring import SafeString, mark_safe
|
|
32
|
+
from django.utils.text import capfirst
|
|
33
|
+
from django.utils.translation import gettext
|
|
34
|
+
from django.utils.translation import gettext_lazy as _
|
|
35
|
+
|
|
36
|
+
from django_admin_inline_controls.actions import delete_selected, inline_action
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def set_render_context(inline: Any, request: HttpRequest, parent: Any) -> None:
|
|
40
|
+
"""Remember the request and parent object the inline is rendered for: the
|
|
41
|
+
actions' column only gets the row. On the instance, which the admin
|
|
42
|
+
creates for each request (``get_inline_instances()``)."""
|
|
43
|
+
inline._inline_controls_render = (request, parent)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_render_context(inline: Any) -> tuple[HttpRequest | None, Any]:
|
|
47
|
+
return getattr(inline, "_inline_controls_render", (None, None))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@inline_action(
|
|
51
|
+
permissions=["delete"],
|
|
52
|
+
description=_("Delete"),
|
|
53
|
+
confirmation=_("Delete “%(object)s”? This cannot be undone."),
|
|
54
|
+
)
|
|
55
|
+
def delete(inline: Any, request: HttpRequest, queryset: Any) -> None:
|
|
56
|
+
"""Delete the row (``delete()`` overrides and signals run), recorded in
|
|
57
|
+
the parent's history, like ``delete_selected``."""
|
|
58
|
+
return delete_selected(inline, request, queryset)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@inline_action(permissions=["view"], description=_("View"))
|
|
62
|
+
def view(inline: Any, request: HttpRequest, obj: Any, parent_obj: Any = None) -> Any:
|
|
63
|
+
"""Open the row's change view (its own ``ModelAdmin``)."""
|
|
64
|
+
url = change_url(inline, obj)
|
|
65
|
+
if url is None: # pragma: no cover - only offered when it has one
|
|
66
|
+
inline.message_user(request, gettext("This item has no page."), messages.ERROR)
|
|
67
|
+
return None
|
|
68
|
+
return HttpResponseRedirect(url)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#: Rendered as a link to the row's change view, not a button.
|
|
72
|
+
view.inline_actions_link = True
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#: Row actions that can be referenced by name in ``inline_actions``.
|
|
76
|
+
BUILTIN_ROW_ACTIONS: dict[str, Callable[..., Any]] = {"delete": delete, "view": view}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def change_url(inline: Any, obj: Any) -> str | None:
|
|
80
|
+
"""The change view of ``obj`` in the inline's admin site, if registered."""
|
|
81
|
+
opts = obj._meta
|
|
82
|
+
try:
|
|
83
|
+
return reverse(
|
|
84
|
+
f"{inline.admin_site.name}:{opts.app_label}_{opts.model_name}_change",
|
|
85
|
+
args=[quote(obj.pk)],
|
|
86
|
+
)
|
|
87
|
+
except NoReverseMatch:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def takes_one_row(function: Callable[..., Any]) -> bool:
|
|
92
|
+
"""Whether ``function`` acts on one row (``obj``) rather than a queryset."""
|
|
93
|
+
try:
|
|
94
|
+
return "obj" in inspect.signature(function).parameters
|
|
95
|
+
except (TypeError, ValueError): # pragma: no cover - builtins, C functions
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True)
|
|
100
|
+
class RowActionSpec:
|
|
101
|
+
"""A row action as offered for one row."""
|
|
102
|
+
|
|
103
|
+
name: str
|
|
104
|
+
function: Callable[..., Any]
|
|
105
|
+
label: str
|
|
106
|
+
css_classes: str
|
|
107
|
+
#: Extra HTML attributes of the button.
|
|
108
|
+
attrs: SafeString
|
|
109
|
+
confirmation: str | None
|
|
110
|
+
#: A link instead of a button (``view``).
|
|
111
|
+
url: str | None = None
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def row_action_spec(
|
|
115
|
+
inline: Any, name: str, function: Callable[..., Any], obj: Any
|
|
116
|
+
) -> RowActionSpec:
|
|
117
|
+
"""``function`` as ``name``'s action for the row ``obj``."""
|
|
118
|
+
names = {**model_format_dict(inline.model._meta), "object": obj, "count": 1}
|
|
119
|
+
|
|
120
|
+
def hook(kind: str) -> Any:
|
|
121
|
+
method = getattr(inline, f"get_{name}_{kind}", None)
|
|
122
|
+
return method(obj=obj) if callable(method) else None
|
|
123
|
+
|
|
124
|
+
label = hook("label")
|
|
125
|
+
if label is None:
|
|
126
|
+
label = getattr(function, "short_description", None)
|
|
127
|
+
label = (
|
|
128
|
+
str(label) % names
|
|
129
|
+
if label is not None
|
|
130
|
+
else capfirst(name.replace("_", " "))
|
|
131
|
+
)
|
|
132
|
+
css = hook("css")
|
|
133
|
+
if css is None:
|
|
134
|
+
css = getattr(function, "css_classes", "")
|
|
135
|
+
attrs = hook("attr")
|
|
136
|
+
if attrs is None:
|
|
137
|
+
attrs = getattr(function, "attribute_properties", "")
|
|
138
|
+
if isinstance(attrs, dict):
|
|
139
|
+
attrs = format_html_join(" ", '{}="{}"', attrs.items())
|
|
140
|
+
else:
|
|
141
|
+
# A string is used as it is, as in django-inline-actions.
|
|
142
|
+
attrs = mark_safe(attrs) # noqa: S308
|
|
143
|
+
confirmation = getattr(function, "confirmation", None)
|
|
144
|
+
return RowActionSpec(
|
|
145
|
+
name=name,
|
|
146
|
+
function=function,
|
|
147
|
+
label=str(label),
|
|
148
|
+
css_classes=str(css),
|
|
149
|
+
attrs=attrs,
|
|
150
|
+
confirmation=None if confirmation is None else str(confirmation) % names,
|
|
151
|
+
url=change_url(inline, obj)
|
|
152
|
+
if getattr(function, "inline_actions_link", False)
|
|
153
|
+
else None,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def run_row_action(
|
|
158
|
+
inline: Any, request: HttpRequest, action: RowActionSpec, obj: Any, parent: Any
|
|
159
|
+
) -> Any:
|
|
160
|
+
"""Call the action on the row ``obj`` in the form it was written for."""
|
|
161
|
+
function = action.function
|
|
162
|
+
if takes_one_row(function):
|
|
163
|
+
return function(inline, request, obj, parent_obj=parent)
|
|
164
|
+
queryset = type(obj)._default_manager.filter(pk=obj.pk)
|
|
165
|
+
return function(inline, request, queryset)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
__all__ = [
|
|
169
|
+
"BUILTIN_ROW_ACTIONS",
|
|
170
|
+
"RowActionSpec",
|
|
171
|
+
"delete",
|
|
172
|
+
"view",
|
|
173
|
+
]
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* django-admin-inline-controls: django-unfold's colors, light and dark. */
|
|
2
|
+
/* The tfoot also on its own: the add view has no controls around it. */
|
|
3
|
+
.inline-controls,
|
|
4
|
+
.inline-controls-tfoot {
|
|
5
|
+
--body-bg: #fff;
|
|
6
|
+
--body-fg: var(--color-font-default-light);
|
|
7
|
+
--body-quiet-color: var(--color-font-subtle-light);
|
|
8
|
+
--border-color: var(--color-base-200);
|
|
9
|
+
--darkened-bg: var(--color-base-50);
|
|
10
|
+
--error-fg: var(--color-red-600);
|
|
11
|
+
--hairline-color: var(--color-base-200);
|
|
12
|
+
--selected-bg: var(--color-base-100);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.dark .inline-controls,
|
|
16
|
+
.dark .inline-controls-tfoot {
|
|
17
|
+
--body-bg: var(--color-base-900);
|
|
18
|
+
--body-fg: var(--color-font-default-dark);
|
|
19
|
+
--body-quiet-color: var(--color-font-subtle-dark);
|
|
20
|
+
--border-color: var(--color-base-700);
|
|
21
|
+
--darkened-bg: var(--color-base-800);
|
|
22
|
+
--error-fg: var(--color-red-500);
|
|
23
|
+
--hairline-color: var(--color-base-800);
|
|
24
|
+
--selected-bg: var(--color-base-800);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.inline-controls-toolbar {
|
|
28
|
+
margin-bottom: 1rem;
|
|
29
|
+
border: 1px solid var(--hairline-color);
|
|
30
|
+
border-radius: var(--border-radius, 6px);
|
|
31
|
+
color: var(--body-fg);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.inline-controls-footer {
|
|
35
|
+
color: var(--body-fg);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.inline-controls-toolbar select,
|
|
39
|
+
.inline-controls-toolbar input:not([type="checkbox"], [type="radio"]) {
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
height: 30px;
|
|
42
|
+
padding: 0 8px;
|
|
43
|
+
border: 1px solid var(--border-color);
|
|
44
|
+
border-radius: var(--border-radius, 6px);
|
|
45
|
+
color: var(--body-fg);
|
|
46
|
+
background-color: var(--body-bg);
|
|
47
|
+
font-size: 0.8125rem;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.inline-controls .button {
|
|
51
|
+
border: 1px solid var(--border-color);
|
|
52
|
+
border-radius: var(--border-radius, 6px);
|
|
53
|
+
color: var(--body-fg);
|
|
54
|
+
background: var(--body-bg);
|
|
55
|
+
font-weight: 500;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.inline-controls .button:hover {
|
|
59
|
+
background: var(--darkened-bg);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.inline-controls a:not(.button) {
|
|
63
|
+
color: var(--color-primary-600);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.dark .inline-controls a:not(.button) {
|
|
67
|
+
color: var(--color-primary-500);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.inline-controls-current {
|
|
71
|
+
color: var(--body-fg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
table tfoot.inline-controls-tfoot.inline-controls-tfoot th,
|
|
75
|
+
table tfoot.inline-controls-tfoot.inline-controls-tfoot td {
|
|
76
|
+
padding: 0.5rem 0.375rem;
|
|
77
|
+
border-top: 1px solid var(--hairline-color);
|
|
78
|
+
background: var(--darkened-bg);
|
|
79
|
+
color: var(--body-fg);
|
|
80
|
+
font-size: 0.8125rem;
|
|
81
|
+
text-align: left;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
table
|
|
85
|
+
tfoot.inline-controls-tfoot.inline-controls-tfoot
|
|
86
|
+
:is(th, td):first-child {
|
|
87
|
+
padding-left: 0.75rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
table tfoot.inline-controls-tfoot.inline-controls-tfoot th {
|
|
91
|
+
text-align: right;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
table
|
|
95
|
+
tfoot.inline-controls-tfoot.inline-controls-tfoot
|
|
96
|
+
.inline-controls-footer-label {
|
|
97
|
+
margin-right: 0.5rem;
|
|
98
|
+
color: var(--body-quiet-color);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
table
|
|
102
|
+
tfoot.inline-controls-tfoot.inline-controls-tfoot
|
|
103
|
+
.inline-controls-footer-value {
|
|
104
|
+
font-weight: 600;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.inline-controls .inline-controls-row-action.button {
|
|
108
|
+
padding: 0.25rem 0.625rem;
|
|
109
|
+
font-size: 0.75rem;
|
|
110
|
+
text-decoration: none;
|
|
111
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
.inline-controls-toolbar {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-wrap: wrap;
|
|
4
|
+
align-items: flex-end;
|
|
5
|
+
gap: 8px 24px;
|
|
6
|
+
padding: 8px 10px;
|
|
7
|
+
border-bottom: 1px solid var(--hairline-color, #e8e8e8);
|
|
8
|
+
background: var(--darkened-bg, #f8f8f8);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.inline-controls-actions {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
flex-basis: 100%;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 6px 10px;
|
|
17
|
+
font-size: 0.8125rem;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.inline-controls-actions label {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 6px;
|
|
24
|
+
float: none;
|
|
25
|
+
width: auto;
|
|
26
|
+
min-width: 0;
|
|
27
|
+
padding: 0;
|
|
28
|
+
font-weight: normal;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.inline-controls-actions select,
|
|
32
|
+
.inline-controls-actions .button {
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
height: 30px;
|
|
35
|
+
margin: 0;
|
|
36
|
+
font-size: 0.8125rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.inline-controls-actions .button {
|
|
40
|
+
padding: 0 12px;
|
|
41
|
+
border-radius: 4px;
|
|
42
|
+
line-height: 1;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.inline-controls-selection {
|
|
47
|
+
color: var(--body-quiet-color, #666);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.inline-controls-select-across[hidden] {
|
|
51
|
+
display: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.inline-controls-select,
|
|
55
|
+
.inline-controls-select-all {
|
|
56
|
+
margin: 0 6px 0 0;
|
|
57
|
+
vertical-align: middle;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* The tabular label line is short and clips; let the checkbox fit. */
|
|
61
|
+
.inline-group .tabular td.original p:has(> .inline-controls-select) {
|
|
62
|
+
height: auto;
|
|
63
|
+
overflow: visible;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.inline-controls-filters {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-wrap: wrap;
|
|
69
|
+
align-items: flex-end;
|
|
70
|
+
gap: 8px 12px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.inline-controls-filter {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 2px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.inline-controls-filter label {
|
|
80
|
+
float: none;
|
|
81
|
+
width: auto;
|
|
82
|
+
min-width: 0;
|
|
83
|
+
padding: 0;
|
|
84
|
+
font-size: 0.75rem;
|
|
85
|
+
font-weight: normal;
|
|
86
|
+
color: var(--body-quiet-color, #666);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.inline-controls-filter .errorlist {
|
|
90
|
+
margin: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* The admin styles text inputs and selects but not date/number inputs or
|
|
94
|
+
<button>: give every single-line control and the buttons one height. */
|
|
95
|
+
.inline-controls-filter input:not([type="checkbox"], [type="radio"]),
|
|
96
|
+
.inline-controls-filter select:not([multiple]),
|
|
97
|
+
.inline-controls-filter-buttons .button {
|
|
98
|
+
box-sizing: border-box;
|
|
99
|
+
height: 30px;
|
|
100
|
+
margin: 0;
|
|
101
|
+
font-size: 0.8125rem;
|
|
102
|
+
vertical-align: middle;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.inline-controls-filter input:not([type="checkbox"], [type="radio"]) {
|
|
106
|
+
padding: 5px 6px;
|
|
107
|
+
border: 1px solid var(--border-color, #ccc);
|
|
108
|
+
border-radius: 4px;
|
|
109
|
+
color: var(--body-fg, #333);
|
|
110
|
+
background-color: var(--body-bg, #fff);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.inline-controls-filter-buttons {
|
|
114
|
+
display: flex;
|
|
115
|
+
gap: 6px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.inline-controls-filter-buttons .button {
|
|
119
|
+
padding: 0 12px;
|
|
120
|
+
border-radius: 4px;
|
|
121
|
+
line-height: 1;
|
|
122
|
+
cursor: pointer;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.inline-controls-ordering {
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-wrap: wrap;
|
|
128
|
+
align-items: center;
|
|
129
|
+
gap: 4px 12px;
|
|
130
|
+
font-size: 0.8125rem;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.inline-controls-ordering[hidden] {
|
|
134
|
+
display: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.inline-controls-ordering-label,
|
|
138
|
+
.inline-controls-sort-priority,
|
|
139
|
+
.inline-controls-sort-remove,
|
|
140
|
+
.inline-controls-count {
|
|
141
|
+
color: var(--body-quiet-color, #666);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.inline-controls-sort-priority {
|
|
145
|
+
font-size: 0.6875rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.inline-controls-sort-remove {
|
|
149
|
+
margin-left: 2px;
|
|
150
|
+
text-decoration: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.inline-controls-ascending .inline-controls-sort-toggle::after {
|
|
154
|
+
content: " \25B2";
|
|
155
|
+
font-size: 0.7em;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.inline-controls-descending .inline-controls-sort-toggle::after {
|
|
159
|
+
content: " \25BC";
|
|
160
|
+
font-size: 0.7em;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
th.inline-controls-sortable .inline-controls-sort-toggle {
|
|
164
|
+
color: inherit;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.inline-controls-footer {
|
|
168
|
+
display: flex;
|
|
169
|
+
flex-wrap: wrap;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: 4px 12px;
|
|
172
|
+
padding: 8px 10px;
|
|
173
|
+
font-size: 0.8125rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.inline-controls-pagination {
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-wrap: wrap;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 4px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.inline-controls-page,
|
|
184
|
+
.inline-controls-ellipsis {
|
|
185
|
+
min-width: 1.5em;
|
|
186
|
+
padding: 2px 6px;
|
|
187
|
+
text-align: center;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.inline-controls-current {
|
|
191
|
+
font-weight: bold;
|
|
192
|
+
border-radius: 4px;
|
|
193
|
+
background: var(--selected-bg, #e4e4e4);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.inline-controls-footer:not(.inline-controls-infinite) .inline-controls-count {
|
|
197
|
+
margin-left: auto;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.inline-controls-infinite {
|
|
201
|
+
justify-content: center;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.inline-controls-save {
|
|
205
|
+
display: flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
gap: 8px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.inline-controls-infinite .inline-controls-save,
|
|
211
|
+
.inline-controls-footer > .inline-controls-save:first-child {
|
|
212
|
+
margin-left: auto;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.inline-controls-save .button {
|
|
216
|
+
box-sizing: border-box;
|
|
217
|
+
height: 30px;
|
|
218
|
+
margin: 0;
|
|
219
|
+
padding: 0 12px;
|
|
220
|
+
border-radius: 4px;
|
|
221
|
+
font-size: 0.8125rem;
|
|
222
|
+
line-height: 1;
|
|
223
|
+
cursor: pointer;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.inline-controls-status-invalid,
|
|
227
|
+
.inline-controls-status-failed,
|
|
228
|
+
.inline-controls-status-error {
|
|
229
|
+
color: var(--error-fg, #ba2121);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.inline-controls.inline-controls-loading {
|
|
233
|
+
opacity: 0.6;
|
|
234
|
+
transition: opacity 0.2s;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.inline-controls-footer-rows {
|
|
238
|
+
display: flex;
|
|
239
|
+
flex-direction: column;
|
|
240
|
+
flex-basis: 100%;
|
|
241
|
+
gap: 2px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.inline-controls-footer-row {
|
|
245
|
+
display: flex;
|
|
246
|
+
flex-wrap: wrap;
|
|
247
|
+
gap: 4px 16px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.inline-controls-footer-label {
|
|
251
|
+
font-weight: bold;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.inline-controls-footer-column {
|
|
255
|
+
color: var(--body-quiet-color, #666);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Specific enough to beat the admin's own `tfoot td` and inline rules. */
|
|
259
|
+
.inline-group table tfoot.inline-controls-tfoot th,
|
|
260
|
+
.inline-group table tfoot.inline-controls-tfoot td {
|
|
261
|
+
border-top: 1px solid var(--hairline-color, #e8e8e8);
|
|
262
|
+
background: var(--darkened-bg, #f8f8f8);
|
|
263
|
+
font-size: 0.8125rem;
|
|
264
|
+
font-weight: normal;
|
|
265
|
+
text-transform: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.inline-group table tfoot.inline-controls-tfoot th {
|
|
269
|
+
text-align: right;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.inline-group table tfoot.inline-controls-tfoot .inline-controls-footer-label {
|
|
273
|
+
color: var(--body-quiet-color, #666);
|
|
274
|
+
font-weight: bold;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.inline-group table tfoot.inline-controls-tfoot .inline-controls-footer-value {
|
|
278
|
+
font-weight: bold;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.inline-controls-row-actions:not([hidden]) {
|
|
282
|
+
display: inline-flex;
|
|
283
|
+
gap: 4px;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.inline-controls-row-action.button {
|
|
287
|
+
margin: 0;
|
|
288
|
+
padding: 4px 8px;
|
|
289
|
+
font-size: 0.75rem;
|
|
290
|
+
line-height: 1.2;
|
|
291
|
+
white-space: nowrap;
|
|
292
|
+
text-decoration: none;
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
}
|