fastapi-lite-admin 0.1.1__tar.gz → 0.1.3__tar.gz
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.
- {fastapi_lite_admin-0.1.1/fastapi_lite_admin.egg-info → fastapi_lite_admin-0.1.3}/PKG-INFO +1 -2
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/README.md +1 -2
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/dashboard.html +12 -11
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/layout.html +100 -27
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/model_detail.html +25 -16
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/model_form.html +30 -20
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/model_list.html +56 -40
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/views.py +13 -3
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3/fastapi_lite_admin.egg-info}/PKG-INFO +1 -2
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/pyproject.toml +1 -1
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/LICENSE +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/__init__.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/core/config.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/core/crud.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/core/registry.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/core/schema.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/dependencies/db.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/integrations/sqlalchemy.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/main.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/routers/admin.py +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/SOURCES.txt +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/dependency_links.txt +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/requires.txt +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/top_level.txt +0 -0
- {fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-lite-admin
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: A lightweight, pluggable admin panel for FastAPI
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -41,4 +41,3 @@ pip install -e ".[dev]"
|
|
|
41
41
|
# Run example
|
|
42
42
|
python -m example.main
|
|
43
43
|
```
|
|
44
|
-
pypi-AgEIcHlwaS5vcmcCJGFkOTJiMmI0LTZhYjEtNGFhMi04MWNiLWY2ZjYwZTQwODMyYwACKlszLCJmMzAxYzgyMC0wMjIxLTQ1YTEtOTJhYi03N2MyMTAzNjg3NWYiXQAABiC_AwPMy7ot3kaVFMV3sTtEyKa_TJeZLX2tuOY9uwCBRg
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/dashboard.html
RENAMED
|
@@ -90,26 +90,27 @@
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
.badge {
|
|
93
|
-
padding: 4px
|
|
94
|
-
border-radius:
|
|
93
|
+
padding: 4px 10px;
|
|
94
|
+
border-radius: 12px;
|
|
95
95
|
font-size: 0.7rem;
|
|
96
96
|
font-weight: 700;
|
|
97
97
|
text-transform: uppercase;
|
|
98
|
+
letter-spacing: 0.025em;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
.badge-info { background-color:
|
|
101
|
-
.badge-warn { background-color:
|
|
102
|
-
.badge-error { background-color:
|
|
103
|
-
.badge-success { background-color:
|
|
101
|
+
.badge-info { background-color: var(--info-bg); color: var(--info-text); }
|
|
102
|
+
.badge-warn { background-color: var(--warning-bg); color: var(--warning-text); }
|
|
103
|
+
.badge-error { background-color: var(--error-bg); color: var(--error-text); }
|
|
104
|
+
.badge-success { background-color: var(--success-bg); color: var(--success-text); }
|
|
104
105
|
|
|
105
106
|
.status-text {
|
|
106
107
|
font-weight: 600;
|
|
107
108
|
font-family: monospace;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
.status-200 { color: var(--success); }
|
|
111
|
-
.status-422 { color: var(--error); }
|
|
112
|
-
.status-latency { color: var(--warning); }
|
|
111
|
+
.status-200 { color: var(--success-text); }
|
|
112
|
+
.status-422 { color: var(--error-text); }
|
|
113
|
+
.status-latency { color: var(--warning-text); }
|
|
113
114
|
|
|
114
115
|
/* Quick Actions */
|
|
115
116
|
.quick-actions {
|
|
@@ -134,12 +135,12 @@
|
|
|
134
135
|
.action-icon {
|
|
135
136
|
width: 48px;
|
|
136
137
|
height: 48px;
|
|
137
|
-
background-color:
|
|
138
|
+
background-color: var(--bg-surface);
|
|
138
139
|
border-radius: 12px;
|
|
139
140
|
display: flex;
|
|
140
141
|
align-items: center;
|
|
141
142
|
justify-content: center;
|
|
142
|
-
color: var(--
|
|
143
|
+
color: var(--primary);
|
|
143
144
|
font-size: 1.25rem;
|
|
144
145
|
}
|
|
145
146
|
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/ui/templates/layout.html
RENAMED
|
@@ -8,28 +8,68 @@
|
|
|
8
8
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
9
9
|
<style>
|
|
10
10
|
:root {
|
|
11
|
-
--primary: #
|
|
12
|
-
--primary-hover: #
|
|
11
|
+
--primary: #6366f1;
|
|
12
|
+
--primary-hover: #4f46e5;
|
|
13
13
|
--bg-main: #f8fafc;
|
|
14
|
-
--bg-
|
|
14
|
+
--bg-card: #ffffff;
|
|
15
|
+
--bg-surface: #f1f5f9;
|
|
16
|
+
--bg-header: #f8fafc;
|
|
17
|
+
--bg-sidebar: #0f172a;
|
|
15
18
|
--text-main: #1e293b;
|
|
16
19
|
--text-muted: #64748b;
|
|
20
|
+
--sidebar-text: #94a3b8;
|
|
21
|
+
--sidebar-text-active: #ffffff;
|
|
17
22
|
--border: #e2e8f0;
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
+
--sidebar-hover: #1e293b;
|
|
24
|
+
--sidebar-active: #334155;
|
|
25
|
+
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
26
|
+
--sidebar-width: 240px;
|
|
27
|
+
--topbar-height: 48px;
|
|
28
|
+
|
|
29
|
+
/* Status Colors */
|
|
30
|
+
--success-bg: #dcfce7;
|
|
31
|
+
--success-text: #166534;
|
|
32
|
+
--warning-bg: #fef9c3;
|
|
33
|
+
--warning-text: #854d0e;
|
|
34
|
+
--error-bg: #fee2e2;
|
|
35
|
+
--error-text: #991b1b;
|
|
36
|
+
--info-bg: #e0f2fe;
|
|
37
|
+
--info-text: #075985;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[data-theme="dark"] {
|
|
41
|
+
--bg-main: #020617;
|
|
42
|
+
--bg-card: #0f172a;
|
|
43
|
+
--bg-surface: #1e293b;
|
|
44
|
+
--bg-header: #1e293b;
|
|
45
|
+
--bg-sidebar: #020617;
|
|
46
|
+
--text-main: #f1f5f9;
|
|
47
|
+
--text-muted: #94a3b8;
|
|
48
|
+
--border: #1e293b;
|
|
49
|
+
--sidebar-hover: #0f172a;
|
|
50
|
+
--sidebar-active: #1e293b;
|
|
51
|
+
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.3);
|
|
52
|
+
|
|
53
|
+
/* Status Colors - Dark Mode */
|
|
54
|
+
--success-bg: rgba(22, 101, 52, 0.2);
|
|
55
|
+
--success-text: #4ade80;
|
|
56
|
+
--warning-bg: rgba(133, 77, 14, 0.2);
|
|
57
|
+
--warning-text: #facc15;
|
|
58
|
+
--error-bg: rgba(153, 27, 27, 0.2);
|
|
59
|
+
--error-text: #f87171;
|
|
60
|
+
--info-bg: rgba(7, 89, 133, 0.2);
|
|
61
|
+
--info-text: #38bdf8;
|
|
23
62
|
}
|
|
24
63
|
|
|
25
64
|
* {
|
|
26
65
|
margin: 0;
|
|
27
66
|
padding: 0;
|
|
28
67
|
box-sizing: border-box;
|
|
68
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
69
|
+
transition: background-color 0.2s, border-color 0.2s, color 0.2s;
|
|
29
70
|
}
|
|
30
71
|
|
|
31
72
|
body {
|
|
32
|
-
font-family: 'Inter', sans-serif;
|
|
33
73
|
background-color: var(--bg-main);
|
|
34
74
|
color: var(--text-main);
|
|
35
75
|
display: flex;
|
|
@@ -69,14 +109,14 @@
|
|
|
69
109
|
.logo-text {
|
|
70
110
|
font-weight: 700;
|
|
71
111
|
font-size: 1.1rem;
|
|
72
|
-
color: var(--text-
|
|
112
|
+
color: var(--sidebar-text-active);
|
|
73
113
|
}
|
|
74
114
|
|
|
75
115
|
.logo-subtext {
|
|
76
116
|
font-size: 0.7rem;
|
|
77
117
|
text-transform: uppercase;
|
|
78
118
|
letter-spacing: 0.05em;
|
|
79
|
-
color: var(--text
|
|
119
|
+
color: var(--sidebar-text);
|
|
80
120
|
margin-top: -2px;
|
|
81
121
|
}
|
|
82
122
|
|
|
@@ -91,7 +131,7 @@
|
|
|
91
131
|
gap: 12px;
|
|
92
132
|
padding: 12px 16px;
|
|
93
133
|
text-decoration: none;
|
|
94
|
-
color: var(--text
|
|
134
|
+
color: var(--sidebar-text);
|
|
95
135
|
border-radius: 8px;
|
|
96
136
|
font-weight: 500;
|
|
97
137
|
transition: all 0.2s;
|
|
@@ -99,13 +139,13 @@
|
|
|
99
139
|
}
|
|
100
140
|
|
|
101
141
|
.nav-item:hover {
|
|
102
|
-
background-color:
|
|
103
|
-
color: var(--text-
|
|
142
|
+
background-color: var(--sidebar-hover);
|
|
143
|
+
color: var(--sidebar-text-active);
|
|
104
144
|
}
|
|
105
145
|
|
|
106
146
|
.nav-item.active {
|
|
107
|
-
background-color:
|
|
108
|
-
color: var(--
|
|
147
|
+
background-color: var(--sidebar-active);
|
|
148
|
+
color: var(--sidebar-text-active);
|
|
109
149
|
}
|
|
110
150
|
|
|
111
151
|
.sidebar-footer {
|
|
@@ -134,11 +174,12 @@
|
|
|
134
174
|
.user-info .name {
|
|
135
175
|
font-size: 0.9rem;
|
|
136
176
|
font-weight: 600;
|
|
177
|
+
color: var(--sidebar-text-active);
|
|
137
178
|
}
|
|
138
179
|
|
|
139
180
|
.user-info .email {
|
|
140
181
|
font-size: 0.75rem;
|
|
141
|
-
color: var(--text
|
|
182
|
+
color: var(--sidebar-text);
|
|
142
183
|
}
|
|
143
184
|
|
|
144
185
|
/* Main Content */
|
|
@@ -151,8 +192,8 @@
|
|
|
151
192
|
|
|
152
193
|
/* Topbar */
|
|
153
194
|
.topbar {
|
|
154
|
-
height:
|
|
155
|
-
background-color: var(--
|
|
195
|
+
height: var(--topbar-height);
|
|
196
|
+
background-color: var(--bg-card);
|
|
156
197
|
border-bottom: 1px solid var(--border);
|
|
157
198
|
display: flex;
|
|
158
199
|
align-items: center;
|
|
@@ -167,13 +208,14 @@
|
|
|
167
208
|
|
|
168
209
|
.search-box input {
|
|
169
210
|
width: 100%;
|
|
170
|
-
padding:
|
|
171
|
-
background-color:
|
|
172
|
-
border: 1px solid
|
|
173
|
-
border-radius:
|
|
211
|
+
padding: 8px 12px 8px 36px;
|
|
212
|
+
background-color: var(--bg-surface);
|
|
213
|
+
border: 1px solid var(--border);
|
|
214
|
+
border-radius: 8px;
|
|
174
215
|
outline: none;
|
|
175
216
|
font-size: 0.85rem;
|
|
176
217
|
transition: all 0.2s;
|
|
218
|
+
color: var(--text-main);
|
|
177
219
|
}
|
|
178
220
|
|
|
179
221
|
.search-box i {
|
|
@@ -217,11 +259,11 @@
|
|
|
217
259
|
|
|
218
260
|
/* Shared Components */
|
|
219
261
|
.card {
|
|
220
|
-
background-color: var(--
|
|
262
|
+
background-color: var(--bg-card);
|
|
221
263
|
border: 1px solid var(--border);
|
|
222
264
|
border-radius: 12px;
|
|
223
265
|
padding: 24px;
|
|
224
|
-
box-shadow:
|
|
266
|
+
box-shadow: var(--shadow);
|
|
225
267
|
}
|
|
226
268
|
|
|
227
269
|
.btn {
|
|
@@ -244,16 +286,17 @@
|
|
|
244
286
|
|
|
245
287
|
.btn-primary:hover {
|
|
246
288
|
background-color: var(--primary-hover);
|
|
289
|
+
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
|
|
247
290
|
}
|
|
248
291
|
|
|
249
292
|
.btn-secondary {
|
|
250
|
-
background-color:
|
|
293
|
+
background-color: var(--bg-card);
|
|
251
294
|
border-color: var(--border);
|
|
252
295
|
color: var(--text-main);
|
|
253
296
|
}
|
|
254
297
|
|
|
255
298
|
.btn-secondary:hover {
|
|
256
|
-
background-color:
|
|
299
|
+
background-color: var(--bg-surface);
|
|
257
300
|
}
|
|
258
301
|
|
|
259
302
|
/* Extra CSS from child templates */
|
|
@@ -311,6 +354,9 @@
|
|
|
311
354
|
<input type="text" placeholder="Search resources...">
|
|
312
355
|
</div>
|
|
313
356
|
<div class="topbar-actions">
|
|
357
|
+
<button id="theme-toggle" class="btn-icon" style="background: none; border: none; cursor: pointer; color: var(--text-muted);">
|
|
358
|
+
<i class="fas fa-moon"></i>
|
|
359
|
+
</button>
|
|
314
360
|
<i class="far fa-bell"></i>
|
|
315
361
|
<i class="far fa-question-circle"></i>
|
|
316
362
|
<div class="avatar" style="width: 32px; height: 32px;">
|
|
@@ -324,6 +370,33 @@
|
|
|
324
370
|
</div>
|
|
325
371
|
</div>
|
|
326
372
|
|
|
373
|
+
<script>
|
|
374
|
+
// Theme Toggle Logic
|
|
375
|
+
const themeToggle = document.getElementById('theme-toggle');
|
|
376
|
+
const icon = themeToggle.querySelector('i');
|
|
377
|
+
|
|
378
|
+
// Check for saved theme or default to light
|
|
379
|
+
const savedTheme = localStorage.getItem('theme') || 'light';
|
|
380
|
+
document.documentElement.setAttribute('data-theme', savedTheme);
|
|
381
|
+
updateIcon(savedTheme);
|
|
382
|
+
|
|
383
|
+
themeToggle.addEventListener('click', () => {
|
|
384
|
+
const currentTheme = document.documentElement.getAttribute('data-theme');
|
|
385
|
+
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
|
386
|
+
|
|
387
|
+
document.documentElement.setAttribute('data-theme', newTheme);
|
|
388
|
+
localStorage.setItem('theme', newTheme);
|
|
389
|
+
updateIcon(newTheme);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
function updateIcon(theme) {
|
|
393
|
+
if (theme === 'dark') {
|
|
394
|
+
icon.className = 'fas fa-sun';
|
|
395
|
+
} else {
|
|
396
|
+
icon.className = 'fas fa-moon';
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
</script>
|
|
327
400
|
{% block extra_js %}{% endblock %}
|
|
328
401
|
</body>
|
|
329
402
|
</html>
|
|
@@ -17,54 +17,63 @@
|
|
|
17
17
|
border-radius: 12px;
|
|
18
18
|
overflow: hidden;
|
|
19
19
|
border: 1px solid var(--border);
|
|
20
|
+
background-color: var(--border); /* This creates the thin border lines */
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
.detail-item {
|
|
23
24
|
padding: 24px;
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
background-color: var(--bg-card);
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
gap: 8px;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
.detail-item:nth-child(odd) {
|
|
29
|
-
|
|
32
|
+
margin-right: 1px;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
.detail-item
|
|
33
|
-
|
|
34
|
-
border-right: none;
|
|
35
|
+
.detail-item:not(:last-child) {
|
|
36
|
+
margin-bottom: 1px;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
.detail-item
|
|
38
|
-
|
|
39
|
+
.detail-item.full-width {
|
|
40
|
+
grid-column: span 2;
|
|
41
|
+
margin-right: 0;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
.detail-label {
|
|
42
|
-
font-size: 0.
|
|
45
|
+
font-size: 0.7rem;
|
|
43
46
|
font-weight: 700;
|
|
44
47
|
text-transform: uppercase;
|
|
45
48
|
color: var(--text-muted);
|
|
46
|
-
margin-bottom: 8px;
|
|
47
49
|
letter-spacing: 0.05em;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
.detail-value {
|
|
51
53
|
font-size: 1rem;
|
|
52
|
-
font-weight:
|
|
54
|
+
font-weight: 600;
|
|
55
|
+
color: var(--text-main);
|
|
53
56
|
word-break: break-all;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
.status-pill {
|
|
57
60
|
display: inline-flex;
|
|
58
61
|
align-items: center;
|
|
59
|
-
gap:
|
|
60
|
-
padding: 4px
|
|
62
|
+
gap: 8px;
|
|
63
|
+
padding: 4px 14px;
|
|
61
64
|
border-radius: 20px;
|
|
62
65
|
font-size: 0.8rem;
|
|
63
|
-
font-weight:
|
|
66
|
+
font-weight: 700;
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
.status-pill.active {
|
|
67
|
-
|
|
69
|
+
.status-pill.active {
|
|
70
|
+
background-color: var(--success-bg);
|
|
71
|
+
color: var(--success-text);
|
|
72
|
+
}
|
|
73
|
+
.status-pill.inactive {
|
|
74
|
+
background-color: var(--bg-surface);
|
|
75
|
+
color: var(--text-muted);
|
|
76
|
+
}
|
|
68
77
|
{% endblock %}
|
|
69
78
|
|
|
70
79
|
{% block content %}
|
|
@@ -58,9 +58,10 @@
|
|
|
58
58
|
font-size: 0.75rem;
|
|
59
59
|
font-weight: 700;
|
|
60
60
|
text-transform: uppercase;
|
|
61
|
-
color: var(--text-
|
|
61
|
+
color: var(--text-main);
|
|
62
62
|
margin-bottom: 8px;
|
|
63
63
|
letter-spacing: 0.05em;
|
|
64
|
+
opacity: 0.9;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
.form-input {
|
|
@@ -71,11 +72,13 @@
|
|
|
71
72
|
outline: none;
|
|
72
73
|
font-size: 0.95rem;
|
|
73
74
|
transition: all 0.2s;
|
|
75
|
+
background-color: var(--bg-card);
|
|
76
|
+
color: var(--text-main);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
.form-input:focus {
|
|
77
80
|
border-color: var(--primary);
|
|
78
|
-
box-shadow: 0 0 0 4px rgba(
|
|
81
|
+
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1);
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
.form-footer {
|
|
@@ -83,7 +86,7 @@
|
|
|
83
86
|
justify-content: flex-end;
|
|
84
87
|
gap: 12px;
|
|
85
88
|
padding: 20px 32px;
|
|
86
|
-
background-color:
|
|
89
|
+
background-color: var(--bg-surface);
|
|
87
90
|
border-top: 1px solid var(--border);
|
|
88
91
|
border-bottom-left-radius: 12px;
|
|
89
92
|
border-bottom-right-radius: 12px;
|
|
@@ -94,28 +97,29 @@
|
|
|
94
97
|
display: flex;
|
|
95
98
|
justify-content: space-between;
|
|
96
99
|
align-items: center;
|
|
97
|
-
padding:
|
|
98
|
-
background-color:
|
|
99
|
-
border-radius:
|
|
100
|
+
padding: 20px;
|
|
101
|
+
background-color: var(--bg-card);
|
|
102
|
+
border-radius: 12px;
|
|
100
103
|
border: 1px solid var(--border);
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
.toggle-info .title {
|
|
104
107
|
font-weight: 700;
|
|
105
|
-
font-size: 0.
|
|
108
|
+
font-size: 0.95rem;
|
|
106
109
|
display: block;
|
|
110
|
+
color: var(--text-main);
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
.toggle-info .desc {
|
|
110
|
-
font-size: 0.
|
|
114
|
+
font-size: 0.8rem;
|
|
111
115
|
color: var(--text-muted);
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
.switch {
|
|
115
119
|
position: relative;
|
|
116
120
|
display: inline-block;
|
|
117
|
-
width:
|
|
118
|
-
height:
|
|
121
|
+
width: 48px;
|
|
122
|
+
height: 26px;
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
.switch input { opacity: 0; width: 0; height: 0; }
|
|
@@ -124,8 +128,9 @@
|
|
|
124
128
|
position: absolute;
|
|
125
129
|
cursor: pointer;
|
|
126
130
|
top: 0; left: 0; right: 0; bottom: 0;
|
|
127
|
-
background-color:
|
|
128
|
-
|
|
131
|
+
background-color: var(--bg-surface);
|
|
132
|
+
border: 1px solid var(--border);
|
|
133
|
+
transition: .3s;
|
|
129
134
|
border-radius: 24px;
|
|
130
135
|
}
|
|
131
136
|
|
|
@@ -135,12 +140,16 @@
|
|
|
135
140
|
height: 18px; width: 18px;
|
|
136
141
|
left: 3px; bottom: 3px;
|
|
137
142
|
background-color: white;
|
|
138
|
-
transition: .
|
|
143
|
+
transition: .3s;
|
|
139
144
|
border-radius: 50%;
|
|
145
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
140
146
|
}
|
|
141
147
|
|
|
142
|
-
input:checked + .slider {
|
|
143
|
-
|
|
148
|
+
input:checked + .slider {
|
|
149
|
+
background-color: var(--primary);
|
|
150
|
+
border-color: var(--primary);
|
|
151
|
+
}
|
|
152
|
+
input:checked + .slider:before { transform: translateX(22px); }
|
|
144
153
|
|
|
145
154
|
/* Metadata Cards */
|
|
146
155
|
.meta-cards {
|
|
@@ -157,10 +166,10 @@
|
|
|
157
166
|
}
|
|
158
167
|
|
|
159
168
|
.meta-icon {
|
|
160
|
-
width:
|
|
161
|
-
height:
|
|
162
|
-
border-radius:
|
|
163
|
-
background-color:
|
|
169
|
+
width: 44px;
|
|
170
|
+
height: 44px;
|
|
171
|
+
border-radius: 12px;
|
|
172
|
+
background-color: var(--bg-surface);
|
|
164
173
|
display: flex;
|
|
165
174
|
align-items: center;
|
|
166
175
|
justify-content: center;
|
|
@@ -175,8 +184,9 @@
|
|
|
175
184
|
}
|
|
176
185
|
|
|
177
186
|
.meta-value {
|
|
178
|
-
font-size: 0.
|
|
187
|
+
font-size: 0.95rem;
|
|
179
188
|
font-weight: 600;
|
|
189
|
+
color: var(--text-main);
|
|
180
190
|
}
|
|
181
191
|
{% endblock %}
|
|
182
192
|
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
padding: 0;
|
|
15
15
|
overflow: hidden;
|
|
16
16
|
margin-bottom: 32px;
|
|
17
|
+
background-color: var(--bg-card);
|
|
18
|
+
border: 1px solid var(--border);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
.data-table {
|
|
@@ -23,63 +25,74 @@
|
|
|
23
25
|
|
|
24
26
|
.data-table th {
|
|
25
27
|
text-align: left;
|
|
26
|
-
padding:
|
|
27
|
-
font-size: 0.
|
|
28
|
+
padding: 10px 16px;
|
|
29
|
+
font-size: 0.7rem;
|
|
28
30
|
font-weight: 700;
|
|
29
31
|
text-transform: uppercase;
|
|
30
32
|
color: var(--text-muted);
|
|
31
33
|
border-bottom: 1px solid var(--border);
|
|
32
|
-
background-color:
|
|
34
|
+
background-color: var(--bg-surface);
|
|
35
|
+
letter-spacing: 0.025em;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
.data-table td {
|
|
36
|
-
padding:
|
|
37
|
-
font-size: 0.
|
|
39
|
+
padding: 12px 16px;
|
|
40
|
+
font-size: 0.85rem;
|
|
38
41
|
border-bottom: 1px solid var(--border);
|
|
39
|
-
color:
|
|
42
|
+
color: var(--text-main);
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
.status-badge {
|
|
43
46
|
display: inline-flex;
|
|
44
47
|
align-items: center;
|
|
45
|
-
gap:
|
|
46
|
-
|
|
48
|
+
gap: 6px;
|
|
49
|
+
padding: 2px 10px;
|
|
50
|
+
border-radius: 12px;
|
|
51
|
+
font-size: 0.75rem;
|
|
47
52
|
font-weight: 600;
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
.status-dot {
|
|
51
|
-
width:
|
|
52
|
-
height:
|
|
56
|
+
width: 6px;
|
|
57
|
+
height: 6px;
|
|
53
58
|
border-radius: 50%;
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
.status-active
|
|
57
|
-
|
|
61
|
+
.status-active {
|
|
62
|
+
background-color: var(--success-bg);
|
|
63
|
+
color: var(--success-text);
|
|
64
|
+
}
|
|
65
|
+
.status-active .status-dot { background-color: var(--success-text); }
|
|
58
66
|
|
|
67
|
+
.status-inactive {
|
|
68
|
+
background-color: var(--bg-surface);
|
|
69
|
+
color: var(--text-muted);
|
|
70
|
+
}
|
|
59
71
|
.status-inactive .status-dot { background-color: var(--text-muted); }
|
|
60
|
-
.status-inactive { color: var(--text-muted); }
|
|
61
72
|
|
|
62
73
|
.action-btns {
|
|
63
74
|
display: flex;
|
|
64
|
-
gap:
|
|
75
|
+
gap: 8px;
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
.action-btn {
|
|
68
79
|
background: none;
|
|
69
80
|
border: none;
|
|
70
|
-
color: var(--
|
|
81
|
+
color: var(--text-muted);
|
|
71
82
|
cursor: pointer;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
transition:
|
|
83
|
+
padding: 4px;
|
|
84
|
+
border-radius: 4px;
|
|
85
|
+
transition: all 0.2s;
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
.action-btn:hover {
|
|
78
|
-
color: var(--
|
|
89
|
+
background-color: var(--bg-surface);
|
|
90
|
+
color: var(--primary);
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
.action-btn.delete:hover {
|
|
82
|
-
color: var(--error);
|
|
94
|
+
background-color: var(--error-bg);
|
|
95
|
+
color: var(--error-text);
|
|
83
96
|
}
|
|
84
97
|
|
|
85
98
|
/* Footer Stats */
|
|
@@ -97,13 +110,13 @@
|
|
|
97
110
|
}
|
|
98
111
|
|
|
99
112
|
.footer-stat-icon {
|
|
100
|
-
width:
|
|
101
|
-
height:
|
|
102
|
-
border-radius:
|
|
113
|
+
width: 44px;
|
|
114
|
+
height: 44px;
|
|
115
|
+
border-radius: 12px;
|
|
103
116
|
display: flex;
|
|
104
117
|
align-items: center;
|
|
105
118
|
justify-content: center;
|
|
106
|
-
font-size: 1.
|
|
119
|
+
font-size: 1.25rem;
|
|
107
120
|
}
|
|
108
121
|
|
|
109
122
|
.footer-stat-info .label {
|
|
@@ -115,8 +128,9 @@
|
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
.footer-stat-info .value {
|
|
118
|
-
font-size: 1.
|
|
131
|
+
font-size: 1.5rem;
|
|
119
132
|
font-weight: 700;
|
|
133
|
+
color: var(--text-main);
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
/* Pagination */
|
|
@@ -126,7 +140,7 @@
|
|
|
126
140
|
justify-content: space-between;
|
|
127
141
|
align-items: center;
|
|
128
142
|
border-top: 1px solid var(--border);
|
|
129
|
-
background-color:
|
|
143
|
+
background-color: var(--bg-card);
|
|
130
144
|
}
|
|
131
145
|
|
|
132
146
|
.pagination-info {
|
|
@@ -149,30 +163,32 @@
|
|
|
149
163
|
}
|
|
150
164
|
|
|
151
165
|
.page-size-selector select {
|
|
152
|
-
padding: 4px
|
|
166
|
+
padding: 4px 12px;
|
|
153
167
|
border: 1px solid var(--border);
|
|
154
|
-
border-radius:
|
|
168
|
+
border-radius: 6px;
|
|
155
169
|
outline: none;
|
|
156
|
-
background:
|
|
170
|
+
background-color: var(--bg-card);
|
|
171
|
+
color: var(--text-main);
|
|
172
|
+
cursor: pointer;
|
|
157
173
|
}
|
|
158
174
|
|
|
159
175
|
.activity-badge {
|
|
160
176
|
display: inline-flex;
|
|
161
177
|
align-items: center;
|
|
162
178
|
gap: 6px;
|
|
163
|
-
padding:
|
|
164
|
-
background-color:
|
|
179
|
+
padding: 4px 12px;
|
|
180
|
+
background-color: var(--bg-surface);
|
|
165
181
|
color: var(--text-muted);
|
|
166
|
-
border-radius:
|
|
182
|
+
border-radius: 20px;
|
|
167
183
|
font-size: 0.75rem;
|
|
168
184
|
font-weight: 600;
|
|
169
185
|
border: 1px solid var(--border);
|
|
170
186
|
}
|
|
171
187
|
|
|
172
188
|
.activity-badge.active {
|
|
173
|
-
background-color:
|
|
174
|
-
color: var(--
|
|
175
|
-
border-color:
|
|
189
|
+
background-color: var(--info-bg);
|
|
190
|
+
color: var(--info-text);
|
|
191
|
+
border-color: transparent;
|
|
176
192
|
}
|
|
177
193
|
|
|
178
194
|
.activity-badge i {
|
|
@@ -241,7 +257,7 @@
|
|
|
241
257
|
|
|
242
258
|
<div class="table-footer-stats">
|
|
243
259
|
<div class="card footer-stat-card">
|
|
244
|
-
<div class="footer-stat-icon" style="background-color:
|
|
260
|
+
<div class="footer-stat-icon" style="background-color: var(--info-bg); color: var(--info-text);">
|
|
245
261
|
<i class="fas fa-user-group"></i>
|
|
246
262
|
</div>
|
|
247
263
|
<div class="footer-stat-info">
|
|
@@ -250,7 +266,7 @@
|
|
|
250
266
|
</div>
|
|
251
267
|
</div>
|
|
252
268
|
<div class="card footer-stat-card">
|
|
253
|
-
<div class="footer-stat-icon" style="background-color:
|
|
269
|
+
<div class="footer-stat-icon" style="background-color: var(--bg-surface); color: var(--primary);">
|
|
254
270
|
<i class="fas fa-bolt"></i>
|
|
255
271
|
</div>
|
|
256
272
|
<div class="footer-stat-info">
|
|
@@ -259,7 +275,7 @@
|
|
|
259
275
|
</div>
|
|
260
276
|
</div>
|
|
261
277
|
<div class="card footer-stat-card">
|
|
262
|
-
<div class="footer-stat-icon" style="background-color:
|
|
278
|
+
<div class="footer-stat-icon" style="background-color: var(--error-bg); color: var(--error-text);">
|
|
263
279
|
<i class="fas fa-triangle-exclamation"></i>
|
|
264
280
|
</div>
|
|
265
281
|
<div class="footer-stat-info">
|
|
@@ -331,7 +347,7 @@
|
|
|
331
347
|
<th onclick="toggleSort('${col}')" style="cursor: pointer; user-select: none;">
|
|
332
348
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
333
349
|
${col.replace('_', ' ')}
|
|
334
|
-
<i class="fas ${icon}" style="font-size: 0.7rem; color: ${isSorted ? 'var(--primary)' : '
|
|
350
|
+
<i class="fas ${icon}" style="font-size: 0.7rem; color: ${isSorted ? 'var(--primary)' : 'var(--border)'}"></i>
|
|
335
351
|
</div>
|
|
336
352
|
</th>
|
|
337
353
|
`;
|
|
@@ -351,7 +367,7 @@
|
|
|
351
367
|
const name = row['name'] || (row['email'] ? row['email'].split('@')[0] : 'Item');
|
|
352
368
|
return `
|
|
353
369
|
<td>
|
|
354
|
-
<span style="font-weight: 600;">${val}</span>
|
|
370
|
+
<span style="font-weight: 600; color: var(--text-main);">${val}</span>
|
|
355
371
|
${col === 'name' && row['email'] ? `<span style="font-size: 0.7rem; color: var(--text-muted); margin-left: 4px;">(${row['email']})</span>` : ''}
|
|
356
372
|
</td>
|
|
357
373
|
`;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
|
|
2
|
+
import asyncio
|
|
3
|
+
from fastapi import APIRouter, HTTPException, Request, Depends
|
|
3
4
|
from fastapi.responses import HTMLResponse
|
|
4
5
|
from fastapi.templating import Jinja2Templates
|
|
6
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
5
7
|
import os
|
|
8
|
+
import asyncio
|
|
6
9
|
|
|
7
10
|
# Get path to templates directory relative to this file
|
|
8
11
|
TEMPLATES_DIR = os.path.join(os.path.dirname(__file__), "templates")
|
|
@@ -74,7 +77,13 @@ def create_ui_router(admin: Any) -> APIRouter:
|
|
|
74
77
|
return templates.TemplateResponse(
|
|
75
78
|
request=request,
|
|
76
79
|
name="dashboard.html",
|
|
77
|
-
context={
|
|
80
|
+
context={
|
|
81
|
+
"stats": stats,
|
|
82
|
+
"recent_logs": recent_logs,
|
|
83
|
+
"models": list(models.keys()),
|
|
84
|
+
"logs_config": admin.logs_config,
|
|
85
|
+
"admin_title": admin.title
|
|
86
|
+
}
|
|
78
87
|
)
|
|
79
88
|
|
|
80
89
|
@router.get("/{model_name}", response_class=HTMLResponse)
|
|
@@ -127,7 +136,8 @@ def create_ui_router(admin: Any) -> APIRouter:
|
|
|
127
136
|
"recent_count": recent_count,
|
|
128
137
|
"attention_count": attention_count,
|
|
129
138
|
"has_date_field": bool(date_field),
|
|
130
|
-
"has_attention_filter": attn_filter is not None
|
|
139
|
+
"has_attention_filter": attn_filter is not None,
|
|
140
|
+
"admin_title": admin.title
|
|
131
141
|
}
|
|
132
142
|
)
|
|
133
143
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-lite-admin
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: A lightweight, pluggable admin panel for FastAPI
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -41,4 +41,3 @@ pip install -e ".[dev]"
|
|
|
41
41
|
# Run example
|
|
42
42
|
python -m example.main
|
|
43
43
|
```
|
|
44
|
-
pypi-AgEIcHlwaS5vcmcCJGFkOTJiMmI0LTZhYjEtNGFhMi04MWNiLWY2ZjYwZTQwODMyYwACKlszLCJmMzAxYzgyMC0wMjIxLTQ1YTEtOTJhYi03N2MyMTAzNjg3NWYiXQAABiC_AwPMy7ot3kaVFMV3sTtEyKa_TJeZLX2tuOY9uwCBRg
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_admin_lite/integrations/sqlalchemy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/requires.txt
RENAMED
|
File without changes
|
{fastapi_lite_admin-0.1.1 → fastapi_lite_admin-0.1.3}/fastapi_lite_admin.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|