django-unfold 0.66.0__py3-none-any.whl → 0.68.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_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/METADATA +8 -5
- {django_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/RECORD +46 -42
- unfold/admin.py +73 -13
- unfold/components.py +2 -2
- unfold/contrib/filters/admin/choice_filters.py +13 -1
- unfold/contrib/filters/admin/mixins.py +3 -3
- unfold/contrib/filters/admin/numeric_filters.py +8 -6
- unfold/contrib/filters/forms.py +25 -4
- unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js +62 -28
- unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +2 -11
- unfold/contrib/forms/widgets.py +5 -5
- unfold/contrib/inlines/admin.py +3 -3
- unfold/contrib/inlines/forms.py +5 -4
- unfold/dataclasses.py +13 -13
- unfold/datasets.py +69 -0
- unfold/decorators.py +19 -19
- unfold/fields.py +40 -1
- unfold/forms.py +19 -7
- unfold/mixins/action_model_admin.py +11 -10
- unfold/mixins/base_model_admin.py +6 -6
- unfold/sites.py +14 -17
- unfold/static/unfold/css/styles.css +1 -1
- unfold/static/unfold/js/app.js +65 -5
- unfold/static/unfold/js/select2.init.js +2 -9
- unfold/styles.css +22 -21
- unfold/templates/admin/change_form.html +5 -1
- unfold/templates/admin/change_list_results.html +10 -62
- unfold/templates/admin/edit_inline/stacked.html +1 -1
- unfold/templates/admin/search_form.html +5 -3
- unfold/templates/unfold/components/card.html +12 -3
- unfold/templates/unfold/components/progress.html +9 -3
- unfold/templates/unfold/helpers/change_list_headers.html +65 -0
- unfold/templates/unfold/helpers/dataset.html +19 -0
- unfold/templates/unfold/helpers/edit_inline/tabular_field.html +1 -1
- unfold/templates/unfold/helpers/empty_results.html +6 -4
- unfold/templates/unfold/helpers/field_readonly_value.html +1 -1
- unfold/templates/unfold/helpers/field_readonly_value_file.html +18 -0
- unfold/templates/unfold/helpers/tab_items.html +6 -0
- unfold/templatetags/unfold.py +18 -13
- unfold/templatetags/unfold_list.py +64 -8
- unfold/typing.py +5 -6
- unfold/utils.py +9 -9
- unfold/views.py +15 -1
- unfold/widgets.py +30 -29
- {django_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/WHEEL +0 -0
- {django_unfold-0.66.0.dist-info → django_unfold-0.68.0.dist-info}/licenses/LICENSE.md +0 -0
unfold/static/unfold/js/app.js
CHANGED
@@ -17,7 +17,9 @@ const sortRecords = (e) => {
|
|
17
17
|
const orderingField = e.from.dataset.orderingField;
|
18
18
|
|
19
19
|
const weightInputs = Array.from(
|
20
|
-
e.from.querySelectorAll(
|
20
|
+
e.from.querySelectorAll(
|
21
|
+
`.has_original input[name$=-${orderingField}], td.field-${orderingField} input[name$=-${orderingField}]`
|
22
|
+
)
|
21
23
|
);
|
22
24
|
|
23
25
|
weightInputs.forEach((input, index) => {
|
@@ -416,6 +418,12 @@ const DEFAULT_CHART_OPTIONS = {
|
|
416
418
|
pointBorderWidth: 0,
|
417
419
|
pointStyle: false,
|
418
420
|
},
|
421
|
+
pie: {
|
422
|
+
borderWidth: 0,
|
423
|
+
},
|
424
|
+
doughnut: {
|
425
|
+
borderWidth: 0,
|
426
|
+
},
|
419
427
|
},
|
420
428
|
plugins: {
|
421
429
|
legend: {
|
@@ -436,6 +444,13 @@ const DEFAULT_CHART_OPTIONS = {
|
|
436
444
|
},
|
437
445
|
scales: {
|
438
446
|
x: {
|
447
|
+
display: function (context) {
|
448
|
+
if (["pie", "doughnut", "radar"].includes(context.chart.config.type)) {
|
449
|
+
return false;
|
450
|
+
}
|
451
|
+
|
452
|
+
return true;
|
453
|
+
},
|
439
454
|
border: {
|
440
455
|
dash: [5, 5],
|
441
456
|
dashOffset: 2,
|
@@ -456,6 +471,13 @@ const DEFAULT_CHART_OPTIONS = {
|
|
456
471
|
},
|
457
472
|
},
|
458
473
|
y: {
|
474
|
+
display: function (context) {
|
475
|
+
if (["pie", "doughnut", "radar"].includes(context.chart.config.type)) {
|
476
|
+
return false;
|
477
|
+
}
|
478
|
+
|
479
|
+
return true;
|
480
|
+
},
|
459
481
|
border: {
|
460
482
|
dash: [5, 5],
|
461
483
|
dashOffset: 5,
|
@@ -512,8 +534,17 @@ const renderCharts = () => {
|
|
512
534
|
const borderColor = hasDarkClass ? baseColorDark : baseColorLight;
|
513
535
|
|
514
536
|
for (const chart of charts) {
|
515
|
-
chart.options.scales.x
|
516
|
-
|
537
|
+
if (chart.options.scales.x) {
|
538
|
+
chart.options.scales.x.grid.color = borderColor;
|
539
|
+
}
|
540
|
+
|
541
|
+
if (chart.options.scales.y) {
|
542
|
+
chart.options.scales.y.grid.color = borderColor;
|
543
|
+
}
|
544
|
+
|
545
|
+
if (chart.options.scales.r) {
|
546
|
+
chart.options.scales.r.grid.color = borderColor;
|
547
|
+
}
|
517
548
|
chart.update();
|
518
549
|
}
|
519
550
|
};
|
@@ -533,7 +564,17 @@ const renderCharts = () => {
|
|
533
564
|
for (const key in parsedData.datasets) {
|
534
565
|
const dataset = parsedData.datasets[key];
|
535
566
|
const processColor = (colorProp) => {
|
536
|
-
if (dataset?.[colorProp]
|
567
|
+
if (Array.isArray(dataset?.[colorProp])) {
|
568
|
+
for (const [index, prop] of dataset?.[colorProp].entries()) {
|
569
|
+
if (prop.startsWith("var(")) {
|
570
|
+
const cssVar = prop.match(/var\((.*?)\)/)[1];
|
571
|
+
const color = getComputedStyle(document.documentElement)
|
572
|
+
.getPropertyValue(cssVar)
|
573
|
+
.trim();
|
574
|
+
dataset[colorProp][index] = color;
|
575
|
+
}
|
576
|
+
}
|
577
|
+
} else if (dataset?.[colorProp]?.startsWith("var(")) {
|
537
578
|
const cssVar = dataset[colorProp].match(/var\((.*?)\)/)[1];
|
538
579
|
const color = getComputedStyle(document.documentElement)
|
539
580
|
.getPropertyValue(cssVar)
|
@@ -546,11 +587,30 @@ const renderCharts = () => {
|
|
546
587
|
processColor("backgroundColor");
|
547
588
|
}
|
548
589
|
|
590
|
+
CHART_OPTIONS = { ...DEFAULT_CHART_OPTIONS };
|
591
|
+
if (type === "radar") {
|
592
|
+
CHART_OPTIONS.scales = {
|
593
|
+
r: {
|
594
|
+
ticks: {
|
595
|
+
backdropColor: "transparent",
|
596
|
+
},
|
597
|
+
pointLabels: {
|
598
|
+
color: "#9ca3af",
|
599
|
+
font: {
|
600
|
+
size: 12,
|
601
|
+
},
|
602
|
+
},
|
603
|
+
},
|
604
|
+
};
|
605
|
+
}
|
606
|
+
Chart.defaults.font.family = "Inter";
|
607
|
+
Chart.defaults.font.size = 12;
|
608
|
+
|
549
609
|
charts.push(
|
550
610
|
new Chart(ctx, {
|
551
611
|
type: type || "bar",
|
552
612
|
data: parsedData,
|
553
|
-
options: options ? JSON.parse(options) : { ...
|
613
|
+
options: options ? JSON.parse(options) : { ...CHART_OPTIONS },
|
554
614
|
})
|
555
615
|
);
|
556
616
|
}
|
@@ -18,7 +18,7 @@
|
|
18
18
|
return this;
|
19
19
|
};
|
20
20
|
|
21
|
-
$.fn.
|
21
|
+
$.fn.djangoFilterSelect2 = function () {
|
22
22
|
$.each(this, function (i, element) {
|
23
23
|
$(element).select2({
|
24
24
|
ajax: {
|
@@ -40,13 +40,6 @@
|
|
40
40
|
$(function () {
|
41
41
|
$(".unfold-admin-autocomplete.admin-autocomplete").djangoCustomSelect2();
|
42
42
|
|
43
|
-
$(".admin-autocomplete")
|
44
|
-
.not(".unfold-admin-autocomplete")
|
45
|
-
.not("[name*=__prefix__]")
|
46
|
-
.djangoAdminSelect2();
|
47
|
-
});
|
48
|
-
|
49
|
-
document.addEventListener("formset:added", (event) => {
|
50
|
-
$(event.target).find(".admin-autocomplete").djangoAdminSelect2();
|
43
|
+
$(".unfold-filter-autocomplete.admin-autocomplete").djangoFilterSelect2();
|
51
44
|
});
|
52
45
|
}
|
unfold/styles.css
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
@source inline("{md:,lg:,2xl:,}relative {md:,lg:,2xl:,}flex {md:,lg:,2xl:,}absolute {md:,lg:,2xl:,}sticky");
|
17
17
|
@source inline("{-,}{lg:,}m{t,r,b,l,x,y,}-{0..24} {-,}{lg:,}p{t,r,b,l,x,y,}-{0..24}");
|
18
18
|
@source inline("{md:,lg:,}border-{0,2} {md:,lg:,}border-{t,r,b,l}-{0,2}");
|
19
|
-
@source inline("{hover:,dark:,}bg-primary-{50,{100..900..100},950}");
|
19
|
+
@source inline("{!,}{hover:,dark:,}bg-primary-{50,{100..900..100},950}");
|
20
20
|
@source inline("{hover:,dark:,}border-base-{50,{100..900..100},950} {hover:,dark:,}border-transparent");
|
21
21
|
@source inline("{hover:,dark:,}bg-base-{50,{100..900..100},950}");
|
22
22
|
@source inline("{md:,lg:,}{min-h,h,min-w,w}-{1..8} {md:,lg:,}w-{1/2,1/3,2/3,1/4,2/4,3/4,1/5,2/5,3/5,4/5,1/6,2/6,3/6,4/6,5/6,1/7,2/7,3/7,4/7,5/7,6/7}");
|
@@ -420,6 +420,10 @@ td .inline-deletelink {
|
|
420
420
|
@apply py-1;
|
421
421
|
}
|
422
422
|
|
423
|
+
.select2-container .select2-results__option--highlighted[aria-selected] {
|
424
|
+
@apply !bg-base-100 dark:!bg-base-800;
|
425
|
+
}
|
426
|
+
|
423
427
|
.select2-container.select2-container--open .select2-dropdown {
|
424
428
|
@apply bg-white border border-base-200 rounded-default shadow-xs dark:border-base-700 dark:bg-base-900;
|
425
429
|
}
|
@@ -505,13 +509,17 @@ fieldset details[open] > summary:after {
|
|
505
509
|
/*******************************************************
|
506
510
|
Calendar
|
507
511
|
*******************************************************/
|
512
|
+
.calendarbox .calendar {
|
513
|
+
@apply min-h-[320px];
|
514
|
+
}
|
515
|
+
|
508
516
|
.calendarbox,
|
509
517
|
.clockbox {
|
510
|
-
@apply bg-white border border-base-200 rounded-default shadow-xs
|
518
|
+
@apply bg-white border border-base-200 rounded-default shadow-xs w-80 z-50 dark:bg-base-800 dark:border-base-700 fixed! left-1/2! top-1/2! -translate-x-1/2 -translate-y-1/2;
|
511
519
|
}
|
512
520
|
|
513
521
|
.calendar caption {
|
514
|
-
@apply font-
|
522
|
+
@apply font-semibold mb-3 py-3 text-important;
|
515
523
|
}
|
516
524
|
|
517
525
|
.calendar table {
|
@@ -519,7 +527,7 @@ fieldset details[open] > summary:after {
|
|
519
527
|
}
|
520
528
|
|
521
529
|
.calendar table th {
|
522
|
-
@apply font-
|
530
|
+
@apply font-semibold text-center text-important text-xs;
|
523
531
|
}
|
524
532
|
|
525
533
|
.calendar table td {
|
@@ -527,7 +535,7 @@ fieldset details[open] > summary:after {
|
|
527
535
|
}
|
528
536
|
|
529
537
|
.calendar table td a {
|
530
|
-
@apply block flex h-8 items-center justify-center rounded-full
|
538
|
+
@apply block flex h-8 items-center justify-center rounded-full w-8 dark:text-base-300;
|
531
539
|
}
|
532
540
|
|
533
541
|
.calendar table td a:hover {
|
@@ -543,7 +551,7 @@ fieldset details[open] > summary:after {
|
|
543
551
|
}
|
544
552
|
|
545
553
|
.calendar-shortcuts a {
|
546
|
-
@apply border border-base-200
|
554
|
+
@apply border border-base-200 font-medium leading-none mx-1 px-2 py-2 rounded-default shadow-xs text-center text-base-500 text-xs w-1/3 dark:border-base-700 dark:text-base-300 ;
|
547
555
|
}
|
548
556
|
|
549
557
|
.calendar-cancel {
|
@@ -554,28 +562,25 @@ fieldset details[open] > summary:after {
|
|
554
562
|
@apply absolute block ml-2 mt-2 left-0 text-[0px] top-0;
|
555
563
|
}
|
556
564
|
|
557
|
-
.calendarnav-next
|
558
|
-
.calendarnav-previous
|
559
|
-
@apply border border-base-200 flex h-7 items-center justify-center material-symbols-outlined rounded-full
|
565
|
+
.calendarnav-next,
|
566
|
+
.calendarnav-previous {
|
567
|
+
@apply after:border after:border-base-200 after:flex after:h-7 after:items-center after:justify-center after:material-symbols-outlined after:rounded-full after:transition-all after:w-7 dark:after:bg-base-800 dark:after:border-base-700;
|
568
|
+
}
|
560
569
|
|
570
|
+
.calendarnav-previous:after {
|
561
571
|
content: "navigate_before";
|
562
572
|
display: flex;
|
563
573
|
}
|
564
574
|
|
565
|
-
.calendarnav-next:
|
566
|
-
|
567
|
-
|
575
|
+
.calendarnav-next:after {
|
576
|
+
content: "navigate_next";
|
577
|
+
display: flex;
|
568
578
|
}
|
569
579
|
|
570
580
|
.calendarnav-next {
|
571
581
|
@apply absolute block mr-2 mt-2 right-0 text-[0px] top-0;
|
572
582
|
}
|
573
583
|
|
574
|
-
.calendarnav-next:after {
|
575
|
-
content: "navigate_next";
|
576
|
-
display: flex;
|
577
|
-
}
|
578
|
-
|
579
584
|
/*******************************************************
|
580
585
|
Timepicker
|
581
586
|
*******************************************************/
|
@@ -637,10 +642,6 @@ fieldset details[open] > summary:after {
|
|
637
642
|
@apply bg-primary-600 border-0 h-1;
|
638
643
|
}
|
639
644
|
|
640
|
-
#changelist-filter .admin-numeric-filter-slider-tooltips {
|
641
|
-
@apply flex flex-row font-medium mb-5 space-x-4 text-base-500 text-sm;
|
642
|
-
}
|
643
|
-
|
644
645
|
/*******************************************************
|
645
646
|
Trix
|
646
647
|
*******************************************************/
|
@@ -34,7 +34,7 @@
|
|
34
34
|
{% include adminform.model_admin.change_form_outer_before_template %}
|
35
35
|
{% endif %}
|
36
36
|
|
37
|
-
<form {% if adminform.model_admin.conditional_fields %}x-data='{{ adminform|changeform_data }}'{% endif %} {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}"{%
|
37
|
+
<form {% if adminform.model_admin.conditional_fields %}x-data='{{ adminform|changeform_data }}'{% endif %} {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}"{% endif %} x-bind:action="activeTab && activeTab !== 'general' ? window.location.pathname + window.location.search + '#' + activeTab : window.location.pathname + window.location.search" method="post" id="{{ opts.model_name }}_form" {% if adminform.model_admin.warn_unsaved_form %}class="warn-unsaved-form"{% endif %} novalidate>
|
38
38
|
{% csrf_token %}
|
39
39
|
|
40
40
|
{% if adminform.model_admin.change_form_before_template %}
|
@@ -99,6 +99,10 @@
|
|
99
99
|
{% endif %}
|
100
100
|
</form>
|
101
101
|
|
102
|
+
{% for dataset in datasets %}
|
103
|
+
{{ dataset.contents }}
|
104
|
+
{% endfor %}
|
105
|
+
|
102
106
|
{% if adminform.model_admin.change_form_outer_after_template %}
|
103
107
|
{% include adminform.model_admin.change_form_outer_after_template %}
|
104
108
|
{% endif %}
|
@@ -8,69 +8,11 @@
|
|
8
8
|
|
9
9
|
{% if results %}
|
10
10
|
<div class="{% if cl.search_fields or cl.has_filters %}lg:rounded-b-default{% else %}lg:rounded-default{% endif %} -mx-1 px-1 overflow-x-auto lg:border lg:border-base-200 lg:mx-0 lg:px-0 lg:shadow-xs lg:dark:border-base-800 lg:bg-white lg:dark:bg-base-900 {% if cl.model_admin.list_horizontal_scrollbar_top %}simplebar-horizontal-scrollbar-top{% endif %}" data-simplebar data-simplebar-auto-hide="false">
|
11
|
-
<table id="result_list" class="block border-base-200 border-spacing-none border-separate w-full lg:table">
|
12
|
-
|
13
|
-
<tr>
|
14
|
-
{% if cl.model_admin.list_sections|length > 0 %}
|
15
|
-
<th></th>
|
16
|
-
{% endif %}
|
17
|
-
|
18
|
-
{% for header in result_headers %}
|
19
|
-
<th class="align-middle font-semibold py-2 text-left text-font-important-light dark:text-font-important-dark whitespace-nowrap {{ header.class_attrib }} {% if "action-toggle" in header.text and forloop.counter == 1 %}lg:px-3 lg:w-10{% else %}hidden px-3 lg:table-cell{% endif %}" scope="col">
|
20
|
-
<div class="flex items-center">
|
21
|
-
<div class="text">
|
22
|
-
{% if header.sortable %}
|
23
|
-
<a href="{{ header.url_primary }}">
|
24
|
-
{{ header.text|capfirst }}
|
25
|
-
</a>
|
26
|
-
{% else %}
|
27
|
-
{% if "action-toggle" in header.text and forloop.counter == 1 %}
|
28
|
-
<label class="flex flex-row items-center gap-2">
|
29
|
-
{{ header.text|capfirst }}
|
30
|
-
|
31
|
-
<span class="block font-normal lg:hidden">
|
32
|
-
{% trans "Select all rows"%}
|
33
|
-
</span>
|
34
|
-
</label>
|
35
|
-
{% else %}
|
36
|
-
<span>
|
37
|
-
{{ header.text|capfirst }}
|
38
|
-
</span>
|
39
|
-
{% endif %}
|
40
|
-
{% endif %}
|
41
|
-
</div>
|
42
|
-
|
43
|
-
{% if header.sortable %}
|
44
|
-
{% if header.sort_priority > 0 %}
|
45
|
-
<div class="sortoptions flex items-center ml-2">
|
46
|
-
<a href="{{ header.url_toggle }}" class="flex items-center leading-none text-base-400 hover:text-base-500 dark:text-base-500 dark:hover:text-base-400 toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% translate "Toggle sorting" %}">
|
47
|
-
{% if header.ascending %}
|
48
|
-
<span class="block material-symbols-outlined">arrow_circle_down</span>
|
49
|
-
{% else %}
|
50
|
-
<span class="block material-symbols-outlined">arrow_circle_up</span>
|
51
|
-
{% endif %}
|
52
|
-
</a>
|
53
|
-
|
54
|
-
<a class="sortremove flex items-center leading-none ml-1 text-base-400 dark:text-base-500 transition-all hover:text-red-700 dark:hover:text-red-500" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}">
|
55
|
-
<span class="block material-symbols-outlined">cancel</span>
|
56
|
-
</a>
|
57
|
-
</div>
|
58
|
-
|
59
|
-
{% if num_sorted_fields > 1 %}
|
60
|
-
<span class="sortpriority font-medium ml-2 text-xs" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">
|
61
|
-
{{ header.sort_priority }}
|
62
|
-
</span>
|
63
|
-
{% endif %}
|
64
|
-
{% endif %}
|
65
|
-
{% endif %}
|
66
|
-
</div>
|
67
|
-
</th>
|
68
|
-
{% endfor %}
|
69
|
-
</tr>
|
70
|
-
</thead>
|
11
|
+
<table id="result_list" class="block border-base-200 border-spacing-none border-separate w-full lg:table" {% if cl.model_admin.ordering_field %}x-sort.ghost x-on:end="sortRecords"{% endif %} data-ordering-field="{{ cl.model_admin.ordering_field }}">
|
12
|
+
{% include 'unfold/helpers/change_list_headers.html' %}
|
71
13
|
|
72
14
|
{% for result in results %}
|
73
|
-
<tbody class="block relative lg:table-row-group lg:hover:shadow-raised lg:dark:hover:shadow-raised-dark lg:hover:z-20 {% cycle '' 'bg-base-50 dark:bg-white/[.02]' %}" x-data="{rowOpen: false}">
|
15
|
+
<tbody class="block relative lg:table-row-group lg:hover:shadow-raised lg:dark:hover:shadow-raised-dark lg:hover:z-20 {% cycle '' 'bg-base-50 dark:bg-white/[.02]' %}" x-data="{rowOpen: false}" {% if cl.model_admin.ordering_field %}x-sort:item{% endif %}>
|
74
16
|
{% if result.form and result.form.non_field_errors %}
|
75
17
|
<tr>
|
76
18
|
<td class="text-left" colspan="{{ result|length }}">
|
@@ -80,6 +22,12 @@
|
|
80
22
|
{% endif %}
|
81
23
|
|
82
24
|
<tr class="block border border-base-200 mb-3 relative rounded-default shadow-xs lg:table-row lg:border-none lg:mb-0 lg:rounded-none lg:shadow-none dark:border-base-800">
|
25
|
+
{% if cl.model_admin.ordering_field %}
|
26
|
+
<td class="align-middle cursor-move flex border-b border-base-200 font-normal px-2.5 py-2 relative text-left before:font-semibold before:text-font-important-light before:block before:capitalize before:content-[attr(data-label)] before:mr-auto lg:before:hidden lg:border-b-0 lg:border-t lg:pl-3 lg:pr-0 lg:py-3 lg:table-cell dark:border-base-800 dark:lg:border-base-800 dark:before:text-font-important-dark lg:w-px" x-sort:handle>
|
27
|
+
<span class="material-symbols-outlined align-middle cursor-move">drag_indicator</span>
|
28
|
+
</td>
|
29
|
+
{% endif %}
|
30
|
+
|
83
31
|
{% if cl.model_admin.list_sections|length > 0 %}
|
84
32
|
<td class="align-middle cursor-pointer flex border-b border-base-200 font-normal px-2.5 py-2 relative text-left before:font-semibold before:text-font-important-light before:block before:capitalize before:content-[attr(data-label)] before:mr-auto lg:before:hidden lg:border-b-0 lg:border-t lg:pl-3 lg:pr-0 lg:py-3 lg:table-cell dark:border-base-800 dark:lg:border-base-800 dark:before:text-font-important-dark lg:w-px"
|
85
33
|
data-label="{% trans "Expand row" %}"
|
@@ -100,7 +48,7 @@
|
|
100
48
|
|
101
49
|
{% if cl.model_admin.list_sections|length > 0 %}
|
102
50
|
<tr class="block mb-3 relative z-30 lg:table-row" x-show="rowOpen">
|
103
|
-
<td colspan="
|
51
|
+
<td colspan="100%" class="border bg-base-200/10 block border-base-200 relative rounded-default p-3 lg:shadow-inner lg:border-0 lg:border-t lg:rounded-none lg:table-cell dark:border-base-800">
|
104
52
|
<div class="absolute bg-primary-600 h-full hidden left-0 top-0 w-0.5 lg:block"></div>
|
105
53
|
|
106
54
|
<div class="grid gap-3 {{ cl.model_admin.list_sections_classes }}">
|
@@ -34,7 +34,7 @@
|
|
34
34
|
|
35
35
|
{% if inline_admin_formset.opts.ordering_field %}
|
36
36
|
{% if inline_admin_form.original %}
|
37
|
-
<span class="material-symbols-outlined cursor-
|
37
|
+
<span class="material-symbols-outlined cursor-move" x-sort:handle>drag_indicator</span>
|
38
38
|
{% else %}
|
39
39
|
<span class="-mr-2" x-sort:handle></span>
|
40
40
|
{% endif %}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
{% if cl.search_fields %}
|
4
4
|
<div id="toolbar">
|
5
|
-
<form id="changelist-search" method="get" role="search"
|
5
|
+
<form {% if not cl.is_dataset %}id="changelist-search" x-data="searchForm()"{% endif %} method="get" role="search">
|
6
6
|
<div class="bg-white border border-base-200 flex flex-row items-center px-3 rounded-default relative shadow-xs w-full focus-within:outline-2 focus-within:-outline-offset-2 focus-within:outline-primary-600 lg:w-96 dark:bg-base-900 dark:border-base-700">
|
7
7
|
<button type="submit" class="flex items-center focus:outline-hidden" id="searchbar-submit">
|
8
8
|
<span class="material-symbols-outlined md-18 text-base-400 dark:text-base-500">search</span>
|
@@ -14,10 +14,12 @@
|
|
14
14
|
class="grow font-medium min-w-0 overflow-hidden p-2 placeholder-font-subtle-light truncate focus:outline-hidden dark:bg-base-900 dark:placeholder-font-subtle-dark dark:text-font-default-dark"
|
15
15
|
name="{{ search_var }}"
|
16
16
|
value="{{ cl.query }}"
|
17
|
-
id="searchbar"
|
17
|
+
{% if not cl.is_dataset %}id="searchbar"{% endif %}
|
18
18
|
placeholder="{% if cl.search_help_text %}{{ cl.search_help_text }}{% else %}{% trans "Type to search" %}{% endif %}" />
|
19
19
|
|
20
|
-
{%
|
20
|
+
{% if not cl.is_dataset %}
|
21
|
+
{% include "unfold/helpers/shortcut.html" with shortcut="/" %}
|
22
|
+
{% endif %}
|
21
23
|
</div>
|
22
24
|
|
23
25
|
{% for pair in cl.filter_params.items %}
|
@@ -1,8 +1,17 @@
|
|
1
1
|
<{% if href %}a href="{{ href }}"{% else %}div{% endif %} class="bg-white block flex flex-col grow overflow-hidden p-6 relative rounded-default shadow-xs dark:bg-base-900 dark:border-base-800 {% if not disable_border %}border border-base-200 {% else %}shadow-base-500/20{% endif %} {% if href %}cursor-pointer transition-all hover:border-base-300 hover:shadow-md dark:hover:border-base-700 dark:hover:shadow-base-800/50 {% endif %}{% if class %} {{ class }}{% endif %}">
|
2
|
+
|
2
3
|
{% if title %}
|
3
|
-
<
|
4
|
-
|
5
|
-
|
4
|
+
<div class="border-b border-base-200 flex flex-row items-center mb-6 -mt-6 -mx-6 py-4 px-6 dark:border-base-800">
|
5
|
+
<h2 class="font-semibold text-[15px] text-important">
|
6
|
+
{{ title }}
|
7
|
+
</h2>
|
8
|
+
|
9
|
+
{% if action %}
|
10
|
+
<div class="ml-auto">
|
11
|
+
{{ action }}
|
12
|
+
</div>
|
13
|
+
{% endif %}
|
14
|
+
</div>
|
6
15
|
{% endif %}
|
7
16
|
|
8
17
|
<div class="grow relative{% if icon %} pl-8{% endif %}">
|
@@ -15,9 +15,15 @@
|
|
15
15
|
</div>
|
16
16
|
{% endif %}
|
17
17
|
|
18
|
-
{% if value %}
|
19
|
-
<div class="bg-base-100 overflow-hidden rounded-default dark:bg-base-800">
|
20
|
-
|
18
|
+
{% if items or value %}
|
19
|
+
<div class="bg-base-100 flex flex-row overflow-hidden rounded-default dark:bg-base-800">
|
20
|
+
{% if items %}
|
21
|
+
{% for item in items %}
|
22
|
+
<div class="h-1.5 bg-primary-600 z-10 dark:bg-primary-500 last:rounded-r-default {{ item.progress_class }}" title="{% if item.title %}{{ item.title }}: {% endif %}{{ item.value }}%" style="width: {{ item.value }}%"></div>
|
23
|
+
{% endfor %}
|
24
|
+
{% elif value %}
|
25
|
+
<div class="h-1.5 bg-primary-600 rounded-default z-10 last:rounded-r-default dark:bg-primary-500 {{ progress_class }}" title="{% if title %}{{ title }}: {% endif %}{{ value }}%" style="width: {{ value }}%"></div>
|
26
|
+
{% endif %}
|
21
27
|
</div>
|
22
28
|
{% endif %}
|
23
29
|
</div>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
{% load i18n %}
|
2
|
+
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
{% if cl.model_admin.ordering_field %}
|
6
|
+
<th></th>
|
7
|
+
{% endif %}
|
8
|
+
|
9
|
+
{% if cl.model_admin.list_sections|length > 0 %}
|
10
|
+
<th></th>
|
11
|
+
{% endif %}
|
12
|
+
|
13
|
+
{% for header in result_headers %}
|
14
|
+
<th class="align-middle font-semibold py-2 text-left text-font-important-light dark:text-font-important-dark whitespace-nowrap {{ header.class_attrib }} {% if "action-toggle" in header.text and forloop.counter == 1 %}lg:px-3 lg:w-10{% else %}hidden px-3 lg:table-cell{% endif %}" scope="col">
|
15
|
+
<div class="flex items-center">
|
16
|
+
<div class="text">
|
17
|
+
{% if header.sortable %}
|
18
|
+
<a href="{{ header.url_primary }}">
|
19
|
+
{{ header.text|capfirst }}
|
20
|
+
</a>
|
21
|
+
{% else %}
|
22
|
+
{% if "action-toggle" in header.text and forloop.counter == 1 %}
|
23
|
+
<label class="flex flex-row items-center gap-2">
|
24
|
+
{{ header.text|capfirst }}
|
25
|
+
|
26
|
+
<span class="block font-normal lg:hidden">
|
27
|
+
{% trans "Select all rows"%}
|
28
|
+
</span>
|
29
|
+
</label>
|
30
|
+
{% else %}
|
31
|
+
<span>
|
32
|
+
{{ header.text|capfirst }}
|
33
|
+
</span>
|
34
|
+
{% endif %}
|
35
|
+
{% endif %}
|
36
|
+
</div>
|
37
|
+
|
38
|
+
{% if header.sortable %}
|
39
|
+
{% if header.sort_priority > 0 %}
|
40
|
+
<div class="sortoptions flex items-center ml-2">
|
41
|
+
<a href="{{ header.url_toggle }}" class="flex items-center leading-none text-base-400 hover:text-base-500 dark:text-base-500 dark:hover:text-base-400 toggle {% if header.ascending %}ascending{% else %}descending{% endif %}" title="{% translate "Toggle sorting" %}">
|
42
|
+
{% if header.ascending %}
|
43
|
+
<span class="block material-symbols-outlined">arrow_circle_down</span>
|
44
|
+
{% else %}
|
45
|
+
<span class="block material-symbols-outlined">arrow_circle_up</span>
|
46
|
+
{% endif %}
|
47
|
+
</a>
|
48
|
+
|
49
|
+
<a class="sortremove flex items-center leading-none ml-1 text-base-400 dark:text-base-500 transition-all hover:text-red-700 dark:hover:text-red-500" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}">
|
50
|
+
<span class="block material-symbols-outlined">cancel</span>
|
51
|
+
</a>
|
52
|
+
</div>
|
53
|
+
|
54
|
+
{% if num_sorted_fields > 1 %}
|
55
|
+
<span class="sortpriority font-medium ml-2 text-xs" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">
|
56
|
+
{{ header.sort_priority }}
|
57
|
+
</span>
|
58
|
+
{% endif %}
|
59
|
+
{% endif %}
|
60
|
+
{% endif %}
|
61
|
+
</div>
|
62
|
+
</th>
|
63
|
+
{% endfor %}
|
64
|
+
</tr>
|
65
|
+
</thead>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{% load admin_list unfold_list %}
|
2
|
+
|
3
|
+
<div {% if cl.model_admin.tab %}x-show="activeTab == 'dataset-{{ dataset.model_name }}'"{% endif %}>
|
4
|
+
{% if not cl.model_admin.tab %}
|
5
|
+
<h2 class="inline-heading bg-base-100 font-semibold mb-6 px-4 py-3 rounded-default text-font-important-light @min-[1570px]:-mx-4 dark:bg-white/[.02] dark:text-font-important-dark">
|
6
|
+
{{ dataset.model_verbose_name|capfirst }}
|
7
|
+
</h2>
|
8
|
+
{% endif %}
|
9
|
+
|
10
|
+
{% if cl.search_fields %}
|
11
|
+
<div class="flex flex-col gap-4 mb-4 sm:flex-row empty:hidden lg:border lg:border-base-200 lg:dark:border-base-800 lg:-mb-8 lg:p-3 lg:pb-11 lg:rounded-t-default">
|
12
|
+
{% unfold_search_form cl %}
|
13
|
+
</div>
|
14
|
+
{% endif %}
|
15
|
+
|
16
|
+
{% unfold_result_list cl %}
|
17
|
+
|
18
|
+
{% pagination cl %}
|
19
|
+
</div>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
{% if forloop.parentloop.counter == 1 and forloop.counter == 1 %}
|
3
3
|
{% if inline_admin_formset.opts.ordering_field %}
|
4
4
|
{% if inline_admin_form.original %}
|
5
|
-
<span class="material-symbols-outlined cursor-
|
5
|
+
<span class="material-symbols-outlined cursor-move" x-sort:handle>drag_indicator</span>
|
6
6
|
{% else %}
|
7
7
|
<span class="-mr-3" x-sort:handle></span>
|
8
8
|
{% endif %}
|
@@ -3,10 +3,12 @@
|
|
3
3
|
{% url cl.opts|admin_urlname:"add" as add_url %}
|
4
4
|
{% blocktranslate with name=cl.opts.verbose_name asvar title %}Add {{ name }}{% endblocktranslate %}
|
5
5
|
|
6
|
-
<div class="bg-white border border-base-200 flex flex-col items-center px-8
|
7
|
-
|
8
|
-
<
|
9
|
-
|
6
|
+
<div class="bg-white border border-base-200 flex flex-col items-center px-8 shadow-xs dark:bg-base-900 dark:border-base-800 {% if cl.search_fields %}rounded-b-default{% else %}rounded-default{% endif %} {% if cl.is_dataset %}py-16{% else %}py-24{% endif %}">
|
7
|
+
{% if not cl.is_dataset %}
|
8
|
+
<div class="border border-base-300 border-dashed flex h-24 items-center justify-center mb-8 rounded-full w-24 dark:border-base-700">
|
9
|
+
<span class="material-symbols-outlined text-base-500 text-5xl! dark:text-base-400">inbox</span>
|
10
|
+
</div>
|
11
|
+
{% endif %}
|
10
12
|
|
11
13
|
<h2 class="font-semibold mb-1 text-xl text-font-important-light tracking-tight dark:text-font-important-dark">
|
12
14
|
{% trans "No results found" %}
|
@@ -1 +1 @@
|
|
1
|
-
<div class="readonly break-words {% if field.is_json %}max-w-4xl{% else %}max-w-2xl{% endif %} py-2 text-sm *:rounded-default {% if not adminform.model_admin.compressed_fields and not field.is_image %}bg-base-50 border border-base-200 font-medium px-3 rounded-default shadow-xs dark:border-base-700 dark:bg-base-800{% endif %}
|
1
|
+
<div class="readonly break-words {% if field.is_json %}max-w-4xl{% else %}max-w-2xl{% endif %} py-2 text-sm *:rounded-default {% if not adminform.model_admin.compressed_fields and not field.is_image %}bg-base-50 border border-base-200 font-medium px-3 rounded-default shadow-xs dark:border-base-700 dark:bg-base-800{% endif %}">{% if value %}{{ value }}{% elif field.contents %}{% if field.is_file %}{% include "unfold/helpers/field_readonly_value_file.html" %}{% else %}{{ field.contents }}{% endif %}{% else %}-{% endif %}</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
{% load i18n %}
|
2
|
+
|
3
|
+
{% with url=field.url %}
|
4
|
+
{% if not url %}
|
5
|
+
<span class="flex items-center">-</span>
|
6
|
+
{% elif field.is_image %}
|
7
|
+
<a href="{{ url }}" target="_blank" class="block max-w-48">
|
8
|
+
<img src="{{ url }}" alt="{% trans 'Image preview' %}" class="block rounded-default" />
|
9
|
+
</a>
|
10
|
+
{% else %}
|
11
|
+
<a href="{{ url }}" target="_blank">
|
12
|
+
<span class="flex items-center gap-2">
|
13
|
+
<span class="text-primary-600 dark:text-primary-500">{% trans "Click to download" %}</span>
|
14
|
+
<span class="material-symbols-outlined text-base-400 dark:text-base-500">download</span>
|
15
|
+
</span>
|
16
|
+
</a>
|
17
|
+
{% endif %}
|
18
|
+
{% endwith %}
|
@@ -24,6 +24,12 @@
|
|
24
24
|
{% endif %}
|
25
25
|
</a>
|
26
26
|
{% endfor %}
|
27
|
+
|
28
|
+
{% for dataset in datasets_list %}
|
29
|
+
<a href="#dataset-{{ dataset.model_name }}" x-on:click="activeTab = 'dataset-{{ dataset.model_name }}'" x-bind:class="{'active': activeTab == 'dataset-{{ dataset.model_name }}'}">
|
30
|
+
{{ dataset.model_verbose_name|capfirst }}
|
31
|
+
</a>
|
32
|
+
{% endfor %}
|
27
33
|
{% endif %}
|
28
34
|
</nav>
|
29
35
|
{% endif %}
|