adminita 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.
- adminita/__init__.py +0 -0
- adminita/apps.py +7 -0
- adminita/static/adminita/adminita-tailwind.css +2 -0
- adminita/static/adminita/adminita-tailwind.js +101 -0
- adminita/static/css/output.css +2700 -0
- adminita/static/src/input.css +370 -0
- adminita/templates/admin/base.html +173 -0
- adminita/templates/admin/change_form.html +185 -0
- adminita/templates/admin/change_list.html +175 -0
- adminita/templates/admin/index.html +120 -0
- adminita/templates/admin/logged_out.html +103 -0
- adminita/templates/admin/login.html +142 -0
- adminita/utils.py +70 -0
- adminita-0.1.0.dist-info/METADATA +416 -0
- adminita-0.1.0.dist-info/RECORD +18 -0
- adminita-0.1.0.dist-info/WHEEL +5 -0
- adminita-0.1.0.dist-info/licenses/LICENSE +21 -0
- adminita-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{% extends "admin/base.html" %}
|
|
2
|
+
{% load i18n admin_urls static admin_modify %}
|
|
3
|
+
|
|
4
|
+
{% block content_title %}
|
|
5
|
+
{% if add %}
|
|
6
|
+
{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}
|
|
7
|
+
{% else %}
|
|
8
|
+
{% blocktrans with name=opts.verbose_name %}Change {{ name }}{% endblocktrans %}
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% endblock %}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
{% block content %}
|
|
14
|
+
<form method="post" id="{{ opts.model_name }}_form" enctype="multipart/form-data" class="space-y-6">
|
|
15
|
+
{% csrf_token %}
|
|
16
|
+
|
|
17
|
+
{% if errors %}
|
|
18
|
+
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
|
19
|
+
<div class="flex items-start">
|
|
20
|
+
<svg class="w-5 h-5 text-red-600 dark:text-red-400 mt-0.5 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
21
|
+
<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"/>
|
|
22
|
+
</svg>
|
|
23
|
+
<div>
|
|
24
|
+
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">
|
|
25
|
+
{% trans "Please correct the errors below." %}
|
|
26
|
+
</h3>
|
|
27
|
+
{{ adminform.form.non_field_errors }}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
{% endif %}
|
|
32
|
+
|
|
33
|
+
<!-- Main Form -->
|
|
34
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
35
|
+
{% block field_sets %}
|
|
36
|
+
{% for fieldset in adminform %}
|
|
37
|
+
<div class="{% if not forloop.first %}border-t border-gray-200 dark:border-gray-700{% endif %}">
|
|
38
|
+
{% if fieldset.name %}
|
|
39
|
+
<div class="px-6 py-4 bg-gray-50 dark:bg-gray-750">
|
|
40
|
+
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
|
41
|
+
{{ fieldset.name }}
|
|
42
|
+
</h2>
|
|
43
|
+
{% if fieldset.description %}
|
|
44
|
+
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
|
45
|
+
{{ fieldset.description|safe }}
|
|
46
|
+
</p>
|
|
47
|
+
{% endif %}
|
|
48
|
+
</div>
|
|
49
|
+
{% endif %}
|
|
50
|
+
|
|
51
|
+
<div class="px-6 py-6 space-y-6">
|
|
52
|
+
{% for line in fieldset %}
|
|
53
|
+
<div class="{% if line.fields|length > 1 %}grid grid-cols-1 md:grid-cols-{{ line.fields|length }} gap-6{% endif %}">
|
|
54
|
+
{% for field in line %}
|
|
55
|
+
<div class="{% if field.is_readonly %}opacity-75{% endif %}">
|
|
56
|
+
<label for="{{ field.field.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
|
57
|
+
{{ field.field.label }}
|
|
58
|
+
{% if field.field.field.required %}
|
|
59
|
+
<span class="text-red-600 dark:text-red-400">*</span>
|
|
60
|
+
{% endif %}
|
|
61
|
+
</label>
|
|
62
|
+
|
|
63
|
+
{% if field.is_readonly %}
|
|
64
|
+
<div class="px-3 py-2 bg-gray-50 dark:bg-gray-750 border border-gray-300 dark:border-gray-600 rounded-lg text-gray-900 dark:text-gray-100">
|
|
65
|
+
{{ field.contents|default:"" }}
|
|
66
|
+
</div>
|
|
67
|
+
{% else %}
|
|
68
|
+
{{ field.field }}
|
|
69
|
+
{% endif %}
|
|
70
|
+
|
|
71
|
+
{% if field.field.help_text %}
|
|
72
|
+
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
73
|
+
{{ field.field.help_text|safe }}
|
|
74
|
+
</p>
|
|
75
|
+
{% endif %}
|
|
76
|
+
|
|
77
|
+
{% if field.field.errors %}
|
|
78
|
+
<div class="mt-2 text-sm text-red-600 dark:text-red-400">
|
|
79
|
+
{{ field.field.errors }}
|
|
80
|
+
</div>
|
|
81
|
+
{% endif %}
|
|
82
|
+
</div>
|
|
83
|
+
{% endfor %}
|
|
84
|
+
</div>
|
|
85
|
+
{% endfor %}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
{% endfor %}
|
|
89
|
+
{% endblock %}
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<!-- Inline Forms -->
|
|
93
|
+
{% block inline_field_sets %}
|
|
94
|
+
{% for inline_admin_formset in inline_admin_formsets %}
|
|
95
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
96
|
+
<div class="px-6 py-4 bg-gray-50 dark:bg-gray-750 border-b border-gray-200 dark:border-gray-700">
|
|
97
|
+
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
|
98
|
+
{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}
|
|
99
|
+
</h2>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class="p-6">
|
|
103
|
+
{{ inline_admin_formset.formset.management_form }}
|
|
104
|
+
|
|
105
|
+
{% for inline_admin_form in inline_admin_formset %}
|
|
106
|
+
<div class="mb-6 pb-6 border-b border-gray-200 dark:border-gray-700 last:border-b-0 last:mb-0 last:pb-0">
|
|
107
|
+
{{ inline_admin_form.form.non_field_errors }}
|
|
108
|
+
|
|
109
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
110
|
+
{% for fieldset in inline_admin_form %}
|
|
111
|
+
{% for line in fieldset %}
|
|
112
|
+
{% for field in line %}
|
|
113
|
+
<div>
|
|
114
|
+
<label for="{{ field.field.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
|
115
|
+
{{ field.field.label }}
|
|
116
|
+
</label>
|
|
117
|
+
{{ field.field }}
|
|
118
|
+
|
|
119
|
+
{% if field.field.errors %}
|
|
120
|
+
<div class="mt-2 text-sm text-red-600 dark:text-red-400">
|
|
121
|
+
{{ field.field.errors }}
|
|
122
|
+
</div>
|
|
123
|
+
{% endif %}
|
|
124
|
+
</div>
|
|
125
|
+
{% endfor %}
|
|
126
|
+
{% endfor %}
|
|
127
|
+
{% endfor %}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
{% endfor %}
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
{% endfor %}
|
|
134
|
+
{% endblock %}
|
|
135
|
+
|
|
136
|
+
<!-- Submit Buttons -->
|
|
137
|
+
<div class="flex items-center justify-between bg-gray-50 dark:bg-gray-800 px-6 py-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
138
|
+
<div class="flex items-center space-x-3">
|
|
139
|
+
<button type="submit" name="_save" class="inline-flex items-center px-6 py-2.5 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors">
|
|
140
|
+
{% trans 'Save' %}
|
|
141
|
+
</button>
|
|
142
|
+
|
|
143
|
+
{% if show_save_and_add_another %}
|
|
144
|
+
<button type="submit" name="_addanother" class="inline-flex items-center px-4 py-2.5 bg-gray-600 hover:bg-gray-700 text-white rounded-lg font-medium transition-colors">
|
|
145
|
+
{% trans 'Save and add another' %}
|
|
146
|
+
</button>
|
|
147
|
+
{% endif %}
|
|
148
|
+
|
|
149
|
+
{% if show_save_and_continue %}
|
|
150
|
+
<button type="submit" name="_continue" class="inline-flex items-center px-4 py-2.5 bg-gray-600 hover:bg-gray-700 text-white rounded-lg font-medium transition-colors">
|
|
151
|
+
{% trans 'Save and continue editing' %}
|
|
152
|
+
</button>
|
|
153
|
+
{% endif %}
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<div class="flex items-center space-x-3">
|
|
157
|
+
{% if show_delete_link %}
|
|
158
|
+
<a href="{% url opts|admin_urlname:'delete' original.pk|admin_urlquote %}" class="inline-flex items-center px-4 py-2.5 bg-red-600 hover:bg-red-700 text-white rounded-lg font-medium transition-colors">
|
|
159
|
+
{% trans 'Delete' %}
|
|
160
|
+
</a>
|
|
161
|
+
{% endif %}
|
|
162
|
+
|
|
163
|
+
<a href="{% url opts|admin_urlname:'changelist' %}" class="inline-flex items-center px-4 py-2.5 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg font-medium transition-colors">
|
|
164
|
+
{% trans 'Cancel' %}
|
|
165
|
+
</a>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</form>
|
|
169
|
+
{% endblock %}
|
|
170
|
+
|
|
171
|
+
{% block extrastyle %}
|
|
172
|
+
{{ block.super }}
|
|
173
|
+
{{ adminform.form.media.css }}
|
|
174
|
+
{% endblock %}
|
|
175
|
+
|
|
176
|
+
{% block extrajs %}
|
|
177
|
+
{{ block.super }}
|
|
178
|
+
<script src="{% url 'admin:jsi18n' %}"></script>
|
|
179
|
+
<script src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
|
|
180
|
+
<script src="{% static 'admin/js/jquery.init.js' %}"></script>
|
|
181
|
+
<script src="{% static 'admin/js/urlify.js' %}"></script>
|
|
182
|
+
<script src="{% static 'admin/js/prepopulate.js' %}"></script>
|
|
183
|
+
{{ media.js }}
|
|
184
|
+
{% if add %}{% prepopulated_fields_js %}{% endif %}
|
|
185
|
+
{% endblock %}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
{% extends "admin/base.html" %}
|
|
2
|
+
{% load i18n admin_urls static admin_list %}
|
|
3
|
+
|
|
4
|
+
{% block content_title %}
|
|
5
|
+
{% if cl.opts.verbose_name_plural %}
|
|
6
|
+
{{ cl.opts.verbose_name_plural|capfirst }}
|
|
7
|
+
{% else %}
|
|
8
|
+
{{ cl.opts.verbose_name|capfirst }}
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% endblock %}
|
|
11
|
+
|
|
12
|
+
{% block extrastyle %}
|
|
13
|
+
{{ block.super }}
|
|
14
|
+
{{ media.css }}
|
|
15
|
+
|
|
16
|
+
{% endblock %}
|
|
17
|
+
|
|
18
|
+
{% block content %}
|
|
19
|
+
<div class="flex gap-6">
|
|
20
|
+
|
|
21
|
+
<!-- MAIN CONTENT AREA -->
|
|
22
|
+
<div class="flex-1">
|
|
23
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
24
|
+
|
|
25
|
+
<!-- Toolbar -->
|
|
26
|
+
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex flex-wrap items-center justify-between gap-4">
|
|
27
|
+
|
|
28
|
+
<!-- Search -->
|
|
29
|
+
<div class="flex-1 min-w-[300px]">
|
|
30
|
+
{% block search %}
|
|
31
|
+
{% if cl.search_fields %}
|
|
32
|
+
<form id="changelist-search" method="get" class="flex items-center space-x-2">
|
|
33
|
+
<div class="relative flex-1">
|
|
34
|
+
<input type="search"
|
|
35
|
+
name="{{ search_var }}"
|
|
36
|
+
value="{{ cl.query }}"
|
|
37
|
+
placeholder="{% trans 'Search' %}"
|
|
38
|
+
class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
|
39
|
+
<svg class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
40
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
41
|
+
</svg>
|
|
42
|
+
</div>
|
|
43
|
+
<button type="submit" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors">
|
|
44
|
+
{% trans 'Search' %}
|
|
45
|
+
</button>
|
|
46
|
+
</form>
|
|
47
|
+
{% endif %}
|
|
48
|
+
{% endblock %}
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- Actions -->
|
|
52
|
+
<div class="flex items-center space-x-3">
|
|
53
|
+
{% block object-tools %}
|
|
54
|
+
{% if has_add_permission %}
|
|
55
|
+
<a href="{% url cl.opts|admin_urlname:'add' %}" class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors">
|
|
56
|
+
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
57
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
|
58
|
+
</svg>
|
|
59
|
+
{% trans 'Add' %} {{ cl.opts.verbose_name }}
|
|
60
|
+
</a>
|
|
61
|
+
{% endif %}
|
|
62
|
+
{% endblock %}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<!-- Results -->
|
|
67
|
+
<div class="overflow-x-auto">
|
|
68
|
+
{% block result_list %}
|
|
69
|
+
{% if cl.result_count %}
|
|
70
|
+
{% result_list cl %}
|
|
71
|
+
{% else %}
|
|
72
|
+
<div class="px-6 py-12 text-center">
|
|
73
|
+
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
74
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
75
|
+
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/>
|
|
76
|
+
</svg>
|
|
77
|
+
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
|
78
|
+
{% trans 'No results found' %}
|
|
79
|
+
</p>
|
|
80
|
+
</div>
|
|
81
|
+
{% endif %}
|
|
82
|
+
{% endblock %}
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<!-- Pagination -->
|
|
86
|
+
{% if cl.result_count %}
|
|
87
|
+
<div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
|
88
|
+
<div class="text-sm text-gray-700 dark:text-gray-300">
|
|
89
|
+
{% if cl.result_count == 1 %}
|
|
90
|
+
1 {{ cl.opts.verbose_name }}
|
|
91
|
+
{% else %}
|
|
92
|
+
{{ cl.result_count }} {{ cl.opts.verbose_name_plural }}
|
|
93
|
+
{% endif %}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{% block pagination %}
|
|
97
|
+
{% if cl.can_show_all or cl.multi_page %}
|
|
98
|
+
<div class="flex items-center space-x-2">
|
|
99
|
+
{% if cl.can_show_all %}
|
|
100
|
+
<a href="?{% if cl.is_popup %}_popup=1&{% endif %}all="
|
|
101
|
+
class="px-3 py-1 text-sm text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
|
102
|
+
{% trans 'Show all' %}
|
|
103
|
+
</a>
|
|
104
|
+
{% endif %}
|
|
105
|
+
|
|
106
|
+
{% if cl.multi_page %}
|
|
107
|
+
<nav class="flex items-center space-x-1">
|
|
108
|
+
{% if cl.page_num > 0 %}
|
|
109
|
+
<a href="?p={{ cl.page_num|add:'-1' }}"
|
|
110
|
+
class="px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
|
|
111
|
+
{% trans 'Previous' %}
|
|
112
|
+
</a>
|
|
113
|
+
{% endif %}
|
|
114
|
+
|
|
115
|
+
<span class="px-3 py-1 text-sm text-gray-700 dark:text-gray-300">
|
|
116
|
+
{% blocktrans with page_num=cl.page_num|add:1 num_pages=cl.paginator.num_pages %}
|
|
117
|
+
Page {{ page_num }} of {{ num_pages }}
|
|
118
|
+
{% endblocktrans %}
|
|
119
|
+
</span>
|
|
120
|
+
|
|
121
|
+
{% if cl.page_num < cl.paginator.num_pages|add:"-1" %}
|
|
122
|
+
<a href="?p={{ cl.page_num|add:1 }}"
|
|
123
|
+
class="px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
|
|
124
|
+
{% trans 'Next' %}
|
|
125
|
+
</a>
|
|
126
|
+
{% endif %}
|
|
127
|
+
</nav>
|
|
128
|
+
{% endif %}
|
|
129
|
+
</div>
|
|
130
|
+
{% endif %}
|
|
131
|
+
{% endblock %}
|
|
132
|
+
</div>
|
|
133
|
+
{% endif %}
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<!-- FILTER SIDEBAR -->
|
|
138
|
+
{% if cl.has_filters %}
|
|
139
|
+
<div class="w-64 flex-shrink-0">
|
|
140
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 sticky top-20">
|
|
141
|
+
<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-750">
|
|
142
|
+
<h3 class="text-sm font-semibold text-gray-900 dark:text-white uppercase tracking-wider">
|
|
143
|
+
{% trans 'Filter' %}
|
|
144
|
+
</h3>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="p-4 space-y-4">
|
|
147
|
+
{% for spec in cl.filter_specs %}
|
|
148
|
+
<div>
|
|
149
|
+
<h4 class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2">
|
|
150
|
+
{{ spec.title }}
|
|
151
|
+
</h4>
|
|
152
|
+
<ul class="space-y-1">
|
|
153
|
+
{% for choice in spec.choices %}
|
|
154
|
+
<li>
|
|
155
|
+
<a href="{{ choice.query_string }}"
|
|
156
|
+
class="block px-2 py-1 text-sm rounded transition-colors {% if choice.selected %}bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 font-medium{% else %}text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700{% endif %}">
|
|
157
|
+
{{ choice.display }}
|
|
158
|
+
</a>
|
|
159
|
+
</li>
|
|
160
|
+
{% endfor %}
|
|
161
|
+
</ul>
|
|
162
|
+
</div>
|
|
163
|
+
{% endfor %}
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
{% endif %}
|
|
168
|
+
|
|
169
|
+
</div>
|
|
170
|
+
{% endblock %}
|
|
171
|
+
|
|
172
|
+
{% block extrajs %}
|
|
173
|
+
{{ block.super }}
|
|
174
|
+
{{ media.js }}
|
|
175
|
+
{% endblock %}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{% extends "admin/base.html" %}
|
|
2
|
+
{% load i18n static log %}
|
|
3
|
+
|
|
4
|
+
{% block content_title %}
|
|
5
|
+
{{ title }}
|
|
6
|
+
{% endblock %}
|
|
7
|
+
|
|
8
|
+
{% block content %}
|
|
9
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
10
|
+
{% if app_list %}
|
|
11
|
+
{% for app in app_list %}
|
|
12
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden hover:shadow-md transition-shadow">
|
|
13
|
+
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-750">
|
|
14
|
+
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
|
15
|
+
{{ app.name }}
|
|
16
|
+
</h2>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="p-4">
|
|
20
|
+
<ul class="space-y-2">
|
|
21
|
+
{% for model in app.models %}
|
|
22
|
+
<li>
|
|
23
|
+
<a href="{{ model.admin_url }}" class="group flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">
|
|
24
|
+
<span class="text-sm font-medium text-gray-700 dark:text-gray-300 group-hover:text-blue-600 dark:group-hover:text-blue-400">
|
|
25
|
+
{{ model.name }}
|
|
26
|
+
</span>
|
|
27
|
+
<svg class="w-5 h-5 text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
28
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
29
|
+
</svg>
|
|
30
|
+
</a>
|
|
31
|
+
|
|
32
|
+
{% if model.add_url or model.change_url %}
|
|
33
|
+
<div class="ml-3 mt-1 flex items-center space-x-4 text-xs">
|
|
34
|
+
{% if model.add_url %}
|
|
35
|
+
<a href="{{ model.add_url }}" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
|
36
|
+
+ {% trans 'Add' %}
|
|
37
|
+
</a>
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
40
|
+
{% if model.change_url %}
|
|
41
|
+
<a href="{{ model.change_url }}" class="text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
|
42
|
+
{% trans 'Change' %}
|
|
43
|
+
</a>
|
|
44
|
+
{% endif %}
|
|
45
|
+
</div>
|
|
46
|
+
{% endif %}
|
|
47
|
+
</li>
|
|
48
|
+
{% endfor %}
|
|
49
|
+
</ul>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
{% endfor %}
|
|
53
|
+
{% else %}
|
|
54
|
+
<div class="col-span-full">
|
|
55
|
+
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-8 text-center">
|
|
56
|
+
<p class="text-gray-600 dark:text-gray-400">
|
|
57
|
+
{% trans "You don't have permission to view or edit anything." %}
|
|
58
|
+
</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
{% endif %}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
{% if app_list %}
|
|
65
|
+
<div class="mt-8 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800 p-6">
|
|
66
|
+
<div class="flex items-start space-x-3">
|
|
67
|
+
<svg class="w-6 h-6 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
68
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
69
|
+
</svg>
|
|
70
|
+
<div class="flex-1">
|
|
71
|
+
<h3 class="text-sm font-semibold text-blue-900 dark:text-blue-200 mb-2">
|
|
72
|
+
{% trans 'Recent actions' %}
|
|
73
|
+
</h3>
|
|
74
|
+
{% get_admin_log 10 as admin_log for_user user %}
|
|
75
|
+
{% if admin_log %}
|
|
76
|
+
<ul class="text-sm text-blue-800 dark:text-blue-300 space-y-2">
|
|
77
|
+
{% for entry in admin_log %}
|
|
78
|
+
<li class="flex items-start space-x-2">
|
|
79
|
+
{% if entry.is_addition %}
|
|
80
|
+
<span class="inline-flex items-center justify-center w-5 h-5 rounded-full bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400 flex-shrink-0 mt-0.5">
|
|
81
|
+
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
|
82
|
+
<path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd"/>
|
|
83
|
+
</svg>
|
|
84
|
+
</span>
|
|
85
|
+
{% elif entry.is_change %}
|
|
86
|
+
<span class="inline-flex items-center justify-center w-5 h-5 rounded-full bg-yellow-100 dark:bg-yellow-900/30 text-yellow-600 dark:text-yellow-400 flex-shrink-0 mt-0.5">
|
|
87
|
+
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
|
88
|
+
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z"/>
|
|
89
|
+
</svg>
|
|
90
|
+
</span>
|
|
91
|
+
{% elif entry.is_deletion %}
|
|
92
|
+
<span class="inline-flex items-center justify-center w-5 h-5 rounded-full bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5">
|
|
93
|
+
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
|
94
|
+
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
|
|
95
|
+
</svg>
|
|
96
|
+
</span>
|
|
97
|
+
{% endif %}
|
|
98
|
+
<span>
|
|
99
|
+
{% if entry.is_deletion or not entry.get_admin_url %}
|
|
100
|
+
{{ entry.object_repr }}
|
|
101
|
+
{% else %}
|
|
102
|
+
<a href="{{ entry.get_admin_url }}" class="text-blue-600 dark:text-blue-400 hover:underline">{{ entry.object_repr }}</a>
|
|
103
|
+
{% endif %}
|
|
104
|
+
{% if entry.content_type %}
|
|
105
|
+
<span class="text-blue-600/70 dark:text-blue-300/70">({{ entry.content_type }})</span>
|
|
106
|
+
{% endif %}
|
|
107
|
+
</span>
|
|
108
|
+
</li>
|
|
109
|
+
{% endfor %}
|
|
110
|
+
</ul>
|
|
111
|
+
{% else %}
|
|
112
|
+
<p class="text-sm text-blue-800 dark:text-blue-300">
|
|
113
|
+
{% trans 'None available' %}
|
|
114
|
+
</p>
|
|
115
|
+
{% endif %}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
{% endif %}
|
|
120
|
+
{% endblock %}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{% load i18n static %}
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" class="h-full">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>{% trans 'Logged out' %} | {{ site_title }}</title>
|
|
8
|
+
<link rel="stylesheet" href="{% static 'adminita/adminita-tailwind.css' %}">
|
|
9
|
+
|
|
10
|
+
{# Dark mode initialization #}
|
|
11
|
+
<script>
|
|
12
|
+
(function() {
|
|
13
|
+
const isDark = localStorage.getItem('darkMode') === 'true' ||
|
|
14
|
+
(!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
|
15
|
+
|
|
16
|
+
if (isDark) {
|
|
17
|
+
document.documentElement.classList.add('dark');
|
|
18
|
+
}
|
|
19
|
+
})();
|
|
20
|
+
</script>
|
|
21
|
+
</head>
|
|
22
|
+
|
|
23
|
+
<body class="h-full bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800">
|
|
24
|
+
|
|
25
|
+
<div class="min-h-full flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
|
26
|
+
<div class="max-w-md w-full">
|
|
27
|
+
|
|
28
|
+
<!-- Logo/Header -->
|
|
29
|
+
<div class="text-center mb-8">
|
|
30
|
+
<div class="w-16 h-16 bg-gradient-to-br from-blue-600 to-indigo-600 rounded-2xl flex items-center justify-center mx-auto mb-4">
|
|
31
|
+
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
32
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
|
|
33
|
+
</svg>
|
|
34
|
+
</div>
|
|
35
|
+
<h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
|
36
|
+
{% trans 'Logged out successfully' %}
|
|
37
|
+
</h1>
|
|
38
|
+
<p class="text-sm text-gray-600 dark:text-gray-400">
|
|
39
|
+
{% trans 'Thanks for using our site!' %}
|
|
40
|
+
</p>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<!-- Success Card -->
|
|
44
|
+
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 overflow-hidden">
|
|
45
|
+
|
|
46
|
+
<div class="px-8 py-10 text-center">
|
|
47
|
+
<div class="w-16 h-16 bg-green-50 dark:bg-green-900/20 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
48
|
+
<svg class="w-8 h-8 text-green-600 dark:text-green-400" fill="currentColor" viewBox="0 0 20 20">
|
|
49
|
+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
|
50
|
+
</svg>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<p class="text-gray-700 dark:text-gray-300 mb-8">
|
|
54
|
+
{% trans "You have been successfully logged out." %}
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
<div class="space-y-3">
|
|
58
|
+
<a href="{% url 'admin:login' %}" class="w-full flex justify-center items-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors">
|
|
59
|
+
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
60
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"/>
|
|
61
|
+
</svg>
|
|
62
|
+
{% trans 'Log in again' %}
|
|
63
|
+
</a>
|
|
64
|
+
|
|
65
|
+
{% if site_url %}
|
|
66
|
+
<a href="{{ site_url }}" class="w-full flex justify-center items-center py-3 px-4 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors">
|
|
67
|
+
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
68
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
|
69
|
+
</svg>
|
|
70
|
+
{% trans 'Go to homepage' %}
|
|
71
|
+
</a>
|
|
72
|
+
{% endif %}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<!-- Dark Mode Toggle -->
|
|
78
|
+
<div class="mt-6 text-center">
|
|
79
|
+
<button id="dark-mode-toggle" type="button" class="inline-flex items-center px-4 py-2 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 transition-colors">
|
|
80
|
+
<svg class="w-5 h-5 mr-2 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
|
|
81
|
+
<path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/>
|
|
82
|
+
</svg>
|
|
83
|
+
<svg class="w-5 h-5 mr-2 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
|
|
84
|
+
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
|
|
85
|
+
</svg>
|
|
86
|
+
<span class="hidden dark:inline">{% trans 'Light mode' %}</span>
|
|
87
|
+
<span class="inline dark:hidden">{% trans 'Dark mode' %}</span>
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<!-- Footer -->
|
|
94
|
+
<footer class="mt-12 px-6 py-4 text-center text-sm text-gray-600 dark:text-gray-400">
|
|
95
|
+
Powered by
|
|
96
|
+
<a href="/" class="text-primary-600 dark:text-primary-400 hover:underline">
|
|
97
|
+
Adminita
|
|
98
|
+
</a>
|
|
99
|
+
</footer>
|
|
100
|
+
|
|
101
|
+
<script src="{% static 'adminita/adminita-tailwind.js' %}"></script>
|
|
102
|
+
</body>
|
|
103
|
+
</html>
|