slthcore 0.4.8__tar.gz → 0.5.0__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.
Potentially problematic release.
This version of slthcore might be problematic. Click here for more details.
- {slthcore-0.4.8/slthcore.egg-info → slthcore-0.5.0}/PKG-INFO +1 -1
- {slthcore-0.4.8 → slthcore-0.5.0}/setup.py +1 -1
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/__init__.py +2 -2
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/application.py +78 -16
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/__init__.py +1 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/components.py +2 -2
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/__init__.py +72 -32
- slthcore-0.5.0/slth/endpoints/settings.py +60 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/user.py +6 -3
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/factory.py +5 -5
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/forms.py +34 -26
- slthcore-0.5.0/slth/integrations/deepseek/__init__.py +36 -0
- slthcore-0.5.0/slth/integrations/google/gemini.py +23 -0
- slthcore-0.5.0/slth/integrations/google/places.py +41 -0
- slthcore-0.5.0/slth/integrations/google/vision.py +18 -0
- slthcore-0.5.0/slth/integrations/justvoip/__init__.py +15 -0
- slthcore-0.5.0/slth/integrations/mercadopago/__init__.py +48 -0
- slthcore-0.5.0/slth/integrations/openai/chatgpt.py +30 -0
- slthcore-0.5.0/slth/integrations/viacep/__init__.py +6 -0
- slthcore-0.5.0/slth/integrations/whatsapp/__init__.py +9 -0
- slthcore-0.5.0/slth/management/commands/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/management/commands/api.py +26 -3
- slthcore-0.5.0/slth/middleware/__init__.py +0 -0
- slthcore-0.5.0/slth/migrations/0014_settings.py +40 -0
- slthcore-0.5.0/slth/migrations/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/models.py +24 -3
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/oauth.py +10 -5
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/queryset.py +81 -26
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/serializer.py +95 -32
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/css/slth.css +14 -7
- slthcore-0.5.0/slth/static/js/slth.min.js +270 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/templates/index.html +7 -15
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/utils.py +8 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/views.py +1 -1
- {slthcore-0.4.8 → slthcore-0.5.0/slthcore.egg-info}/PKG-INFO +1 -1
- {slthcore-0.4.8 → slthcore-0.5.0}/slthcore.egg-info/SOURCES.txt +14 -0
- slthcore-0.4.8/slth/static/js/slth.min.js +0 -251
- {slthcore-0.4.8 → slthcore-0.5.0}/MANIFEST.in +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/setup.cfg +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/apps.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/configure/__main__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/__main__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/__pycache__/__main__.cpython-312.pyc +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/.DS_Store +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/.gitignore +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/asgi.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/endpoints/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/models.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/settings.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/tests.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/urls.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/api/wsgi.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/entrypoint.sh +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/manage.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/backend/requirements.txt +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/base.env +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/docker-compose.yml +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/frontend/package.json +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/frontend/src/main.jsx +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/frontend/vite.config.js +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/local.env +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/run.sh +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/selenium/run.sh +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/cmd/init/boilerplate/test.sh +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/db/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/db/generic.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/db/models.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/auth.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/deletion.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/dev.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/email.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/job.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/log.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/profile.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/pushsubscription.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/report.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/role.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/task.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/timezone.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/endpoints/whatsappnotification.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/exceptions.py +0 -0
- {slthcore-0.4.8/slth/management → slthcore-0.5.0/slth/integrations}/__init__.py +0 -0
- {slthcore-0.4.8/slth/management/commands → slthcore-0.5.0/slth/integrations/google}/__init__.py +0 -0
- {slthcore-0.4.8/slth/middleware → slthcore-0.5.0/slth/integrations/openai}/__init__.py +0 -0
- {slthcore-0.4.8/slth/migrations → slthcore-0.5.0/slth/management}/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/management/commands/integration_test.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/management/commands/sync.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/management/commands/worker.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/middleware/timezone.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0001_initial.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0002_email_role_pushsubscription_error.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0003_rename_photo_profile_alter_profile_options.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0004_alter_profile_photo.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0005_alter_profile_photo.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0006_user.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0007_deletion_log.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0008_alter_deletion_datetime_alter_log_datetime.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0009_remove_email_from_email_email_action_email_attempt_and_more.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0010_email_key_alter_email_action_alter_email_attempt_and_more.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0011_usertimezone.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0012_timezone_remove_usertimezone_key_and_more.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/migrations/0013_whatsappnotification.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/notifications.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/pdf/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/pdf/tests.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/permissions.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/printer.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/roles.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/selenium/__init__.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/selenium/browser.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/.DS_Store +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/css/.DS_Store +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/images/placeholder.png +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/js/index.min.js +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/static/js/react.min.js +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/statistics.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/tasks.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/templates/email.html +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/templates/report.html +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/templates/service-worker.js +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/templates/signature.html +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/tests.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/threadlocal.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/tz.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slth/urls.py +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slthcore.egg-info/dependency_links.txt +0 -0
- {slthcore-0.4.8 → slthcore-0.5.0}/slthcore.egg-info/top_level.txt +0 -0
|
@@ -64,8 +64,8 @@ class JSONDecoder(json.JSONDecoder):
|
|
|
64
64
|
return obj
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def dumps(data):
|
|
68
|
-
return json.dumps(data, cls=JSONEncoder)
|
|
67
|
+
def dumps(data, indent=1, ensure_ascii=False):
|
|
68
|
+
return json.dumps(data, indent=indent, ensure_ascii=ensure_ascii, cls=JSONEncoder)
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def loads(data):
|
|
@@ -8,7 +8,8 @@ APPLICATION_CLASS = None
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Style():
|
|
11
|
-
def __init__(self, color="black", background="inherite", border="none"):
|
|
11
|
+
def __init__(self, name, color="black", background="inherite", border="none"):
|
|
12
|
+
self.name = name
|
|
12
13
|
self.update(color=color, background=background, border=border)
|
|
13
14
|
|
|
14
15
|
def update(self, color=None, background=None, border=None):
|
|
@@ -19,18 +20,70 @@ class Style():
|
|
|
19
20
|
if border:
|
|
20
21
|
self.border = border
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
def to_css(self):
|
|
24
|
+
return f"""
|
|
25
|
+
--{self.name}-color: { self.color };
|
|
26
|
+
--{self.name}-border: { self.border };
|
|
27
|
+
--{self.name}-background: { self.background };
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
class ColorSchema:
|
|
31
|
+
def to_css(self):
|
|
32
|
+
css = []
|
|
33
|
+
css.append("<style>")
|
|
34
|
+
css.append(":root{")
|
|
35
|
+
css.append(f"--border-radius: {self.border_radius}px;")
|
|
36
|
+
css.append(self.default.to_css())
|
|
37
|
+
css.append(self.header.to_css())
|
|
38
|
+
css.append(self.footer.to_css())
|
|
39
|
+
css.append(self.fieldset.to_css())
|
|
40
|
+
css.append(self.input.to_css())
|
|
41
|
+
css.append(self.primary.to_css())
|
|
42
|
+
css.append(self.secondary.to_css())
|
|
43
|
+
css.append(self.auxiliary.to_css())
|
|
44
|
+
css.append(self.highlight.to_css())
|
|
45
|
+
css.append(self.info.to_css())
|
|
46
|
+
css.append(self.success.to_css())
|
|
47
|
+
css.append(self.warning.to_css())
|
|
48
|
+
css.append(self.danger.to_css())
|
|
49
|
+
css.append("</style>")
|
|
50
|
+
return "\n".join(css)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class Light(ColorSchema):
|
|
24
54
|
def __init__(self):
|
|
25
|
-
self.
|
|
26
|
-
self.
|
|
27
|
-
self.
|
|
28
|
-
self.
|
|
29
|
-
|
|
30
|
-
self.
|
|
31
|
-
self.
|
|
32
|
-
self.
|
|
33
|
-
self.
|
|
55
|
+
self.border_radius = 0
|
|
56
|
+
self.default: Style = Style("default", color="#383838", background="#FFFFFF")
|
|
57
|
+
self.header: Style = Style("header", color="#383838", background="#FFFFFF")
|
|
58
|
+
self.footer: Style = Style("footer", color="#383838", background="#FFFFFF")
|
|
59
|
+
self.fieldset: Style = Style("fieldset", color="#383838", background="#FFFFFF")
|
|
60
|
+
self.input: Style = Style("input", border="solid 1px #d9d9d9", background="#FFFFFF")
|
|
61
|
+
self.primary:Style = Style("primary", color="#1351b4", background="#1351b4")
|
|
62
|
+
self.secondary:Style = Style("secondary", color="#071e41")
|
|
63
|
+
self.auxiliary:Style = Style("auxiliary", color="#2670e8", background="#f8f8f8")
|
|
64
|
+
self.highlight:Style = Style("hightlight", color="#0c326f")
|
|
65
|
+
self.info:Style = Style("info", color="#1351b4", background="#d4e5ff")
|
|
66
|
+
self.success:Style = Style("success", color="#ffffff", background="#1351b4")
|
|
67
|
+
self.warning:Style = Style("warning", color="#fff5c2")
|
|
68
|
+
self.danger:Style = Style("danger", color="#e52207")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Dark(ColorSchema):
|
|
72
|
+
def __init__(self):
|
|
73
|
+
self.border_radius = 3
|
|
74
|
+
self.default: Style = Style("default", color="#c3d0e5", background="#0D1117")
|
|
75
|
+
self.header: Style = Style("header", color="#383838", background="#FFFFFF")
|
|
76
|
+
self.footer: Style = Style("footer", color="#383838", background="#FFFFFF")
|
|
77
|
+
self.fieldset: Style = Style("fieldset", color="#91aad2", background="#262c35")
|
|
78
|
+
self.input: Style = Style("input", border="0", background="#0D1117")
|
|
79
|
+
self.primary:Style = Style("primary", color="#c3d0e5", background="#90C4F9")
|
|
80
|
+
self.secondary:Style = Style("secondary", color="#071e41")
|
|
81
|
+
self.auxiliary:Style = Style("auxiliary", color="#91aad2", background="#262c35")
|
|
82
|
+
self.highlight:Style = Style("hightlight", color="#0c326f")
|
|
83
|
+
self.info:Style = Style("info", color="#c3d0e5", background="#262c35")
|
|
84
|
+
self.success:Style = Style("success", color="#c3d0e5", background="#121f1a", border="1px solid #3b622b")
|
|
85
|
+
self.warning:Style = Style("warning", color="#fff5c2")
|
|
86
|
+
self.danger:Style = Style("danger", color="#e52207")
|
|
34
87
|
|
|
35
88
|
|
|
36
89
|
class Groups(dict):
|
|
@@ -71,8 +124,8 @@ class Menu(dict):
|
|
|
71
124
|
return items
|
|
72
125
|
|
|
73
126
|
class Oauth(list):
|
|
74
|
-
def add(self, name, client_id, client_secret, redirect_uri, authorize_url, access_token_url, user_data_url,
|
|
75
|
-
super().append(dict(name=name, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, authorize_url=authorize_url, access_token_url=access_token_url, user_data_url=user_data_url,
|
|
127
|
+
def add(self, name, client_id, client_secret, redirect_uri, authorize_url, access_token_url, user_data_url, user_username, user_email=None, user_scope=None, user_create=False, user_logout_url=None):
|
|
128
|
+
super().append(dict(name=name, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, authorize_url=authorize_url, access_token_url=access_token_url, user_data_url=user_data_url, user_username=user_username, user_email=user_email, user_scope=user_scope, user_create=user_create, user_logout_url=user_logout_url))
|
|
76
129
|
|
|
77
130
|
def serialize(self):
|
|
78
131
|
data = []
|
|
@@ -96,6 +149,7 @@ class Dashboard():
|
|
|
96
149
|
def __init__(self):
|
|
97
150
|
self.actions:List = List()
|
|
98
151
|
self.toolbar:List = List()
|
|
152
|
+
self.todo:List = List()
|
|
99
153
|
self.top:List = List()
|
|
100
154
|
self.center:List = List()
|
|
101
155
|
self.boxes:List = List()
|
|
@@ -107,6 +161,12 @@ class Dashboard():
|
|
|
107
161
|
self.index = "dashboard"
|
|
108
162
|
|
|
109
163
|
|
|
164
|
+
class Theme:
|
|
165
|
+
def __init__(self):
|
|
166
|
+
self.light = Light()
|
|
167
|
+
self.dark = Dark()
|
|
168
|
+
|
|
169
|
+
|
|
110
170
|
class ApplicationMetaclass(type):
|
|
111
171
|
|
|
112
172
|
def __new__(mcs, name, bases, attrs):
|
|
@@ -124,6 +184,7 @@ class Application(metaclass=ApplicationMetaclass):
|
|
|
124
184
|
self.subtitle = "Take your time!"
|
|
125
185
|
self.icon = "/static/images/logo.png"
|
|
126
186
|
self.logo = "/static/images/logo.png"
|
|
187
|
+
self.brand = None
|
|
127
188
|
self.version = "0.0.1"
|
|
128
189
|
self.oauth:Oauth = Oauth()
|
|
129
190
|
self.groups:Groups = Groups()
|
|
@@ -136,7 +197,8 @@ class Application(metaclass=ApplicationMetaclass):
|
|
|
136
197
|
|
|
137
198
|
def serialize(self, request):
|
|
138
199
|
icon = build_url(request, self.icon)
|
|
139
|
-
logo = build_url(request, self.logo)
|
|
200
|
+
logo = build_url(request, self.brand or self.logo)
|
|
201
|
+
title = self.title if self.brand is None else None
|
|
140
202
|
if request.user.is_authenticated:
|
|
141
203
|
user = request.user.username.split()[0].split("@")[0]
|
|
142
204
|
profile = apps.get_model("slth", "profile").objects.filter(user=request.user).first()
|
|
@@ -158,7 +220,7 @@ class Application(metaclass=ApplicationMetaclass):
|
|
|
158
220
|
type="application",
|
|
159
221
|
icon=icon,
|
|
160
222
|
navbar=dict(
|
|
161
|
-
type="navbar", title=
|
|
223
|
+
type="navbar", title=title, subtitle=self.subtitle, logo=logo, user=user, **endpoints
|
|
162
224
|
),
|
|
163
225
|
menu=dict(
|
|
164
226
|
type="menu", items=self.menu.process(request), user=user, image=photo
|
|
@@ -95,9 +95,9 @@ class Indicators(dict):
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
class Boxes(dict):
|
|
98
|
-
def __init__(self, title):
|
|
98
|
+
def __init__(self, title=None):
|
|
99
99
|
self["type"] = "boxes"
|
|
100
|
-
self["title"] = str(title)
|
|
100
|
+
self["title"] = str(title) if title else None
|
|
101
101
|
self["items"] = []
|
|
102
102
|
|
|
103
103
|
def append(self, icon, label, url, style=None):
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import io
|
|
2
|
-
import
|
|
2
|
+
import os
|
|
3
3
|
import inspect
|
|
4
4
|
from ..models import Log
|
|
5
5
|
from django.apps import apps
|
|
6
6
|
from typing import TypeVar, Generic
|
|
7
7
|
from django.core.cache import cache
|
|
8
|
-
from django.conf import settings
|
|
9
8
|
from django.utils.text import slugify
|
|
10
9
|
from django.db import models
|
|
11
|
-
from django.http import JsonResponse, HttpResponse
|
|
10
|
+
from django.http import JsonResponse, HttpResponse, StreamingHttpResponse
|
|
12
11
|
from ..factory import FormFactory
|
|
13
12
|
from django.core.exceptions import ValidationError
|
|
14
13
|
from slth import forms
|
|
@@ -26,10 +25,9 @@ from ..components import (
|
|
|
26
25
|
from slth.application import Application as ApplicationConfig
|
|
27
26
|
from ..exceptions import JsonResponseException, ReadyResponseException
|
|
28
27
|
from ..utils import build_url, append_url
|
|
29
|
-
from ..models import
|
|
28
|
+
from ..models import Log, Job
|
|
30
29
|
from slth.queryset import QuerySet
|
|
31
|
-
from slth import ENDPOINTS
|
|
32
|
-
from .. import oauth
|
|
30
|
+
from slth import ENDPOINTS, dumps
|
|
33
31
|
from ..threadlocal import tl
|
|
34
32
|
from ..tasks import Task
|
|
35
33
|
|
|
@@ -44,7 +42,8 @@ class ApiResponse(JsonResponse):
|
|
|
44
42
|
self["Access-Control-Allow-Headers"] = "*"
|
|
45
43
|
self["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS, PUT, DELETE, PATCH"
|
|
46
44
|
self["Access-Control-Max-Age"] = "600"
|
|
47
|
-
|
|
45
|
+
x = args[0]
|
|
46
|
+
#os.system('clear'); print(dumps(args[0]))
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
class EnpointMetaclass(type):
|
|
@@ -65,6 +64,7 @@ class Endpoint(metaclass=EnpointMetaclass):
|
|
|
65
64
|
cache = cache
|
|
66
65
|
|
|
67
66
|
def __init__(self):
|
|
67
|
+
self.form: Form | ModelForm = None
|
|
68
68
|
self.base_url = None
|
|
69
69
|
self.request = None
|
|
70
70
|
self.source = None
|
|
@@ -92,7 +92,8 @@ class Endpoint(metaclass=EnpointMetaclass):
|
|
|
92
92
|
return self.formfactory().fields(*fields) if fields else {}
|
|
93
93
|
|
|
94
94
|
def post(self):
|
|
95
|
-
|
|
95
|
+
redirect = '.' if 'only' in self.request.GET else self.form._redirect
|
|
96
|
+
return Response(message="Ação realizada com sucesso", redirect=redirect)
|
|
96
97
|
|
|
97
98
|
def check_permission(self):
|
|
98
99
|
return self.request.user.is_superuser
|
|
@@ -116,6 +117,7 @@ class Endpoint(metaclass=EnpointMetaclass):
|
|
|
116
117
|
raise JsonResponseException(dict(type="redirect", url=url, autosubmit=self.request.GET.get('autosubmit')))
|
|
117
118
|
|
|
118
119
|
def render(self, data, template=None, pdf=False, autoreload=None):
|
|
120
|
+
from django.conf import settings
|
|
119
121
|
base_url=settings.SITE_URL
|
|
120
122
|
data.update(base_url=base_url)
|
|
121
123
|
if template is None:
|
|
@@ -150,15 +152,16 @@ class Endpoint(metaclass=EnpointMetaclass):
|
|
|
150
152
|
elif isinstance(data, Serializer):
|
|
151
153
|
data = data.contextualize(self.request).settitle(title)
|
|
152
154
|
elif isinstance(data, FormFactory):
|
|
153
|
-
form = self.getform(data.settitle(title).
|
|
154
|
-
if self.request.method == "POST" or (title and self.request.GET.get("form") == form._key):
|
|
155
|
+
self.form = self.getform(data.settitle(title).build(self))
|
|
156
|
+
if self.request.method == "POST" or (title and self.request.GET.get("form") == self.form._key):
|
|
155
157
|
try:
|
|
156
158
|
if isinstance(self, DeleteEndpoint):
|
|
157
159
|
return self.post()
|
|
158
160
|
else:
|
|
159
|
-
self.cleaned_data = form.submit()
|
|
160
|
-
if form._message or form._redirect or form._dispose:
|
|
161
|
-
|
|
161
|
+
self.cleaned_data = self.form.submit()
|
|
162
|
+
if self.form._message or self.form._redirect or self.form._dispose:
|
|
163
|
+
redirect = '.' if 'only' in self.request.GET else self.form._redirect
|
|
164
|
+
return Response(self.form._message, redirect, dispose=self.form._dispose)
|
|
162
165
|
else:
|
|
163
166
|
return self.post()
|
|
164
167
|
except ValidationError as e:
|
|
@@ -166,9 +169,11 @@ class Endpoint(metaclass=EnpointMetaclass):
|
|
|
166
169
|
dict(type="error", text="\n".join(e.messages), errors={})
|
|
167
170
|
)
|
|
168
171
|
else:
|
|
169
|
-
data = form
|
|
172
|
+
data = self.form
|
|
170
173
|
elif isinstance(data, Form) or isinstance(data, ModelForm):
|
|
171
174
|
data = data.settitle(title)
|
|
175
|
+
elif isinstance(data, HttpResponse) or isinstance(data, StreamingHttpResponse):
|
|
176
|
+
raise ReadyResponseException(data)
|
|
172
177
|
elif self.request.method == "POST":# and not data:
|
|
173
178
|
return self.post()
|
|
174
179
|
return data
|
|
@@ -337,7 +342,6 @@ class PublicEndpoint(Endpoint):
|
|
|
337
342
|
return True
|
|
338
343
|
|
|
339
344
|
|
|
340
|
-
|
|
341
345
|
class ModelEndpoint(Endpoint):
|
|
342
346
|
def __init__(self):
|
|
343
347
|
self.model = self.__orig_bases__[0].__args__[0]
|
|
@@ -503,6 +507,43 @@ class ChildInstanceEndpoint(ChildEndpoint):
|
|
|
503
507
|
return Serializer(self.get_instance()).contextualize(self.request)
|
|
504
508
|
|
|
505
509
|
|
|
510
|
+
class RelationEditEndpoint(Generic[T], ChildEndpoint):
|
|
511
|
+
|
|
512
|
+
def __init__(self, instance):
|
|
513
|
+
self.source = instance
|
|
514
|
+
|
|
515
|
+
def get(self) -> FormFactory:
|
|
516
|
+
return self.formfactory()
|
|
517
|
+
|
|
518
|
+
def formfactory(self) -> FormFactory:
|
|
519
|
+
return FormFactory(self.get_instance())
|
|
520
|
+
|
|
521
|
+
def get_instance(self):
|
|
522
|
+
return self.__orig_bases__[0].__args__[0].objects.get(pk=self.request.GET['id'])
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
class RelationDeleteEndpoint(Generic[T], ChildEndpoint):
|
|
526
|
+
|
|
527
|
+
def __init__(self, instance):
|
|
528
|
+
self.model = self.__orig_bases__[0].__args__[0]
|
|
529
|
+
self.source = instance
|
|
530
|
+
|
|
531
|
+
def get(self) -> FormFactory:
|
|
532
|
+
return FormFactory(self.get_instance()).fields()
|
|
533
|
+
|
|
534
|
+
def post(self):
|
|
535
|
+
self.get_instance().safe_delete(self.request.user.username)
|
|
536
|
+
return super().post()
|
|
537
|
+
|
|
538
|
+
def formfactory(self) -> FormFactory:
|
|
539
|
+
return FormFactory(self.get_instance())
|
|
540
|
+
|
|
541
|
+
def get_instance(self):
|
|
542
|
+
return self.model.objects.get(pk=self.request.GET['id'])
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
|
|
506
547
|
class Search(Endpoint):
|
|
507
548
|
def get(self):
|
|
508
549
|
key = "_options_"
|
|
@@ -529,7 +570,6 @@ class Search(Endpoint):
|
|
|
529
570
|
return result[0:10]
|
|
530
571
|
|
|
531
572
|
|
|
532
|
-
|
|
533
573
|
class Home(PublicEndpoint):
|
|
534
574
|
class Meta:
|
|
535
575
|
verbose_name = ""
|
|
@@ -546,36 +586,36 @@ class Dashboard(Endpoint):
|
|
|
546
586
|
|
|
547
587
|
def get(self):
|
|
548
588
|
application = ApplicationConfig.get_instance()
|
|
549
|
-
serializer =
|
|
589
|
+
serializer = self.serializer()
|
|
590
|
+
if application.dashboard.actions:
|
|
591
|
+
serializer.actions(*application.dashboard.actions)
|
|
592
|
+
if application.dashboard.todo:
|
|
593
|
+
serializer.todo(*application.dashboard.todo)
|
|
594
|
+
if application.dashboard.top:
|
|
595
|
+
group = serializer.group("Top")
|
|
596
|
+
for name in application.dashboard.top:
|
|
597
|
+
cls = ENDPOINTS[name]
|
|
598
|
+
endpoint = cls.instantiate(self.request, self)
|
|
599
|
+
if endpoint.check_permission():
|
|
600
|
+
group.endpoint(cls)
|
|
601
|
+
group.parent()
|
|
550
602
|
if application.dashboard.boxes:
|
|
551
603
|
boxes = Boxes("Acesso Rápido")
|
|
552
604
|
for name in application.dashboard.boxes:
|
|
553
605
|
cls = ENDPOINTS[name]
|
|
554
606
|
endpoint = cls().contextualize(self.request)
|
|
555
607
|
if endpoint.check_permission():
|
|
556
|
-
icon = endpoint.get_icon() or "
|
|
608
|
+
icon = endpoint.get_icon() or "link"
|
|
557
609
|
label = endpoint.get_verbose_name()
|
|
558
610
|
url = build_url(self.request, cls.get_api_url())
|
|
559
611
|
boxes.append(icon, label, url)
|
|
560
|
-
serializer.append(
|
|
561
|
-
if application.dashboard.top:
|
|
562
|
-
group = serializer.group("Top")
|
|
563
|
-
for name in application.dashboard.top:
|
|
564
|
-
cls = ENDPOINTS[name]
|
|
565
|
-
endpoint = cls.instantiate(self.request, self)
|
|
566
|
-
if endpoint.check_permission():
|
|
567
|
-
group.endpoint(
|
|
568
|
-
endpoint.get_verbose_name(), cls, wrap=False
|
|
569
|
-
)
|
|
570
|
-
group.parent()
|
|
612
|
+
serializer.append(boxes)
|
|
571
613
|
if application.dashboard.center:
|
|
572
614
|
for name in application.dashboard.center:
|
|
573
615
|
cls = ENDPOINTS[name]
|
|
574
616
|
endpoint = cls.instantiate(self.request, self)
|
|
575
617
|
if endpoint.check_permission():
|
|
576
|
-
serializer.endpoint(
|
|
577
|
-
endpoint.get_verbose_name(), cls, wrap=False
|
|
578
|
-
)
|
|
618
|
+
serializer.endpoint(cls)
|
|
579
619
|
return serializer
|
|
580
620
|
|
|
581
621
|
def check_permission(self):
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from slth import endpoints
|
|
2
|
+
from ..models import Settings as SettingsModel
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Settings(endpoints.ListEndpoint[SettingsModel]):
|
|
6
|
+
class Meta:
|
|
7
|
+
modal = False
|
|
8
|
+
verbose_name = 'Configurações'
|
|
9
|
+
|
|
10
|
+
def get(self):
|
|
11
|
+
return (
|
|
12
|
+
super().get()
|
|
13
|
+
.actions('settings.add', 'settings.view', 'settings.edit', 'settings.delete')
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Add(endpoints.AddEndpoint[SettingsModel]):
|
|
18
|
+
class Meta:
|
|
19
|
+
icon = 'plus'
|
|
20
|
+
verbose_name = 'Cadastrar Configuração'
|
|
21
|
+
|
|
22
|
+
def get(self):
|
|
23
|
+
return (
|
|
24
|
+
super().get()
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class View(endpoints.ViewEndpoint[SettingsModel]):
|
|
29
|
+
class Meta:
|
|
30
|
+
modal = False
|
|
31
|
+
icon = 'eye'
|
|
32
|
+
verbose_name = 'Visualizar Configuração'
|
|
33
|
+
|
|
34
|
+
def get(self):
|
|
35
|
+
return (
|
|
36
|
+
super().get()
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Edit(endpoints.EditEndpoint[SettingsModel]):
|
|
41
|
+
class Meta:
|
|
42
|
+
icon = 'pen'
|
|
43
|
+
verbose_name = 'Editar Configuração'
|
|
44
|
+
|
|
45
|
+
def get(self):
|
|
46
|
+
return (
|
|
47
|
+
super().get()
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Delete(endpoints.DeleteEndpoint[SettingsModel]):
|
|
52
|
+
class Meta:
|
|
53
|
+
icon = 'trash'
|
|
54
|
+
verbose_name = 'Excluir Configuração'
|
|
55
|
+
|
|
56
|
+
def get(self):
|
|
57
|
+
return (
|
|
58
|
+
super().get()
|
|
59
|
+
)
|
|
60
|
+
|
|
@@ -9,7 +9,8 @@ class Users(endpoints.ListEndpoint[User]):
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Add(endpoints.AddEndpoint[User]):
|
|
12
|
-
|
|
12
|
+
class Meta:
|
|
13
|
+
icon = "user-plus"
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class View(endpoints.ViewEndpoint[User]):
|
|
@@ -17,11 +18,13 @@ class View(endpoints.ViewEndpoint[User]):
|
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class Edit(endpoints.EditEndpoint[User]):
|
|
20
|
-
|
|
21
|
+
class Meta:
|
|
22
|
+
icon = "user-pen"
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
class Delete(endpoints.DeleteEndpoint[User]):
|
|
24
|
-
|
|
26
|
+
class Meta:
|
|
27
|
+
icon = "user-minus"
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
class ChangePassword(endpoints.ChildInstanceEndpoint):
|
|
@@ -3,7 +3,7 @@ from .serializer import Serializer
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class FormFactory:
|
|
6
|
-
def __init__(self, instance,
|
|
6
|
+
def __init__(self, instance, method='POST'):
|
|
7
7
|
self._instance = instance
|
|
8
8
|
self._fieldsets = {}
|
|
9
9
|
self._values = {}
|
|
@@ -48,7 +48,7 @@ class FormFactory:
|
|
|
48
48
|
self._append_field(field_name)
|
|
49
49
|
for k in values:
|
|
50
50
|
self._append_field(k)
|
|
51
|
-
self.
|
|
51
|
+
self.values(**values)
|
|
52
52
|
self._empty = not self._fieldlist
|
|
53
53
|
return self
|
|
54
54
|
|
|
@@ -84,7 +84,7 @@ class FormFactory:
|
|
|
84
84
|
self._actions.update(kwargs)
|
|
85
85
|
return self
|
|
86
86
|
|
|
87
|
-
def
|
|
87
|
+
def values(self, **kwargs) -> 'FormFactory':
|
|
88
88
|
self._values.update(kwargs)
|
|
89
89
|
return self
|
|
90
90
|
|
|
@@ -106,7 +106,7 @@ class FormFactory:
|
|
|
106
106
|
self._redirect = '.'
|
|
107
107
|
return self
|
|
108
108
|
|
|
109
|
-
def
|
|
109
|
+
def build(self, endpoint):
|
|
110
110
|
from .forms import ModelForm, Form
|
|
111
111
|
|
|
112
112
|
if isinstance(self._instance, Model):
|
|
@@ -135,7 +135,7 @@ class FormFactory:
|
|
|
135
135
|
for name, queryset in self._choices.items():
|
|
136
136
|
form.fields[name].queryset = queryset
|
|
137
137
|
form.fieldsets = self._fieldsets
|
|
138
|
-
form.
|
|
138
|
+
form.values(**self._values)
|
|
139
139
|
if self._display:
|
|
140
140
|
serializer = Serializer(self._instance, request=endpoint.request)
|
|
141
141
|
for title, fields in self._display.items():
|