plain.admin 0.18.0__tar.gz → 0.19.1__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.
- {plain_admin-0.18.0 → plain_admin-0.19.1}/PKG-INFO +1 -1
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/cards/base.py +3 -4
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/base.html +1 -1
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Textarea.html +1 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/urls.py +0 -2
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/base.py +2 -20
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/models.py +17 -18
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/registry.py +18 -10
- {plain_admin-0.18.0 → plain_admin-0.19.1}/pyproject.toml +1 -1
- {plain_admin-0.18.0 → plain_admin-0.19.1}/.gitignore +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/LICENSE +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/README.md +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/README.md +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/admin.css +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/admin.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/chart.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/jquery-3.6.1.slim.min.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/list.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/popper.min.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/admin/tippy-bundle.umd.min.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/assets/toolbar/toolbar.js +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/cards/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/cards/charts.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/cards/tables.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/config.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/dates.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/default_settings.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/README.md +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/middleware.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/models.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/permissions.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/settings.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/urls.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/impersonate/views.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/middleware.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/README.md +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/core.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/middleware.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/urls.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/querystats/views.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/cards/base.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/cards/card.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/cards/chart.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/cards/table.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/delete.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/detail.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/index.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/list.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/page.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/search.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/UUID.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/bool.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/datetime.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/default.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/dict.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/get_display.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/img.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/list.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/model.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/queryset.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Checkbox.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/CheckboxField.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/FieldErrors.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Help.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Input.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/InputField.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Label.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Select.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/SelectField.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Submit.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/TextareaField.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/querystats/querystats.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/querystats/toolbar.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/toolbar/toolbar.html +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/toolbar.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/objects.py +12 -12
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/types.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/views/viewsets.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/app/settings.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/app/urls.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/app/users/migrations/0001_initial.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/app/users/migrations/__init__.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/app/users/models.py +0 -0
- {plain_admin-0.18.0 → plain_admin-0.19.1}/tests/test_admin.py +0 -0
@@ -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
|
-
|
64
|
-
|
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
|
@@ -78,7 +78,7 @@
|
|
78
78
|
{% for view in views %}
|
79
79
|
{% set url = view.get_view_url() %}
|
80
80
|
<a
|
81
|
-
{% if url == request.path %}data-active{% endif %}
|
81
|
+
{% if url == request.path or view in parent_view_classes %}data-active{% endif %}
|
82
82
|
class="data-[active]:bg-white/20 data-[active]:text-white flex items-center px-2 py-1 mt-px -mx-2 text-sm rounded hover:text-stone-300 text-stone-400/80 hover:bg-white/5"
|
83
83
|
href="{{ url }}">
|
84
84
|
{{ view.get_nav_title() }}
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Textarea.html
RENAMED
@@ -3,5 +3,6 @@
|
|
3
3
|
name="{{ field.html_name }}"
|
4
4
|
class="block w-full text-sm border rounded border-white/10 bg-white/5"
|
5
5
|
rows="{{ rows|default(3) }}"
|
6
|
+
spellcheck="{{ spellcheck|default('default') }}"
|
6
7
|
{% if field.field.required %}required{% endif %}
|
7
8
|
>{{ field.value() or "" }}</textarea>
|
@@ -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()
|
@@ -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
|
-
|
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.__qualname__}".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
|
-
|
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
|
72
|
-
|
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 =
|
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
|
-
|
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
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/admin/values/get_display.html
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/Checkbox.html
RENAMED
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/CheckboxField.html
RENAMED
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/FieldErrors.html
RENAMED
File without changes
|
File without changes
|
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/InputField.html
RENAMED
File without changes
|
File without changes
|
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/SelectField.html
RENAMED
File without changes
|
File without changes
|
{plain_admin-0.18.0 → plain_admin-0.19.1}/plain/admin/templates/elements/admin/TextareaField.html
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -306,18 +306,6 @@ class AdminDetailView(AdminView, DetailView):
|
|
306
306
|
|
307
307
|
return links
|
308
308
|
|
309
|
-
def get_success_url(self, form):
|
310
|
-
if detail_url := self.get_detail_url(self.object):
|
311
|
-
return detail_url
|
312
|
-
|
313
|
-
if list_url := self.get_list_url():
|
314
|
-
return list_url
|
315
|
-
|
316
|
-
if update_url := self.get_update_url(self.object):
|
317
|
-
return update_url
|
318
|
-
|
319
|
-
return super().get_success_url(form)
|
320
|
-
|
321
309
|
|
322
310
|
class AdminUpdateView(AdminView, UpdateView):
|
323
311
|
template_name = None
|
@@ -355,6 +343,18 @@ class AdminUpdateView(AdminView, UpdateView):
|
|
355
343
|
|
356
344
|
return links
|
357
345
|
|
346
|
+
def get_success_url(self, form):
|
347
|
+
if detail_url := self.get_detail_url(self.object):
|
348
|
+
return detail_url
|
349
|
+
|
350
|
+
if list_url := self.get_list_url():
|
351
|
+
return list_url
|
352
|
+
|
353
|
+
if update_url := self.get_update_url(self.object):
|
354
|
+
return update_url
|
355
|
+
|
356
|
+
return super().get_success_url(form)
|
357
|
+
|
358
358
|
|
359
359
|
class AdminDeleteView(AdminView, DeleteView):
|
360
360
|
template_name = "admin/delete.html"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|