plain.admin 0.17.0__py3-none-any.whl → 0.19.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.
@@ -61,6 +61,12 @@ main a:hover {
61
61
  border-radius: 6px;
62
62
  transition: background-color 0.2s, border-color 0.2s, transform 0.2s;
63
63
  cursor: pointer;
64
+ flex-shrink: 0;
65
+
66
+ @media (max-width: 640px) {
67
+ font-size: 12px;
68
+ padding: 6px 12px;
69
+ }
64
70
 
65
71
  &:hover {
66
72
  background-color: #2a2928;
@@ -80,6 +86,20 @@ main a:hover {
80
86
  }
81
87
  }
82
88
 
89
+ main button[type="submit"] {
90
+ background-color: #2563eb;
91
+ border-color: #2563eb;
92
+
93
+ &:hover {
94
+ background-color: #1d4ed8;
95
+ border-color: #1d4ed8;
96
+ }
97
+ &:focus {
98
+ outline: 2px solid #2563eb;
99
+ outline-offset: 2px;
100
+ }
101
+ }
102
+
83
103
  /* Cards use these? */
84
104
  section {
85
105
  border: rgba(255, 255, 255, 0.1) 1px solid;
plain/admin/cards/base.py CHANGED
@@ -2,7 +2,6 @@ from enum import Enum
2
2
 
3
3
  from plain.http import HttpRequest
4
4
  from plain.templates import Template
5
- from plain.utils.text import slugify
6
5
  from plain.views import View
7
6
 
8
7
 
@@ -22,7 +21,6 @@ class Card:
22
21
  title: str
23
22
 
24
23
  # Optional fields
25
- slug: str = ""
26
24
  description: str = ""
27
25
  text: str = ""
28
26
  link: str = ""
@@ -60,8 +58,9 @@ class Card:
60
58
  def get_title(self) -> str:
61
59
  return self.title
62
60
 
63
- def get_slug(self) -> str:
64
- return self.slug or slugify(self.title)
61
+ @classmethod
62
+ def get_slug(cls) -> str:
63
+ return f"{cls.__module__}.{cls.__name__}".lower().replace(".", "_")
65
64
 
66
65
  def get_description(self) -> str:
67
66
  return self.description
@@ -22,9 +22,9 @@
22
22
  </head>
23
23
  <body class="flex min-h-screen bg-stone-950">
24
24
 
25
- <nav class="fixed top-0 left-0 right-0 h-14 px-4 py-2 flex items-center justify-evenly text-sm text-white/70">
25
+ <nav class="fixed top-0 left-0 right-0 h-14 px-4 py-2 flex items-center justify-between sm:justify-evenly text-sm text-white/70 space-x-3">
26
26
  <div class="flex items-center space-x-2">
27
- <button type="button" data-toggle="#admin-sidebar,#admin-content" class="mr-1 lg:hidden">
27
+ <button type="button" data-toggle="#admin-sidebar,#admin-content" class="lg:hidden">
28
28
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-5 h-5 bi bi-list" viewBox="0 0 16 16">
29
29
  <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5"/>
30
30
  </svg>
@@ -32,11 +32,6 @@
32
32
  </button>
33
33
 
34
34
  <a class="inline-flex items-center text-stone-300" href="{{ url('admin:index') }}">
35
- <svg class="w-5 h-5 mr-2" width="160" height="125" viewBox="0 0 160 125" fill="none" xmlns="http://www.w3.org/2000/svg">
36
- <rect x="4.78467" y="4.79785" width="150.978" height="115.404" rx="5" stroke="#ffffff" stroke-width="8"/>
37
- <path d="M151.762 60.3705C99.2596 39.3233 80.202 66.8232 8.78467 60.3705V116.2H151.762V60.3705Z" fill="#ffffff"/>
38
- <path d="M51.104 8.08887H108.179V10.7668C108.179 12.6998 106.612 14.2668 104.679 14.2668H54.604C52.671 14.2668 51.104 12.6998 51.104 10.7668V8.08887Z" fill="#ffffff" stroke="#ffffff"/>
39
- </svg>
40
35
  <span class="text-stone-400">Admin</span>
41
36
  </a>
42
37
 
@@ -50,14 +45,14 @@
50
45
  #}
51
46
  </div>
52
47
 
53
- <form method="GET" action="{{ url('admin:search') }}" class="flex flex-1 justify-center">
54
- <div class="relative max-w-xs">
48
+ <form method="GET" action="{{ url('admin:search') }}" class="hidden sm:flex flex-1 justify-center">
49
+ <div class="relative max-w-xs flex flex-1">
55
50
  <label for="query" class="sr-only">Search</label>
56
51
  <input
57
52
  type="text"
58
53
  name="query"
59
54
  id="query"
60
- class="block w-full pr-10 pl-10 placeholder:text-center text-sm border-gray-200/10 text-white rounded-md focus:border-blue-500 focus:ring-blue-500 bg-white/5 py-1"
55
+ class="block w-full pr-10 pl-10 placeholder:text-white/30 placeholder:text-center text-sm border-gray-200/10 text-white rounded-md focus:border-blue-500 focus:ring-blue-500 bg-white/5 py-1"
61
56
  placeholder="Search everything"
62
57
  value="{{ global_search_query|default('') }}"
63
58
  >
@@ -99,23 +94,26 @@
99
94
  <div class="text-xs tracking-wide text-stone-500">Recent</div>
100
95
  </div> -->
101
96
  </div>
102
- <div class="flex items-center justify-between mt-8 text-sm pb-3 pt-3 text-stone-400 sticky bottom-0 bg-stone-950">
103
- <div class="flex items-center truncate">
104
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-6 h-6 mr-1.5 bi bi-person-circle" viewBox="0 0 16 16">
105
- <path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
106
- <path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
107
- </svg>
108
- <span class="truncate">
109
- {{ request.user }}
110
- </span>
97
+ <div class="mt-8 flex flex-col text-sm pb-3 pt-3 text-stone-400 sticky bottom-0 bg-stone-950">
98
+ <a class="sm:hidden py-1" href="{{ url('admin:search') }}">Global search</a>
99
+ <div class="flex items-center justify-between">
100
+ <div class="flex items-center truncate">
101
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-6 h-6 mr-1.5 bi bi-person-circle" viewBox="0 0 16 16">
102
+ <path d="M11 6a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
103
+ <path fill-rule="evenodd" d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm8-7a7 7 0 0 0-5.468 11.37C3.242 11.226 4.805 10 8 10s4.757 1.225 5.468 2.37A7 7 0 0 0 8 1z"/>
104
+ </svg>
105
+ <span class="truncate">
106
+ {{ request.user }}
107
+ </span>
108
+ </div>
109
+ <a class="ml-2 hover:text-white hover:underline flex-shrink-0" href="{{ url('logout') }}">Log out</a>
111
110
  </div>
112
- <a class="ml-2 hover:text-white hover:underline flex-shrink-0" href="{{ url('logout') }}">Log out</a>
113
111
  </div>
114
112
  </aside>
115
113
 
116
114
  <div id="admin-content" data-toggle-class="x" class="absolute top-0 bottom-0 right-0 left-0 lg:left-52 bg-stone-900 border border-white/5 text-white rounded-lg overflow-auto">
117
- <div class="flex items-center justify-between px-4 lg:px-8 sticky z-10 top-0 bg-stone-900 border-b border-white/10 py-2 lg:py-3">
118
- <div>
115
+ <div class="flex space-x-3 items-center justify-between px-4 lg:px-8 sticky z-10 top-0 left-0 right-0 bg-stone-900 border-b border-white/10 py-2 lg:py-3">
116
+ <div class="flex-shrink-0">
119
117
  {% block header %}
120
118
  <div class="flex items-center">
121
119
  {% block image %}
@@ -124,7 +122,7 @@
124
122
  {% endif %}
125
123
  {% endblock %}
126
124
  <div class="max-w-prose break-all">
127
- <h1 class="text-xl text-white/90">
125
+ <h1 class="sm:text-xl text-white/90">
128
126
  {% block title %}{{ title }}{% endblock %}
129
127
  </h1>
130
128
  {% if description %}<p class="mt-1 text-sm text-gray-500">{{ description }}</p>{% endif %}
@@ -132,7 +130,8 @@
132
130
  </div>
133
131
  {% endblock %}
134
132
  </div>
135
- <div class="flex space-x-2 text-sm actions">
133
+ <div class="flex space-x-2 text-sm actions overflow-auto p-1">
134
+ {# Styled with admin.css for easier adding of elements #}
136
135
  {% block actions %}{% endblock %}
137
136
  {% for link, url in links.items() %}
138
137
  <a href="{{ url }}">{{ link }}</a>
@@ -150,7 +149,7 @@
150
149
  </div>
151
150
  {% endif %}
152
151
 
153
- <main class="px-4 py-6 lg:px-8 text-white/70">{% block content %}{% endblock %}</main>
152
+ <main class="px-4 py-6 lg:px-8 text-white/80">{% block content %}{% endblock %}</main>
154
153
  </div>
155
154
 
156
155
  </div>
@@ -9,10 +9,10 @@
9
9
  Toggle raw values
10
10
  </button>
11
11
 
12
- <dl class="text-sm mt-3 w-full grid grid-cols-[max-content,1fr] gap-y-2 gap-x-8" style="grid-template-columns: max-content 1fr;">
12
+ <dl class="text-sm mt-3 w-full grid !grid-cols-1 sm:!grid-cols-[max-content,1fr] sm:gap-y-2 gap-x-8" style="grid-template-columns: max-content 1fr;">
13
13
  {% for field in fields %}
14
- <dt class="font-semibold"><code>{{ field }}</code></dt>
15
- <dd class="flex items-center">
14
+ <dt class="font-medium mt-4 sm:mt-0"><code>{{ field }}</code></dt>
15
+ <dd class="flex items-center mt-1 sm:mt-0">
16
16
  {% with value=get_field_value(object, field) %}
17
17
  <div class="raw-value hidden"><code>{{ value }}</code></div>
18
18
  <div class="pretty-value">{% include get_field_value_template(object, field, value) with context %}</div>
@@ -10,6 +10,28 @@ Search
10
10
 
11
11
  {% block content %}
12
12
 
13
+ {# Mobile search bar #}
14
+ <div class="sm:hidden">
15
+ <form method="GET" action="{{ url('admin:search') }}" class="">
16
+ <div class="relative">
17
+ <label for="query" class="sr-only">Search</label>
18
+ <input
19
+ type="text"
20
+ name="query"
21
+ id="query"
22
+ class="block w-full pr-10 pl-10 placeholder:text-center border-gray-200/10 text-white rounded-md focus:border-blue-500 focus:ring-blue-500 bg-white/5 py-1"
23
+ placeholder="Search everything"
24
+ value="{{ global_search_query|default('') }}"
25
+ >
26
+ <div class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none">
27
+ <svg class="h-3.5 w-3.5 text-gray-400" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
28
+ <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"></path>
29
+ </svg>
30
+ </div>
31
+ </div>
32
+ </form>
33
+ </div>
34
+
13
35
  {% if global_search_query %}
14
36
  <div class="*:mt-14 *:empty:mt-0">
15
37
  {% for view in searchable_views %}
@@ -21,7 +43,7 @@ Search
21
43
  {% endfor %}
22
44
  </div>
23
45
  {% else %}
24
- <p class="text-stone-500">Enter a search query in the top bar</p>
46
+ <p class="text-stone-500 hidden sm:inline">Enter a search query in the top bar</p>
25
47
  {% endif %}
26
48
 
27
49
  {% endblock %}
@@ -2,6 +2,7 @@
2
2
  <div class="flex items-center space-x-2">
3
3
  <admin.Checkbox field=field />
4
4
  <admin.Label field=field>{{ label }}</admin.Label>
5
+ {% if help is defined %}<admin.Help help=help />{% endif %}
5
6
  </div>
6
7
  <admin.FieldErrors field=field />
7
8
  </div>
@@ -0,0 +1 @@
1
+ <p class="mt-2 text-sm text-gray-500">{{ help }}</p>
@@ -1,5 +1,6 @@
1
1
  <div class="space-y-1">
2
2
  <admin.Label field=field>{{ label }}</admin.Label>
3
3
  <admin.Input field=field />
4
+ {% if help is defined %}<admin.Help help=help />{% endif %}
4
5
  <admin.FieldErrors field=field />
5
6
  </div>
@@ -1,3 +1,4 @@
1
- <label for="{{ field.html_id }}" class="block text-sm font-medium">
2
- {{ caller() }}
1
+ <label for="{{ field.html_id }}" class="block flex items-baseline justify-between">
2
+ <div class="text-sm font-medium">{{ caller() }}</div>
3
+ {% if not field.field.required %}<div class="text-white/60 text-xs">Optional</div>{% endif %}
3
4
  </label>
@@ -1,5 +1,6 @@
1
1
  <div class="space-y-1">
2
2
  <admin.Label field=field>{{ label }}</admin.Label>
3
3
  <admin.Select field=field />
4
+ {% if help is defined %}<admin.Help help=help />{% endif %}
4
5
  <admin.FieldErrors field=field />
5
6
  </div>
@@ -0,0 +1,7 @@
1
+ <textarea
2
+ id="{{ field.html_id }}"
3
+ name="{{ field.html_name }}"
4
+ class="block w-full text-sm border rounded border-white/10 bg-white/5"
5
+ rows="{{ rows|default(3) }}"
6
+ {% if field.field.required %}required{% endif %}
7
+ >{{ field.value() or "" }}</textarea>
@@ -0,0 +1,6 @@
1
+ <div class="space-y-1">
2
+ <admin.Label field=field>{{ label }}</admin.Label>
3
+ <admin.Textarea field=field />
4
+ {% if help is defined %}<admin.Help help=help />{% endif %}
5
+ <admin.FieldErrors field=field />
6
+ </div>
@@ -1,15 +1,10 @@
1
1
  {% if toolbar.should_render() %}
2
2
  {% set exception=toolbar.request_exception() %}
3
3
  <script src="{{ asset('toolbar/toolbar.js') }}"></script>
4
- <div id="plaintoolbar" class="print:hidden text-sm py-1.5 text-stone-300 bg-stone-950 fixed bottom-3 mx-3 max-w-full drop-shadow-md z-30 rounded-2xl lg:flex lg:flex-col -translate-x-1/2 left-1/2 max-h-[90vh]">
5
- <div class="flex justify-between px-4 mx-auto space-x-4">
4
+ <div id="plaintoolbar" class="print:hidden text-sm py-1.5 text-stone-300 fixed bottom-3 mx-3 max-w-full drop-shadow-sm z-30 ring-1 ring-stone-200/5 rounded-2xl lg:flex lg:flex-col -translate-x-1/2 left-1/2 max-h-[90vh] bg-gradient-to-b from-stone-950/90 to-stone-950/95 backdrop-blur-sm">
5
+ <div class="flex justify-between px-3 mx-auto space-x-4">
6
6
  <div class="flex items-center">
7
- <svg class="h-4 w-4" width="160" height="125" viewBox="0 0 160 125" fill="none" xmlns="http://www.w3.org/2000/svg">
8
- <rect x="4.78467" y="4.79785" width="150.978" height="115.404" rx="5" stroke="#ffffff" stroke-width="8"/>
9
- <path d="M151.762 60.3705C99.2596 39.3233 80.202 66.8232 8.78467 60.3705V116.2H151.762V60.3705Z" fill="#ffffff"/>
10
- <path d="M51.104 8.08887H108.179V10.7668C108.179 12.6998 106.612 14.2668 104.679 14.2668H54.604C52.671 14.2668 51.104 12.6998 51.104 10.7668V8.08887Z" fill="#ffffff" stroke="#ffffff"/>
11
- </svg>
12
- <code class="ml-2 text-xs whitespace-nowrap text-mono">{{ toolbar.version }}</code>
7
+ <code class="ml-1.5 text-xs whitespace-nowrap text-mono">{{ toolbar.version }}</code>
13
8
 
14
9
  {% if request.impersonator is defined %}
15
10
  <div class="flex items-center ml-1 font-light">
plain/admin/urls.py CHANGED
@@ -10,7 +10,6 @@ from .views.registry import registry
10
10
  class AdminIndexView(AdminView):
11
11
  template_name = "admin/index.html"
12
12
  title = "Dashboard"
13
- slug = ""
14
13
 
15
14
  def get(self):
16
15
  # Slight hack to redirect to the first view that doesn't
@@ -24,7 +23,6 @@ class AdminIndexView(AdminView):
24
23
  class AdminSearchView(AdminView):
25
24
  template_name = "admin/search.html"
26
25
  title = "Search"
27
- slug = "search"
28
26
 
29
27
  def get_template_context(self):
30
28
  context = super().get_template_context()
plain/admin/views/base.py CHANGED
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING
3
3
  from plain.auth.views import AuthViewMixin
4
4
  from plain.urls import reverse
5
5
  from plain.utils import timezone
6
- from plain.utils.text import slugify
7
6
  from plain.views import (
8
7
  TemplateView,
9
8
  )
@@ -22,7 +21,6 @@ class AdminView(AuthViewMixin, TemplateView):
22
21
  admin_required = True
23
22
 
24
23
  title: str = ""
25
- slug: str = ""
26
24
  path: str = ""
27
25
  description: str = ""
28
26
  image: Img | None = None
@@ -69,15 +67,7 @@ class AdminView(AuthViewMixin, TemplateView):
69
67
 
70
68
  @classmethod
71
69
  def get_slug(cls) -> str:
72
- if cls.slug:
73
- return cls.slug
74
-
75
- if cls.title:
76
- return slugify(cls.title)
77
-
78
- raise NotImplementedError(
79
- f"Please set a slug on the {cls} class or implement get_slug()."
80
- )
70
+ return f"{cls.__module__}.{cls.__name__}".lower().replace(".", "_")
81
71
 
82
72
  # Can actually use @classmethod, @staticmethod or regular method for these?
83
73
  def get_title(self) -> str:
@@ -91,15 +81,7 @@ class AdminView(AuthViewMixin, TemplateView):
91
81
 
92
82
  @classmethod
93
83
  def get_path(cls) -> str:
94
- if cls.path:
95
- return cls.path
96
-
97
- if slug := cls.get_slug():
98
- return slug
99
-
100
- raise NotImplementedError(
101
- f"Please set a path on the {cls} class or implement get_slug() or get_path()."
102
- )
84
+ return cls.path
103
85
 
104
86
  @classmethod
105
87
  def get_parent_view_classes(cls) -> list["AdminView"]:
@@ -68,8 +68,11 @@ class AdminModelListView(AdminListView):
68
68
  return cls.model._meta.model_name.capitalize() + "s"
69
69
 
70
70
  @classmethod
71
- def get_slug(cls) -> str:
72
- return cls.model._meta.model_name
71
+ def get_path(cls) -> str:
72
+ if path := super().get_path():
73
+ return path
74
+
75
+ return f"{cls.model._meta.model_name}/"
73
76
 
74
77
  def get_template_context(self):
75
78
  context = super().get_template_context()
@@ -137,12 +140,11 @@ class AdminModelDetailView(AdminDetailView):
137
140
  def get_title(self) -> str:
138
141
  return str(self.object)
139
142
 
140
- @classmethod
141
- def get_slug(cls) -> str:
142
- return f"{cls.model._meta.model_name}_detail"
143
-
144
143
  @classmethod
145
144
  def get_path(cls) -> str:
145
+ if path := super().get_path():
146
+ return path
147
+
146
148
  return f"{cls.model._meta.model_name}/<int:pk>/"
147
149
 
148
150
  def get_fields(self):
@@ -182,12 +184,11 @@ class AdminModelCreateView(AdminCreateView):
182
184
 
183
185
  return f"New {self.model._meta.model_name}"
184
186
 
185
- @classmethod
186
- def get_slug(cls) -> str:
187
- return f"{cls.model._meta.model_name}_create"
188
-
189
187
  @classmethod
190
188
  def get_path(cls) -> str:
189
+ if path := super().get_path():
190
+ return path
191
+
191
192
  return f"{cls.model._meta.model_name}/create/"
192
193
 
193
194
  def get_template_names(self):
@@ -213,12 +214,11 @@ class AdminModelUpdateView(AdminUpdateView):
213
214
 
214
215
  return f"Update {self.object}"
215
216
 
216
- @classmethod
217
- def get_slug(cls) -> str:
218
- return f"{cls.model._meta.model_name}_update"
219
-
220
217
  @classmethod
221
218
  def get_path(cls) -> str:
219
+ if path := super().get_path():
220
+ return path
221
+
222
222
  return f"{cls.model._meta.model_name}/<int:pk>/update/"
223
223
 
224
224
  def get_object(self):
@@ -242,12 +242,11 @@ class AdminModelDeleteView(AdminDeleteView):
242
242
  def get_title(self) -> str:
243
243
  return f"Delete {self.object}"
244
244
 
245
- @classmethod
246
- def get_slug(cls) -> str:
247
- return f"{cls.model._meta.model_name}_delete"
248
-
249
245
  @classmethod
250
246
  def get_path(cls) -> str:
247
+ if path := super().get_path():
248
+ return path
249
+
251
250
  return f"{cls.model._meta.model_name}/<int:pk>/delete/"
252
251
 
253
252
  def get_object(self):
@@ -67,18 +67,26 @@ class AdminViewRegistry:
67
67
  def get_urls(self):
68
68
  urls = []
69
69
 
70
- paths_seen = set()
71
-
72
- def add_view_path(view, _path):
73
- if _path in paths_seen:
74
- raise ValueError(f"Path {_path} already registered")
75
- paths_seen.add(_path)
76
- if not _path.endswith("/"):
77
- _path += "/"
78
- urls.append(path(_path, view, name=view.view_name()))
70
+ paths_seen = {}
79
71
 
80
72
  for view in self.registered_views:
81
- add_view_path(view, f"p/{view.get_path()}")
73
+ view_path = view.get_path()
74
+
75
+ if not view_path:
76
+ raise ValueError(f"Path for {view} is empty")
77
+
78
+ if existing_view := paths_seen.get(view_path, None):
79
+ raise ValueError(
80
+ f"Duplicate admin path {view_path}\n{existing_view}\n{view}"
81
+ )
82
+
83
+ paths_seen[view_path] = view
84
+
85
+ # Append trailing slashes automatically
86
+ if not view_path.endswith("/"):
87
+ view_path += "/"
88
+
89
+ urls.append(path(f"p/{view_path}", view, name=view.view_name()))
82
90
 
83
91
  return urls
84
92
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.admin
3
- Version: 0.17.0
3
+ Version: 0.19.0
4
4
  Summary: Admin dashboard and tools for Plain.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
@@ -6,8 +6,8 @@ plain/admin/default_settings.py,sha256=j7RdgGqksCmCgPO7zCcFiVV9f8yW-EULvqDcFOhQa
6
6
  plain/admin/middleware.py,sha256=k3yP1o3CzvLiZZSoxqq-DvAZlp4sICRauaT-kD3FJKM,398
7
7
  plain/admin/templates.py,sha256=jLhJkuvqnPMBQTP-kzojFaqmFi50GZHvrVzuZCLc3rk,836
8
8
  plain/admin/toolbar.py,sha256=dsZa_I-tTbaeOluCbvHGEqy4_Suw6Q_JSrKl8Eu08qY,973
9
- plain/admin/urls.py,sha256=xGZDs103SStrlny806pqfvuA-UBUI2Xy_eXtq1VtoBI,1365
10
- plain/admin/assets/admin/admin.css,sha256=K8XfU6XMSe2-e-T9XvD-g2t1cgYz9GDMne-ugVeNXcA,2207
9
+ plain/admin/urls.py,sha256=Q44_HpivSHJfDQWJLtm_OQVWm0VQlqAg8sa1M1NdxFM,1331
10
+ plain/admin/assets/admin/admin.css,sha256=qSM3Q99I2YbWxNmRjSORz9yCZ-H7oeGppTFE4QzByvk,2580
11
11
  plain/admin/assets/admin/admin.js,sha256=AWD6UqPxGqJFaUhYTDWe4niTgk0thzU4gRl7qK41KNc,2759
12
12
  plain/admin/assets/admin/chart.js,sha256=GZiCYXjL6SmyuSCGE0Df80QvOUkw6H2YD-zsVID05lo,205089
13
13
  plain/admin/assets/admin/jquery-3.6.1.slim.min.js,sha256=W2eb4M1jdKpuZ_-_KnDgqI9X9SwGLrXtO0dknpNPJyE,72534
@@ -16,7 +16,7 @@ plain/admin/assets/admin/popper.min.js,sha256=SgCxkjQZdrt2puqn62YUu9hknpCBGBEAy9
16
16
  plain/admin/assets/admin/tippy-bundle.umd.min.js,sha256=oVWBpeGTKMG_iBWGkQF02JnGIMFPYuFqTjUWeJY3pZ0,25668
17
17
  plain/admin/assets/toolbar/toolbar.js,sha256=kRCQ37iQNklzBjjBeHSeBU39mLpQ4Q0pnC3cdbQAy28,1636
18
18
  plain/admin/cards/__init__.py,sha256=8NfWrguyJRriJFUc3_QeGaDILhgeU3d1aXktzIuAR1E,172
19
- plain/admin/cards/base.py,sha256=IUqHOWB0t7sM1vVUrbHT76alP-7Jwga3FfagNgKTJww,2250
19
+ plain/admin/cards/base.py,sha256=g9t-pQq8O8gqMbTVdTujacfDQguFMq_aoRIKZkme_SA,2238
20
20
  plain/admin/cards/charts.py,sha256=fbCypn4_2uhFnNgj7z1T7bhSjQVtlxODnctynI6yrqI,5017
21
21
  plain/admin/cards/tables.py,sha256=lGUBeSaBsNVuzINVH8qU-1XF0PfPY03gcUKtN-462zE,599
22
22
  plain/admin/impersonate/README.md,sha256=GT7ubMxyB2RhUh-gDg_yYqWSm7oMp0hy1LepXyDRMo8,1012
@@ -33,14 +33,13 @@ plain/admin/querystats/core.py,sha256=GLhKwWwO2OwN2wneAgfbKRQzIIjZqegZYb1fMVwilj
33
33
  plain/admin/querystats/middleware.py,sha256=M1EVdX11H545IdZlppbSIL_h8hzBIrMELrYrcAb4aq0,3192
34
34
  plain/admin/querystats/urls.py,sha256=SHYbWvxjg6kFHR-e6T4vFmh4VqyPG7gYHXxDKdB4qz0,230
35
35
  plain/admin/querystats/views.py,sha256=58UpxaBp_H80Tf7azi4QcphgHbXgP5iqLDf-qZJfzRI,788
36
- plain/admin/templates/admin/base.html,sha256=nhgBk69i8HaafIe0aa2xuj-YmEKyc9UZAju-k3G0nUs,8514
36
+ plain/admin/templates/admin/base.html,sha256=pLv6gKOSwTaNumhzl2ThLD--lq3u-aBVnSt64f-lkdI,8307
37
37
  plain/admin/templates/admin/delete.html,sha256=lNuU2G-BR6TH6NUmh7VcvjnEuFeI84rwwk_oO1jkUq0,431
38
- plain/admin/templates/admin/detail.html,sha256=hwRSjPunxLnJKPAyP2HYVKV3cJmWw-OBgCLZ1WQ8zaE,743
39
- plain/admin/templates/admin/form.html,sha256=Cc9zKjYbs_W3TaoO5teLhg35eb47JYYXEJH55wA760E,289
38
+ plain/admin/templates/admin/detail.html,sha256=NOEUvZlHM5lvpq6ZnfMYS6UUBCMSya4CmAHxZr-joJQ,787
40
39
  plain/admin/templates/admin/index.html,sha256=b65tcZhv9QfvmjePySU7MmzUlpMECIXP8dBH-a3Eyxw,69
41
40
  plain/admin/templates/admin/list.html,sha256=RFtGZf_g_IDiPc8udchgf63mMpfEsvzS4hUKqkvDjoM,8781
42
41
  plain/admin/templates/admin/page.html,sha256=wzRR-JLs8CgCOoB3BMoYWqTMpYM0z4X2qlqdwAe0YjM,67
43
- plain/admin/templates/admin/search.html,sha256=c04SZ5MbF1iKBYSGospQwB1UtU2_JAi_npaaPUtuJIk,620
42
+ plain/admin/templates/admin/search.html,sha256=zfwnXoztAFnj8OmwxJcWaqo-SKCy50bLwfwSrAnAtoQ,1799
44
43
  plain/admin/templates/admin/cards/base.html,sha256=2HRIxvt5Kf0MPVv7XLQZcc7vfz3YR_WLsrVgbQtyN5I,933
45
44
  plain/admin/templates/admin/cards/card.html,sha256=OWR1kF4vKtr06x_Q34Z01UmKEv_Jdq2Ws3v3RARaxCY,263
46
45
  plain/admin/templates/admin/cards/chart.html,sha256=boQRaWXiZvwKkMudT3IDsRvaofv5LHgbSeWr_HEGghg,642
@@ -56,25 +55,28 @@ plain/admin/templates/admin/values/list.html,sha256=vqUOuJglFDbOBuKCA11VoIZHWVt_
56
55
  plain/admin/templates/admin/values/model.html,sha256=_aX_t2VQYt_bN_jQBky5IDi49cbq7dzBLuisb3BY_is,410
57
56
  plain/admin/templates/admin/values/queryset.html,sha256=YU-mDxHzinWWLUBE-oX3dOMOMyHymzrdeZyxXGMF5Ss,138
58
57
  plain/admin/templates/elements/admin/Checkbox.html,sha256=2hUSWCbazaJKyZdsk2shF0qN6kSeV20HVLdRitC_KfQ,213
59
- plain/admin/templates/elements/admin/CheckboxField.html,sha256=B6s4jXK96MfMJY8X9YgMfR4UKWkHogK7Dfn81jbW0fk,206
58
+ plain/admin/templates/elements/admin/CheckboxField.html,sha256=oj8ur5fX5ftOjhHEQ8QcFobnPBjXrEfxFxzVpwU8-nw,274
60
59
  plain/admin/templates/elements/admin/FieldErrors.html,sha256=YO150DwGG8tf8Q4d1Cf59gpchXzF-n8FSse2GqOX3cA,108
60
+ plain/admin/templates/elements/admin/Help.html,sha256=qivAiGNW97Ht9Vmq09m5bIk1IbMLlYuRIFzClVll5_Y,53
61
61
  plain/admin/templates/elements/admin/Input.html,sha256=7rziKkGDgg-fQ4Yfb_hjR9pOt0DFs8UeXicN6MCoM4s,371
62
- plain/admin/templates/elements/admin/InputField.html,sha256=J3pvMs3ajYJ1G1iE0vFaS9kjSppe2HyLIbEl3WbqkuY,156
63
- plain/admin/templates/elements/admin/Label.html,sha256=OsSkdbeREkDwdLSxXTLjgnycvFf69j4FPTKciDFf-Z4,96
62
+ plain/admin/templates/elements/admin/InputField.html,sha256=iZuhlGxWWQwmXsYXjGHF-5V8En24EWa7HGanDRwNvUs,220
63
+ plain/admin/templates/elements/admin/Label.html,sha256=RVZZjrv4ff_ujSmKu2M7HngIycImGhPXbja-kF03OC8,249
64
64
  plain/admin/templates/elements/admin/Select.html,sha256=CUJD4cHno_bc0g_SQN0IV0a5sZL7Gx4fFB44xBse-Ic,458
65
- plain/admin/templates/elements/admin/SelectField.html,sha256=thvPmQzvi65BnGsErVtLwZUKYvsTpz4onrMwKXMuXA4,157
65
+ plain/admin/templates/elements/admin/SelectField.html,sha256=P2-vXifOs2-ie20AgLyni6Oy0iz0dAeOxBBGrZV4nIg,221
66
66
  plain/admin/templates/elements/admin/Submit.html,sha256=1Lgn3Du9rXplbM3V12z2JckSaiWPlPGLP48xIZ887AA,150
67
+ plain/admin/templates/elements/admin/Textarea.html,sha256=zi9A_NAsXdZXpVTAS1KXNjQyhtVrqjyQvTHUPtf64uM,275
68
+ plain/admin/templates/elements/admin/TextareaField.html,sha256=4IOJapBNEfhUpMkkLW-gliIefZCEMn5aKyW4QagfcNw,223
67
69
  plain/admin/templates/querystats/querystats.html,sha256=CMH3TDBXXxoxrICMIxiLfo4cN7ae9DMCg3WNmZR8M_o,3504
68
70
  plain/admin/templates/querystats/toolbar.html,sha256=dePs614akVWUD8IlgzvQ0TREThv1ttKPj-yOPzJxmXM,3574
69
- plain/admin/templates/toolbar/toolbar.html,sha256=k76DXO8NrnFKGZpDA0DASdesFvw6qt8vv_T9CqCLE6U,6504
71
+ plain/admin/templates/toolbar/toolbar.html,sha256=KcGAG6kRmx60wfqEsdD5C4nDMilH-JvPjHoU6EktfaY,5985
70
72
  plain/admin/views/__init__.py,sha256=nF6AENZ3Xxyi08OTRrF6e-HYBkZSFj7XBK2mVzMYqN4,846
71
- plain/admin/views/base.py,sha256=ueMH1kvLInceIqKeR2w8HSiIT0MlAtv6i73k7ijsNUU,3943
72
- plain/admin/views/models.py,sha256=0zSrxvZa1ARmqUeSzKqXNS5fT0bVwydsNdSOK5AUhk8,7287
73
+ plain/admin/views/base.py,sha256=0EZPhc7h7QKj8-jhZ2pLk1Pe-eTIp4dL5_JwY3F8gY8,3508
74
+ plain/admin/views/models.py,sha256=M4qoz3IpZuD_9DG25vKUNnfijAJhj33sXSciw2edkGE,7205
73
75
  plain/admin/views/objects.py,sha256=5jipTCJBnypM8nyD9YF-i2MLT9E4aWJbIK2GNMdtel0,11319
74
- plain/admin/views/registry.py,sha256=aGLu9GMraLJBl60Kpfa6PXgno1vFsQZZI3YlXHClPYg,3504
76
+ plain/admin/views/registry.py,sha256=Lxib4YSQCMHb_zACnLKymJakV8jCZPWYll7J8-aV9Xw,3712
75
77
  plain/admin/views/types.py,sha256=ONMMdUoapgMoUVYgSIe-4YCdfvaVMQ4jgPWYiMo0pDk,178
76
78
  plain/admin/views/viewsets.py,sha256=dqMlQ6kLn9iqd9BwBWAZT1S271wH1FdfM5HXbOgBMEw,1655
77
- plain_admin-0.17.0.dist-info/METADATA,sha256=h7ZFRPzMeEMlOuHnMFk724vpfIrtG3mFKorPYSodL4A,6821
78
- plain_admin-0.17.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
79
- plain_admin-0.17.0.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
80
- plain_admin-0.17.0.dist-info/RECORD,,
79
+ plain_admin-0.19.0.dist-info/METADATA,sha256=Ji-WLwjWtFpvVTKPI7mEBBwWMQB-hJ1zoZ09B4QAqqg,6821
80
+ plain_admin-0.19.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
81
+ plain_admin-0.19.0.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
82
+ plain_admin-0.19.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- {% extends "admin/base.html" %}
2
-
3
- {% block content %}
4
-
5
- <form method="post">
6
- {{ csrf_input }}
7
- {% block form_content %}{% endblock %}
8
- <button class="px-5 py-2 mt-6 text-white bg-blue-600 rounded hover:bg-blue-700" type="submit">
9
- Save
10
- </button>
11
- </form>
12
-
13
- {% endblock %}