slthcore 0.4.7__tar.gz → 0.4.9__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.

Files changed (115) hide show
  1. {slthcore-0.4.7/slthcore.egg-info → slthcore-0.4.9}/PKG-INFO +1 -1
  2. {slthcore-0.4.7 → slthcore-0.4.9}/setup.py +1 -2
  3. {slthcore-0.4.7 → slthcore-0.4.9}/slth/__init__.py +9 -14
  4. slthcore-0.4.9/slth/application.py +178 -0
  5. slthcore-0.4.9/slth/cmd/init/boilerplate/backend/api/__init__.py +27 -0
  6. {slthcore-0.4.7 → slthcore-0.4.9}/slth/db/models.py +1 -0
  7. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/__init__.py +66 -103
  8. {slthcore-0.4.7 → slthcore-0.4.9}/slth/factory.py +5 -5
  9. {slthcore-0.4.7 → slthcore-0.4.9}/slth/forms.py +68 -44
  10. slthcore-0.4.9/slth/management/commands/api.py +90 -0
  11. {slthcore-0.4.7 → slthcore-0.4.9}/slth/models.py +7 -4
  12. {slthcore-0.4.7 → slthcore-0.4.9}/slth/notifications.py +3 -2
  13. {slthcore-0.4.7 → slthcore-0.4.9}/slth/oauth.py +5 -4
  14. {slthcore-0.4.7 → slthcore-0.4.9}/slth/queryset.py +7 -0
  15. {slthcore-0.4.7 → slthcore-0.4.9}/slth/serializer.py +7 -3
  16. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/.DS_Store +0 -0
  17. slthcore-0.4.9/slth/static/js/slth.min.js +251 -0
  18. {slthcore-0.4.7 → slthcore-0.4.9}/slth/templates/index.html +9 -9
  19. {slthcore-0.4.7 → slthcore-0.4.9}/slth/utils.py +8 -0
  20. {slthcore-0.4.7 → slthcore-0.4.9}/slth/views.py +7 -6
  21. {slthcore-0.4.7 → slthcore-0.4.9/slthcore.egg-info}/PKG-INFO +1 -1
  22. {slthcore-0.4.7 → slthcore-0.4.9}/slthcore.egg-info/SOURCES.txt +2 -1
  23. slthcore-0.4.7/slth/cmd/init/boilerplate/backend/application.yml +0 -64
  24. slthcore-0.4.7/slth/migrations/__init__.py +0 -0
  25. slthcore-0.4.7/slth/static/js/slth.min.js +0 -240
  26. {slthcore-0.4.7 → slthcore-0.4.9}/MANIFEST.in +0 -0
  27. {slthcore-0.4.7 → slthcore-0.4.9}/setup.cfg +0 -0
  28. {slthcore-0.4.7 → slthcore-0.4.9}/slth/apps.py +0 -0
  29. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/configure/__main__.py +0 -0
  30. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/__main__.py +0 -0
  31. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/__pycache__/__main__.cpython-312.pyc +0 -0
  32. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/.DS_Store +0 -0
  33. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/.gitignore +0 -0
  34. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/asgi.py +0 -0
  35. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/endpoints/__init__.py +0 -0
  36. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/models.py +0 -0
  37. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/settings.py +0 -0
  38. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/tests.py +0 -0
  39. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/urls.py +0 -0
  40. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/api/wsgi.py +0 -0
  41. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/entrypoint.sh +0 -0
  42. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/manage.py +0 -0
  43. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/backend/requirements.txt +0 -0
  44. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/base.env +0 -0
  45. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/docker-compose.yml +0 -0
  46. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/frontend/package.json +0 -0
  47. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/frontend/src/main.jsx +0 -0
  48. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/frontend/vite.config.js +0 -0
  49. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/local.env +0 -0
  50. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/run.sh +0 -0
  51. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/selenium/run.sh +0 -0
  52. {slthcore-0.4.7 → slthcore-0.4.9}/slth/cmd/init/boilerplate/test.sh +0 -0
  53. {slthcore-0.4.7 → slthcore-0.4.9}/slth/components.py +0 -0
  54. {slthcore-0.4.7 → slthcore-0.4.9}/slth/db/__init__.py +0 -0
  55. {slthcore-0.4.7 → slthcore-0.4.9}/slth/db/generic.py +0 -0
  56. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/auth.py +0 -0
  57. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/deletion.py +0 -0
  58. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/dev.py +0 -0
  59. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/email.py +0 -0
  60. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/job.py +0 -0
  61. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/log.py +0 -0
  62. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/profile.py +0 -0
  63. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/pushsubscription.py +0 -0
  64. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/report.py +0 -0
  65. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/role.py +0 -0
  66. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/task.py +0 -0
  67. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/timezone.py +0 -0
  68. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/user.py +0 -0
  69. {slthcore-0.4.7 → slthcore-0.4.9}/slth/endpoints/whatsappnotification.py +0 -0
  70. {slthcore-0.4.7 → slthcore-0.4.9}/slth/exceptions.py +0 -0
  71. {slthcore-0.4.7/slth/cmd/init/boilerplate/backend/api → slthcore-0.4.9/slth/management}/__init__.py +0 -0
  72. {slthcore-0.4.7/slth/management → slthcore-0.4.9/slth/management/commands}/__init__.py +0 -0
  73. {slthcore-0.4.7 → slthcore-0.4.9}/slth/management/commands/integration_test.py +0 -0
  74. {slthcore-0.4.7 → slthcore-0.4.9}/slth/management/commands/sync.py +0 -0
  75. {slthcore-0.4.7 → slthcore-0.4.9}/slth/management/commands/worker.py +0 -0
  76. {slthcore-0.4.7/slth/management/commands → slthcore-0.4.9/slth/middleware}/__init__.py +0 -0
  77. {slthcore-0.4.7 → slthcore-0.4.9}/slth/middleware/timezone.py +0 -0
  78. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0001_initial.py +0 -0
  79. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0002_email_role_pushsubscription_error.py +0 -0
  80. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0003_rename_photo_profile_alter_profile_options.py +0 -0
  81. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0004_alter_profile_photo.py +0 -0
  82. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0005_alter_profile_photo.py +0 -0
  83. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0006_user.py +0 -0
  84. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0007_deletion_log.py +0 -0
  85. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0008_alter_deletion_datetime_alter_log_datetime.py +0 -0
  86. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0009_remove_email_from_email_email_action_email_attempt_and_more.py +0 -0
  87. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0010_email_key_alter_email_action_alter_email_attempt_and_more.py +0 -0
  88. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0011_usertimezone.py +0 -0
  89. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0012_timezone_remove_usertimezone_key_and_more.py +0 -0
  90. {slthcore-0.4.7 → slthcore-0.4.9}/slth/migrations/0013_whatsappnotification.py +0 -0
  91. {slthcore-0.4.7/slth/middleware → slthcore-0.4.9/slth/migrations}/__init__.py +0 -0
  92. {slthcore-0.4.7 → slthcore-0.4.9}/slth/pdf/__init__.py +0 -0
  93. {slthcore-0.4.7 → slthcore-0.4.9}/slth/pdf/tests.py +0 -0
  94. {slthcore-0.4.7 → slthcore-0.4.9}/slth/permissions.py +0 -0
  95. {slthcore-0.4.7 → slthcore-0.4.9}/slth/printer.py +0 -0
  96. {slthcore-0.4.7 → slthcore-0.4.9}/slth/roles.py +0 -0
  97. {slthcore-0.4.7 → slthcore-0.4.9}/slth/selenium/__init__.py +0 -0
  98. {slthcore-0.4.7 → slthcore-0.4.9}/slth/selenium/browser.py +0 -0
  99. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/css/.DS_Store +0 -0
  100. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/css/slth.css +0 -0
  101. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/images/placeholder.png +0 -0
  102. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/js/index.min.js +0 -0
  103. {slthcore-0.4.7 → slthcore-0.4.9}/slth/static/js/react.min.js +0 -0
  104. {slthcore-0.4.7 → slthcore-0.4.9}/slth/statistics.py +0 -0
  105. {slthcore-0.4.7 → slthcore-0.4.9}/slth/tasks.py +0 -0
  106. {slthcore-0.4.7 → slthcore-0.4.9}/slth/templates/email.html +0 -0
  107. {slthcore-0.4.7 → slthcore-0.4.9}/slth/templates/report.html +0 -0
  108. {slthcore-0.4.7 → slthcore-0.4.9}/slth/templates/service-worker.js +0 -0
  109. {slthcore-0.4.7 → slthcore-0.4.9}/slth/templates/signature.html +0 -0
  110. {slthcore-0.4.7 → slthcore-0.4.9}/slth/tests.py +0 -0
  111. {slthcore-0.4.7 → slthcore-0.4.9}/slth/threadlocal.py +0 -0
  112. {slthcore-0.4.7 → slthcore-0.4.9}/slth/tz.py +0 -0
  113. {slthcore-0.4.7 → slthcore-0.4.9}/slth/urls.py +0 -0
  114. {slthcore-0.4.7 → slthcore-0.4.9}/slthcore.egg-info/dependency_links.txt +0 -0
  115. {slthcore-0.4.7 → slthcore-0.4.9}/slthcore.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: slthcore
3
- Version: 0.4.7
3
+ Version: 0.4.9
4
4
  Summary: API generator based on yml file
5
5
  Home-page: https://github.com/brenokcc
6
6
  Author: Breno Silva
@@ -1,11 +1,10 @@
1
- import os
2
1
  from setuptools import find_packages, setup
3
2
 
4
3
  install_requires = []
5
4
 
6
5
  setup(
7
6
  name='slthcore',
8
- version='0.4.7',
7
+ version='0.4.9',
9
8
  packages=find_packages(),
10
9
  install_requires=install_requires,
11
10
  include_package_data=True,
@@ -1,6 +1,3 @@
1
- import re
2
- import os
3
- import yaml
4
1
  import json
5
2
  import warnings
6
3
  from pathlib import Path
@@ -15,6 +12,7 @@ import django.db.models.options as options
15
12
  from django.db.models.base import ModelBase
16
13
  from django.db.models import Model
17
14
  from django.core.exceptions import FieldDoesNotExist
15
+ from django.core.exceptions import ObjectDoesNotExist
18
16
  from django.utils.autoreload import autoreload_started
19
17
  from django.core import serializers
20
18
  from django.utils import autoreload
@@ -29,15 +27,6 @@ FILENAME = 'application.yml'
29
27
  ENDPOINTS = {}
30
28
  PROXIED_MODELS = []
31
29
  THREADS = []
32
- APPLICATON = None
33
-
34
- if APPLICATON is None and os.path.exists(FILENAME):
35
- with open(FILENAME) as file:
36
- content = file.read()
37
- for variable in re.findall(r'\$[a-zA-z0-9_]+', content):
38
- content = content.replace(variable, os.environ.get(variable[1:], ''))
39
- APPLICATON = yaml.safe_load(content).get('application')
40
-
41
30
 
42
31
  class JSONEncoder(json.JSONEncoder):
43
32
  def default(self, obj):
@@ -185,13 +174,19 @@ def save_decorator(func):
185
174
  if obj:
186
175
  for field in self._meta.fields:
187
176
  a = getattr(obj, field.name)
188
- b = getattr(self, field.name)
177
+ try:
178
+ b = getattr(self, field.name)
179
+ except ObjectDoesNotExist:
180
+ b = None
189
181
  if a != b:
190
182
  diff[field.verbose_name] = (serialize(a), serialize(b))
191
183
  else:
192
184
  action = 'add'
193
185
  for field in self._meta.fields:
194
- b = getattr(self, field.name)
186
+ try:
187
+ b = getattr(self, field.name)
188
+ except ObjectDoesNotExist:
189
+ b = None
195
190
  if b is not None:
196
191
  diff[field.verbose_name] = (None, serialize(b))
197
192
  func(self, *args, **kwargs)
@@ -0,0 +1,178 @@
1
+
2
+ from slth import ENDPOINTS
3
+ from .utils import build_url
4
+ from django.conf import settings
5
+ from django.apps import apps
6
+
7
+ APPLICATION_CLASS = None
8
+
9
+
10
+ class Style():
11
+ def __init__(self, color="black", background="inherite", border="none"):
12
+ self.update(color=color, background=background, border=border)
13
+
14
+ def update(self, color=None, background=None, border=None):
15
+ if color:
16
+ self.color = color
17
+ if background:
18
+ self.background = background
19
+ if border:
20
+ self.border = border
21
+
22
+
23
+ class Theme():
24
+ def __init__(self):
25
+ self.primary:Style = Style("#1351b4")
26
+ self.secondary:Style = Style("#071e41")
27
+ self.auxiliary:Style = Style("#2670e8")
28
+ self.highlight:Style = Style("#0c326f")
29
+
30
+ self.info:Style = Style("#1351b4", "#d4e5ff")
31
+ self.success:Style = Style("#1351b4")
32
+ self.warning:Style = Style("#fff5c2")
33
+ self.danger:Style = Style("#e52207")
34
+
35
+
36
+ class Groups(dict):
37
+ def add(self, **kwargs):
38
+ self.update(**kwargs)
39
+
40
+ class Menu(dict):
41
+ def add(self, arg):
42
+ self.update(arg)
43
+
44
+ def process(self, request):
45
+ items = []
46
+
47
+ def get_item(k, v):
48
+ if isinstance(v, dict):
49
+ icon, label = k.split(":") if ":" in k else (None, k)
50
+ subitems = []
51
+ for k1, v1 in v.items():
52
+ subitem = get_item(k1, v1)
53
+ if subitem:
54
+ subitems.append(subitem)
55
+ if subitems:
56
+ return dict(dict(icon=icon, label=label, items=subitems))
57
+ else:
58
+ cls = ENDPOINTS.get(v)
59
+ if cls:
60
+ endpoint = cls().instantiate(request, None)
61
+ if endpoint.check_permission() and endpoint.contribute("menu"):
62
+ icon, label = k.split(":") if ":" in k else (None, k)
63
+ url = build_url(request, cls.get_api_url())
64
+ return dict(dict(label=label, url=url, icon=icon))
65
+
66
+ for k, v in self.items():
67
+ item = get_item(k, v)
68
+ if item:
69
+ items.append(item)
70
+
71
+ return items
72
+
73
+ class Oauth(list):
74
+ def add(self, name, client_id, client_secret, redirect_uri, authorize_url, access_token_url, user_data_url, user_logout_url, user_scope, user_create, user_username, user_email):
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, user_logout_url=user_logout_url, user_scope=user_scope, user_create=user_create, user_username=user_username, user_email=user_email))
76
+
77
+ def serialize(self):
78
+ data = []
79
+ for provider in self:
80
+ redirect_uri = "{}{}".format(settings.SITE_URL, provider['redirect_uri'])
81
+ authorize_url = '{}?response_type=code&client_id={}&redirect_uri={}'.format(
82
+ provider['authorize_url'], provider['client_id'], redirect_uri
83
+ )
84
+ if provider.get('scope'):
85
+ authorize_url = '{}&scope={}'.format(authorize_url, provider.get('scope'))
86
+ data.append(dict(label=f'Entrar com {provider["name"]}', url=authorize_url))
87
+ return data
88
+
89
+ class List(list):
90
+
91
+ def add(self, *names):
92
+ super().extend(names)
93
+
94
+
95
+ class Dashboard():
96
+ def __init__(self):
97
+ self.actions:List = List()
98
+ self.toolbar:List = List()
99
+ self.top:List = List()
100
+ self.center:List = List()
101
+ self.boxes:List = List()
102
+ self.search:List = List()
103
+ self.usermenu:List = List()
104
+ self.adder:List = List()
105
+ self.tools:List = List()
106
+ self.settings:List = List()
107
+ self.index = "dashboard"
108
+
109
+
110
+ class ApplicationMetaclass(type):
111
+
112
+ def __new__(mcs, name, bases, attrs):
113
+ global APPLICATION_CLASS
114
+ cls = super().__new__(mcs, name, bases, attrs)
115
+ APPLICATION_CLASS = cls
116
+ return cls
117
+
118
+
119
+ class Application(metaclass=ApplicationMetaclass):
120
+
121
+ def __init__(self):
122
+ self.lang = "pt-br"
123
+ self.title = "Sloth"
124
+ self.subtitle = "Take your time!"
125
+ self.icon = "/static/images/logo.png"
126
+ self.logo = "/static/images/logo.png"
127
+ self.version = "0.0.1"
128
+ self.oauth:Oauth = Oauth()
129
+ self.groups:Groups = Groups()
130
+ self.menu:Menu = Menu()
131
+ self.dashboard = Dashboard()
132
+ self.theme:Theme = Theme()
133
+
134
+ def load(self):
135
+ pass
136
+
137
+ def serialize(self, request):
138
+ icon = build_url(request, self.icon)
139
+ logo = build_url(request, self.logo)
140
+ if request.user.is_authenticated:
141
+ user = request.user.username.split()[0].split("@")[0]
142
+ profile = apps.get_model("slth", "profile").objects.filter(user=request.user).first()
143
+ photo = profile and profile.photo and build_url(request, profile.photo.url) or None
144
+ else:
145
+ user = profile = photo = None
146
+ endpoints = {"actions": [], "usermenu": [], "adder": [], "settings": [], "tools": [], "toolbar": []}
147
+ for entrypoint in endpoints:
148
+ for endpoint_name in getattr(self.dashboard, entrypoint):
149
+ cls = ENDPOINTS[endpoint_name]
150
+ endpoint = cls().instantiate(request, None)
151
+ if endpoint.check_permission() and endpoint.contribute(entrypoint):
152
+ name = endpoint.get_verbose_name()
153
+ url = build_url(request, cls.get_api_url())
154
+ modal = cls.get_metadata("modal", False)
155
+ icon = cls.get_metadata("icon", None)
156
+ endpoints[entrypoint].append(dict(name=name, url=url, modal=modal, icon=icon))
157
+ return dict(
158
+ type="application",
159
+ icon=icon,
160
+ navbar=dict(
161
+ type="navbar", title=self.title, subtitle=self.subtitle, logo=logo, user=user, **endpoints
162
+ ),
163
+ menu=dict(
164
+ type="menu", items=self.menu.process(request), user=user, image=photo
165
+ ),
166
+ footer=dict(
167
+ type="footer", version=self.version
168
+ ),
169
+ oauth=self.oauth.serialize(),
170
+ sponsors=[]
171
+ )
172
+
173
+ @staticmethod
174
+ def get_instance():
175
+ instance = APPLICATION_CLASS()
176
+ instance.load()
177
+ return instance
178
+
@@ -0,0 +1,27 @@
1
+ from slth.application import Application
2
+
3
+
4
+ class ApiApplication(Application):
5
+ def __init__(self):
6
+ super().__init__()
7
+ self.groups.add(administrador="Administrador", operador="Operador")
8
+ self.dashboard.usermenu.add(
9
+ "dev.icons",
10
+ "user.users",
11
+ "log.logs",
12
+ "email.emails",
13
+ "pushsubscription.pushsubscriptions",
14
+ "job.jobs",
15
+ "deletion.deletions",
16
+ "auth.logout",
17
+ )
18
+ self.dashboard.boxes.add("user.users")
19
+ self.dashboard.actions.add()
20
+ self.dashboard.toolbar.add()
21
+ self.dashboard.top.add()
22
+ self.dashboard.center.add()
23
+ self.dashboard.search.add()
24
+ self.dashboard.adder.add()
25
+ self.dashboard.tools.add()
26
+ self.dashboard.settings.add()
27
+ self.menu.add({"Sair": "auth.logout"})
@@ -36,6 +36,7 @@ class IntegerField(IntegerField):
36
36
  field.pick = self.pick
37
37
  return field
38
38
 
39
+
39
40
  class ForeignKey(ForeignKey):
40
41
  def __init__(self, to, on_delete=None, **kwargs):
41
42
  self.pick = kwargs.pop('pick', False)
@@ -1,5 +1,4 @@
1
1
  import io
2
- import json
3
2
  import inspect
4
3
  from ..models import Log
5
4
  from django.apps import apps
@@ -19,20 +18,16 @@ from django.template.loader import render_to_string
19
18
  from ..forms import ModelForm, Form
20
19
  from ..serializer import serialize, Serializer
21
20
  from ..components import (
22
- Application as Application_,
23
- Navbar,
24
- Menu,
25
- Footer,
26
21
  Response,
27
22
  Boxes,
28
23
  TemplateContent,
29
24
  )
25
+ from slth.application import Application as ApplicationConfig
30
26
  from ..exceptions import JsonResponseException, ReadyResponseException
31
27
  from ..utils import build_url, append_url
32
- from ..models import Profile, Log, Job
28
+ from ..models import Log, Job
33
29
  from slth.queryset import QuerySet
34
- from slth import APPLICATON, ENDPOINTS
35
- from .. import oauth
30
+ from slth import ENDPOINTS
36
31
  from ..threadlocal import tl
37
32
  from ..tasks import Task
38
33
 
@@ -68,6 +63,7 @@ class Endpoint(metaclass=EnpointMetaclass):
68
63
  cache = cache
69
64
 
70
65
  def __init__(self):
66
+ self.form: Form | ModelForm = None
71
67
  self.base_url = None
72
68
  self.request = None
73
69
  self.source = None
@@ -153,15 +149,15 @@ class Endpoint(metaclass=EnpointMetaclass):
153
149
  elif isinstance(data, Serializer):
154
150
  data = data.contextualize(self.request).settitle(title)
155
151
  elif isinstance(data, FormFactory):
156
- form = self.getform(data.settitle(title).form(self))
157
- if self.request.method == "POST" or (title and self.request.GET.get("form") == form._key):
152
+ self.form = self.getform(data.settitle(title).build(self))
153
+ if self.request.method == "POST" or (title and self.request.GET.get("form") == self.form._key):
158
154
  try:
159
155
  if isinstance(self, DeleteEndpoint):
160
156
  return self.post()
161
157
  else:
162
- self.cleaned_data = form.submit()
163
- if form._message or form._redirect or form._dispose:
164
- return Response(form._message, form._redirect, dispose=form._dispose)
158
+ self.cleaned_data = self.form.submit()
159
+ if self.form._message or self.form._redirect or self.form._dispose:
160
+ return Response(self.form._message, self.form._redirect, dispose=self.form._dispose)
165
161
  else:
166
162
  return self.post()
167
163
  except ValidationError as e:
@@ -169,7 +165,7 @@ class Endpoint(metaclass=EnpointMetaclass):
169
165
  dict(type="error", text="\n".join(e.messages), errors={})
170
166
  )
171
167
  else:
172
- data = form
168
+ data = self.form
173
169
  elif isinstance(data, Form) or isinstance(data, ModelForm):
174
170
  data = data.settitle(title)
175
171
  elif self.request.method == "POST":# and not data:
@@ -340,7 +336,6 @@ class PublicEndpoint(Endpoint):
340
336
  return True
341
337
 
342
338
 
343
-
344
339
  class ModelEndpoint(Endpoint):
345
340
  def __init__(self):
346
341
  self.model = self.__orig_bases__[0].__args__[0]
@@ -506,14 +501,52 @@ class ChildInstanceEndpoint(ChildEndpoint):
506
501
  return Serializer(self.get_instance()).contextualize(self.request)
507
502
 
508
503
 
504
+ class RelationEditEndpoint(Generic[T], ChildEndpoint):
505
+
506
+ def __init__(self, instance):
507
+ self.source = instance
508
+
509
+ def get(self) -> FormFactory:
510
+ return self.formfactory()
511
+
512
+ def formfactory(self) -> FormFactory:
513
+ return FormFactory(self.get_instance())
514
+
515
+ def get_instance(self):
516
+ return self.__orig_bases__[0].__args__[0].objects.get(pk=self.request.GET['id'])
517
+
518
+
519
+ class RelationDeleteEndpoint(Generic[T], ChildEndpoint):
520
+
521
+ def __init__(self, instance):
522
+ self.model = self.__orig_bases__[0].__args__[0]
523
+ self.source = instance
524
+
525
+ def get(self) -> FormFactory:
526
+ return FormFactory(self.get_instance()).fields()
527
+
528
+ def post(self):
529
+ self.get_instance().safe_delete(self.request.user.username)
530
+ return super().post()
531
+
532
+ def formfactory(self) -> FormFactory:
533
+ return FormFactory(self.get_instance())
534
+
535
+ def get_instance(self):
536
+ return self.model.objects.get(pk=self.request.GET['id'])
537
+
538
+
539
+
540
+
509
541
  class Search(Endpoint):
510
542
  def get(self):
511
543
  key = "_options_"
512
544
  options = self.cache.get(key, [])
513
545
  term = self.request.GET.get("term")
514
- if options is None and APPLICATON["dashboard"]["search"]:
546
+ application = ApplicationConfig.get_instance()
547
+ if options is None and application.dashboard.search:
515
548
  options = []
516
- for name in APPLICATON["dashboard"]["search"]:
549
+ for name in application.dashboard.search:
517
550
  cls = ENDPOINTS[name]
518
551
  endpoint = cls.instantiate(self.request, self)
519
552
  if endpoint.check_permission():
@@ -531,13 +564,13 @@ class Search(Endpoint):
531
564
  return result[0:10]
532
565
 
533
566
 
534
-
535
567
  class Home(PublicEndpoint):
536
568
  class Meta:
537
569
  verbose_name = ""
538
570
 
539
571
  def get(self):
540
- cls = ENDPOINTS[APPLICATON["index"]]
572
+ application = ApplicationConfig.get_instance()
573
+ cls = ENDPOINTS[application.dashboard.index]
541
574
  self.redirect(cls.get_api_url())
542
575
 
543
576
 
@@ -546,10 +579,11 @@ class Dashboard(Endpoint):
546
579
  verbose_name = ""
547
580
 
548
581
  def get(self):
582
+ application = ApplicationConfig.get_instance()
549
583
  serializer = Serializer(request=self.request)
550
- if APPLICATON["dashboard"]["boxes"]:
584
+ if application.dashboard.boxes:
551
585
  boxes = Boxes("Acesso Rápido")
552
- for name in APPLICATON["dashboard"]["boxes"]:
586
+ for name in application.dashboard.boxes:
553
587
  cls = ENDPOINTS[name]
554
588
  endpoint = cls().contextualize(self.request)
555
589
  if endpoint.check_permission():
@@ -558,9 +592,9 @@ class Dashboard(Endpoint):
558
592
  url = build_url(self.request, cls.get_api_url())
559
593
  boxes.append(icon, label, url)
560
594
  serializer.append("Acesso Rápido", boxes)
561
- if APPLICATON["dashboard"]["top"]:
595
+ if application.dashboard.top:
562
596
  group = serializer.group("Top")
563
- for name in APPLICATON["dashboard"]["top"]:
597
+ for name in application.dashboard.top:
564
598
  cls = ENDPOINTS[name]
565
599
  endpoint = cls.instantiate(self.request, self)
566
600
  if endpoint.check_permission():
@@ -568,8 +602,8 @@ class Dashboard(Endpoint):
568
602
  endpoint.get_verbose_name(), cls, wrap=False
569
603
  )
570
604
  group.parent()
571
- if APPLICATON["dashboard"]["center"]:
572
- for name in APPLICATON["dashboard"]["center"]:
605
+ if application.dashboard.center:
606
+ for name in application.dashboard.center:
573
607
  cls = ENDPOINTS[name]
574
608
  endpoint = cls.instantiate(self.request, self)
575
609
  if endpoint.check_permission():
@@ -584,79 +618,7 @@ class Dashboard(Endpoint):
584
618
 
585
619
  class Application(PublicEndpoint):
586
620
  def get(self):
587
- user = None
588
- photo = None
589
- navbar = None
590
- menu = None
591
- icon = build_url(self.request, APPLICATON["logo"])
592
- logo = build_url(self.request, APPLICATON["logo"])
593
- if self.request.user.is_authenticated:
594
- user = self.request.user.username.split()[0].split("@")[0]
595
- profile = Profile.objects.filter(user=self.request.user).first()
596
- photo = profile and profile.photo and build_url(self.request, profile.photo.url) or None
597
-
598
- navbar = Navbar(
599
- title=APPLICATON["title"],
600
- subtitle=APPLICATON["subtitle"],
601
- logo=logo,
602
- user=user,
603
- photo=photo,
604
- search=False,
605
- roles=' | '.join((str(role) for role in self.objects('slth.role').filter(username=self.request.user.username)))
606
- )
607
- for entrypoint in ["actions", "usermenu", "adder", "settings", "tools", "toolbar"]:
608
- if APPLICATON["dashboard"][entrypoint]:
609
- for endpoint_name in APPLICATON["dashboard"][entrypoint]:
610
- cls = ENDPOINTS[endpoint_name]
611
- endpoint = cls().instantiate(self.request, self)
612
- if endpoint.check_permission() and endpoint.contribute(entrypoint):
613
- label = endpoint.get_verbose_name()
614
- url = build_url(self.request, cls.get_api_url())
615
- modal = cls.get_metadata("modal", False)
616
- icon = cls.get_metadata("icon", None)
617
- navbar.add_action(entrypoint, label, url, modal, icon=icon)
618
-
619
- if APPLICATON["menu"]:
620
- items = []
621
-
622
- def get_item(k, v):
623
- if isinstance(v, dict):
624
- icon, label = k.split(":") if ":" in k else (None, k)
625
- subitems = []
626
- for k1, v1 in v.items():
627
- subitem = get_item(k1, v1)
628
- if subitem:
629
- subitems.append(subitem)
630
- if subitems:
631
- return dict(dict(icon=icon, label=label, items=subitems))
632
- else:
633
- cls = ENDPOINTS.get(v)
634
- if cls:
635
- endpoint = cls().instantiate(self.request, self)
636
- if endpoint.check_permission() and endpoint.contribute("menu"):
637
- icon, label = k.split(":") if ":" in k else (None, k)
638
- url = build_url(self.request, cls.get_api_url())
639
- return dict(dict(label=label, url=url, icon=icon))
640
-
641
- for k, v in APPLICATON["menu"].items():
642
- item = get_item(k, v)
643
- if item:
644
- items.append(item)
645
- profile = (
646
- Profile.objects.filter(user=self.request.user).first() if user else None
647
- )
648
- photo_url = (
649
- profile.photo.url
650
- if profile and profile.photo
651
- else "/static/images/user.svg"
652
- )
653
- menu = Menu(items, user=user, image=build_url(self.request, photo_url))
654
-
655
- footer = Footer(APPLICATON["version"])
656
- return Application_(
657
- icon=icon, navbar=navbar, menu=menu, footer=footer, oauth=oauth.providers(),
658
- sponsors=APPLICATON.get("sponsors", ())
659
- )
621
+ return ApplicationConfig.get_instance().serialize(self.request)
660
622
 
661
623
 
662
624
  class Manifest(PublicEndpoint):
@@ -665,17 +627,18 @@ class Manifest(PublicEndpoint):
665
627
  verbose_name = "Manifest"
666
628
 
667
629
  def get(self):
630
+ application = ApplicationConfig.get_instance()
668
631
  return dict(
669
632
  {
670
- "name": APPLICATON["title"],
671
- "short_name": APPLICATON["title"],
633
+ "name": application.title,
634
+ "short_name": application.title,
672
635
  "lang": "pt-BR",
673
636
  "start_url": build_url(self.request, "/app/home/"),
674
637
  "scope": build_url(self.request, "/app/"),
675
638
  "display": "standalone",
676
639
  "icons": [
677
640
  {
678
- "src": build_url(self.request, APPLICATON["icon"]),
641
+ "src": build_url(self.request, application.icon),
679
642
  "sizes": "192x192",
680
643
  "type": "image/png",
681
644
  }
@@ -689,5 +652,5 @@ class Manifest(PublicEndpoint):
689
652
 
690
653
  class About(PublicEndpoint):
691
654
  def get(self):
692
- return dict(version=APPLICATON["version"])
693
-
655
+ application = ApplicationConfig.get_instance()
656
+ return dict(version=application.version)
@@ -3,7 +3,7 @@ from .serializer import Serializer
3
3
 
4
4
 
5
5
  class FormFactory:
6
- def __init__(self, instance, endpoint=None, method='POST'):
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.setvalue(**values)
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 setvalue(self, **kwargs) -> 'FormFactory':
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 form(self, endpoint):
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.setvalue(**self._values)
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():