slthcore 0.0.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.
Potentially problematic release.
This version of slthcore might be problematic. Click here for more details.
- slthcore-0.0.1/MANIFEST.in +3 -0
- slthcore-0.0.1/PKG-INFO +16 -0
- slthcore-0.0.1/requirements.txt +9 -0
- slthcore-0.0.1/setup.cfg +4 -0
- slthcore-0.0.1/setup.py +28 -0
- slthcore-0.0.1/slth/__init__.py +128 -0
- slthcore-0.0.1/slth/components.py +339 -0
- slthcore-0.0.1/slth/db/__init__.py +3 -0
- slthcore-0.0.1/slth/db/models.py +140 -0
- slthcore-0.0.1/slth/endpoints.py +808 -0
- slthcore-0.0.1/slth/exceptions.py +6 -0
- slthcore-0.0.1/slth/factory.py +129 -0
- slthcore-0.0.1/slth/forms.py +721 -0
- slthcore-0.0.1/slth/management/__init__.py +0 -0
- slthcore-0.0.1/slth/management/commands/__init__.py +0 -0
- slthcore-0.0.1/slth/management/commands/integration_test.py +27 -0
- slthcore-0.0.1/slth/management/commands/sync.py +35 -0
- slthcore-0.0.1/slth/migrations/0001_initial.py +41 -0
- slthcore-0.0.1/slth/migrations/0002_email_role_pushsubscription_error.py +78 -0
- slthcore-0.0.1/slth/migrations/0003_rename_photo_profile_alter_profile_options.py +23 -0
- slthcore-0.0.1/slth/migrations/0004_alter_profile_photo.py +18 -0
- slthcore-0.0.1/slth/migrations/0005_alter_profile_photo.py +19 -0
- slthcore-0.0.1/slth/migrations/0006_user.py +33 -0
- slthcore-0.0.1/slth/migrations/__init__.py +0 -0
- slthcore-0.0.1/slth/models.py +195 -0
- slthcore-0.0.1/slth/notifications.py +15 -0
- slthcore-0.0.1/slth/oauth.py +57 -0
- slthcore-0.0.1/slth/permissions.py +56 -0
- slthcore-0.0.1/slth/queryset.py +474 -0
- slthcore-0.0.1/slth/roles.py +103 -0
- slthcore-0.0.1/slth/selenium/__init__.py +243 -0
- slthcore-0.0.1/slth/selenium/browser.py +300 -0
- slthcore-0.0.1/slth/serializer.py +348 -0
- slthcore-0.0.1/slth/static/.DS_Store +0 -0
- slthcore-0.0.1/slth/static/css/.DS_Store +0 -0
- slthcore-0.0.1/slth/static/css/slth.css +82 -0
- slthcore-0.0.1/slth/static/js/index.min.js +1 -0
- slthcore-0.0.1/slth/static/js/react.min.js +40 -0
- slthcore-0.0.1/slth/static/js/slth.min.js +187 -0
- slthcore-0.0.1/slth/statistics.py +173 -0
- slthcore-0.0.1/slth/templates/index.html +81 -0
- slthcore-0.0.1/slth/templates/service-worker.js +39 -0
- slthcore-0.0.1/slth/tests.py +174 -0
- slthcore-0.0.1/slth/urls.py +28 -0
- slthcore-0.0.1/slth/utils.py +32 -0
- slthcore-0.0.1/slth/views.py +61 -0
- slthcore-0.0.1/slthcore.egg-info/PKG-INFO +16 -0
- slthcore-0.0.1/slthcore.egg-info/SOURCES.txt +48 -0
- slthcore-0.0.1/slthcore.egg-info/dependency_links.txt +1 -0
- slthcore-0.0.1/slthcore.egg-info/top_level.txt +1 -0
slthcore-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: slthcore
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: API generator based on yml file
|
|
5
|
+
Home-page: https://github.com/brenokcc
|
|
6
|
+
Author: Breno Silva
|
|
7
|
+
Author-email: brenokcc@yahoo.com.br
|
|
8
|
+
License: BSD License
|
|
9
|
+
Classifier: Environment :: Web Environment
|
|
10
|
+
Classifier: Framework :: Django
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
16
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
slthcore-0.0.1/setup.cfg
ADDED
slthcore-0.0.1/setup.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from setuptools import find_packages, setup
|
|
3
|
+
|
|
4
|
+
install_requires = []
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name='slthcore',
|
|
8
|
+
version='0.0.1',
|
|
9
|
+
packages=find_packages(),
|
|
10
|
+
install_requires=install_requires,
|
|
11
|
+
include_package_data=True,
|
|
12
|
+
license='BSD License',
|
|
13
|
+
description='API generator based on yml file',
|
|
14
|
+
long_description='',
|
|
15
|
+
url='https://github.com/brenokcc',
|
|
16
|
+
author='Breno Silva',
|
|
17
|
+
author_email='brenokcc@yahoo.com.br',
|
|
18
|
+
classifiers=[
|
|
19
|
+
'Environment :: Web Environment',
|
|
20
|
+
'Framework :: Django',
|
|
21
|
+
'Intended Audience :: Developers',
|
|
22
|
+
'License :: OSI Approved :: BSD License',
|
|
23
|
+
'Operating System :: OS Independent',
|
|
24
|
+
'Programming Language :: Python',
|
|
25
|
+
'Topic :: Internet :: WWW/HTTP',
|
|
26
|
+
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
|
|
27
|
+
],
|
|
28
|
+
)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
import warnings
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from django.apps import apps
|
|
7
|
+
from django.db import models
|
|
8
|
+
from .queryset import QuerySet
|
|
9
|
+
from django.db.models import manager
|
|
10
|
+
from .serializer import Serializer
|
|
11
|
+
from .factory import FormFactory
|
|
12
|
+
import django.db.models.options as options
|
|
13
|
+
from django.db.models.base import ModelBase
|
|
14
|
+
from django.core.exceptions import FieldDoesNotExist
|
|
15
|
+
from django.utils.autoreload import autoreload_started
|
|
16
|
+
|
|
17
|
+
warnings.filterwarnings('ignore', module='urllib3')
|
|
18
|
+
|
|
19
|
+
FILENAME = 'application.yml'
|
|
20
|
+
ENDPOINTS = {}
|
|
21
|
+
PROXIED_MODELS = []
|
|
22
|
+
APPLICATON = None
|
|
23
|
+
|
|
24
|
+
if APPLICATON is None and os.path.exists(FILENAME):
|
|
25
|
+
with open(FILENAME) as file:
|
|
26
|
+
content = file.read()
|
|
27
|
+
for variable in re.findall(r'\$[a-zA-z0-9_]+', content):
|
|
28
|
+
content = content.replace(variable, os.environ.get(variable[1:], ''))
|
|
29
|
+
APPLICATON = yaml.safe_load(content).get('application')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BaseManager(manager.BaseManager):
|
|
33
|
+
def get_queryset(self):
|
|
34
|
+
return super().get_queryset()
|
|
35
|
+
|
|
36
|
+
def all(self):
|
|
37
|
+
return self.get_queryset().all()
|
|
38
|
+
|
|
39
|
+
def __call__(self, model):
|
|
40
|
+
return apps.get_model(model)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Manager(BaseManager.from_queryset(QuerySet)):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
models.QuerySet = QuerySet
|
|
48
|
+
models.Manager = Manager
|
|
49
|
+
setattr(options, 'DEFAULT_NAMES', options.DEFAULT_NAMES + ('icon', 'search_fields'))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ModelMixin(object):
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def get_field(cls, lookup):
|
|
57
|
+
model = cls
|
|
58
|
+
attrs = lookup.split('__')
|
|
59
|
+
while attrs:
|
|
60
|
+
attr_name = attrs.pop(0)
|
|
61
|
+
if attrs: # go deeper
|
|
62
|
+
field = model._meta.get_field(attr_name)
|
|
63
|
+
model = field.related_model
|
|
64
|
+
else:
|
|
65
|
+
try:
|
|
66
|
+
return model._meta.get_field(attr_name)
|
|
67
|
+
except FieldDoesNotExist:
|
|
68
|
+
pass
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
def getroles(self, username_lookup='username'):
|
|
72
|
+
roles = getattr(self, '_roles', None)
|
|
73
|
+
if roles is None:
|
|
74
|
+
obj = self
|
|
75
|
+
for attr_name in username_lookup.split('__'):
|
|
76
|
+
obj = getattr(obj, attr_name)
|
|
77
|
+
roles = apps.get_model('api.role').objects.filter(username=obj)
|
|
78
|
+
setattr(self, '_roles', roles)
|
|
79
|
+
return roles
|
|
80
|
+
|
|
81
|
+
def getuser(self, username_lookup):
|
|
82
|
+
obj = self
|
|
83
|
+
for attr_name in username_lookup.split('__'):
|
|
84
|
+
obj = getattr(obj, attr_name)
|
|
85
|
+
return apps.get_model('auth.user').objects.get(username=obj)
|
|
86
|
+
|
|
87
|
+
def serializer(self) -> Serializer:
|
|
88
|
+
return Serializer(self)
|
|
89
|
+
|
|
90
|
+
def formfactory(self) -> FormFactory:
|
|
91
|
+
return FormFactory(self)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
___new___ = ModelBase.__new__
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def __new__(mcs, name, bases, attrs, **kwargs):
|
|
98
|
+
if attrs['__module__'] != '__fake__':
|
|
99
|
+
# See .db.models.Manager
|
|
100
|
+
if 'objects' in attrs and isinstance(attrs['objects'], QuerySet):
|
|
101
|
+
queryset_class = attrs['objects']
|
|
102
|
+
attrs.update(objects=BaseManager.from_queryset(type(queryset_class))())
|
|
103
|
+
# Defining the objects Manager using .db.models.QuerySet
|
|
104
|
+
if 'objects' not in attrs and not all(['objects' in dir(cls) for cls in bases]):
|
|
105
|
+
attrs.update(objects=BaseManager.from_queryset(QuerySet)())
|
|
106
|
+
|
|
107
|
+
if ModelMixin not in bases:
|
|
108
|
+
bases = bases + (ModelMixin, )
|
|
109
|
+
cls = ___new___(mcs, name, bases, attrs, **kwargs)
|
|
110
|
+
if cls._meta.proxy_for_model:
|
|
111
|
+
PROXIED_MODELS.append(cls._meta.proxy_for_model)
|
|
112
|
+
return cls
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
ModelBase.__new__ = __new__
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def api_watchdog(sender, **kwargs):
|
|
119
|
+
sender.extra_files.add(Path('application.yml'))
|
|
120
|
+
|
|
121
|
+
autoreload_started.connect(api_watchdog)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def meta(verbose_name=None):
|
|
125
|
+
def decorate(function):
|
|
126
|
+
function.verbose_name = verbose_name
|
|
127
|
+
return function
|
|
128
|
+
return decorate
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
from datetime import date, timedelta, datetime
|
|
2
|
+
from django.template.loader import render_to_string
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
SUCCESS = "success"
|
|
6
|
+
PRIMARY = "primary"
|
|
7
|
+
WARNING = "warning"
|
|
8
|
+
DANGER = "danger"
|
|
9
|
+
|
|
10
|
+
class Text(dict):
|
|
11
|
+
def __init__(self, text, color="inherite", size="inherite", bold=False, italic=False):
|
|
12
|
+
self["type"] = "text"
|
|
13
|
+
self["text"] = text
|
|
14
|
+
self["color"] = color
|
|
15
|
+
self["bold"] = bold
|
|
16
|
+
self["italic"] = italic
|
|
17
|
+
|
|
18
|
+
class Image(dict):
|
|
19
|
+
def __init__(self, src, width=None, height=None, round=False, placeholder=None):
|
|
20
|
+
if width is None and height is None:
|
|
21
|
+
width = 100
|
|
22
|
+
height = 100
|
|
23
|
+
if width and not height:
|
|
24
|
+
height = width
|
|
25
|
+
if height and not width:
|
|
26
|
+
width = height
|
|
27
|
+
self["type"] = "image"
|
|
28
|
+
self["src"] = src
|
|
29
|
+
self["width"] = width
|
|
30
|
+
self["height"] = height
|
|
31
|
+
self["round"] = round
|
|
32
|
+
self["placeholder"] = placeholder
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class FileLink(dict):
|
|
36
|
+
def __init__(self, url, modal=False, icon=None):
|
|
37
|
+
self["type"] = "filelink"
|
|
38
|
+
self["url"] = url
|
|
39
|
+
self["modal"] = modal
|
|
40
|
+
self["icon"] = icon
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class FileViewer(dict):
|
|
44
|
+
def __init__(self, url):
|
|
45
|
+
self["type"] = "filepreview"
|
|
46
|
+
self["url"] = url
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class QrCode(dict):
|
|
50
|
+
def __init__(self, text):
|
|
51
|
+
self["type"] = "qrcode"
|
|
52
|
+
self["text"] = text
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Progress(dict):
|
|
56
|
+
def __init__(self, value, style="primary"):
|
|
57
|
+
self["type"] = "progress"
|
|
58
|
+
self["value"] = int(value or 0)
|
|
59
|
+
self["style"] = style
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Status(dict):
|
|
63
|
+
def __init__(self, style, label):
|
|
64
|
+
self["type"] = "status"
|
|
65
|
+
self["style"] = style
|
|
66
|
+
self["label"] = str(label)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class Badge(dict):
|
|
70
|
+
def __init__(self, color, label, icon=None):
|
|
71
|
+
self["type"] = "badge"
|
|
72
|
+
self["color"] = color
|
|
73
|
+
self["label"] = str(label)
|
|
74
|
+
self["icon"] = icon
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Shell(dict):
|
|
78
|
+
def __init__(self, output):
|
|
79
|
+
self["type"] = "shell"
|
|
80
|
+
self["output"] = output
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Indicators(dict):
|
|
84
|
+
def __init__(self, title):
|
|
85
|
+
self["type"] = "indicators"
|
|
86
|
+
self["title"] = title
|
|
87
|
+
self["items"] = []
|
|
88
|
+
self["actions"] = []
|
|
89
|
+
|
|
90
|
+
def append(self, name, value):
|
|
91
|
+
self["items"].append(dict(name=str(name), value=value))
|
|
92
|
+
|
|
93
|
+
def action(self, label, url, modal=False):
|
|
94
|
+
self["actions"].append(dict(label=str(label), url=url, modal=modal))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class Boxes(dict):
|
|
98
|
+
def __init__(self, title):
|
|
99
|
+
self["type"] = "boxes"
|
|
100
|
+
self["title"] = str(title)
|
|
101
|
+
self["items"] = []
|
|
102
|
+
|
|
103
|
+
def append(self, icon, label, url, style=None):
|
|
104
|
+
self["items"].append(dict(icon=icon, label=str(label), url=url, style=style))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Info(dict):
|
|
108
|
+
def __init__(self, title, message):
|
|
109
|
+
self["type"] = "info"
|
|
110
|
+
self["title"] = title
|
|
111
|
+
self["message"] = message
|
|
112
|
+
self["actions"] = []
|
|
113
|
+
|
|
114
|
+
def action(self, label, url, modal=False, icon=None):
|
|
115
|
+
self["actions"].append(dict(label=str(label), url=url, modal=modal, icon=icon))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Warning(dict):
|
|
119
|
+
def __init__(self, title, message):
|
|
120
|
+
self["type"] = "warning"
|
|
121
|
+
self["title"] = title
|
|
122
|
+
self["message"] = message
|
|
123
|
+
self["actions"] = []
|
|
124
|
+
|
|
125
|
+
def action(self, label, url, modal=False, icon=None):
|
|
126
|
+
self["actions"].append(dict(label=str(label), url=url, modal=modal, icon=icon))
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class Table(dict):
|
|
130
|
+
def __init__(self, title, subset=None, pagination=None):
|
|
131
|
+
self["type"] = "table"
|
|
132
|
+
self["title"] = title
|
|
133
|
+
self["actions"] = []
|
|
134
|
+
self["subsets"] = []
|
|
135
|
+
self["subset"] = subset
|
|
136
|
+
self["filters"] = []
|
|
137
|
+
self["flags"] = []
|
|
138
|
+
self["rows"] = []
|
|
139
|
+
self["pagination"] = {}
|
|
140
|
+
|
|
141
|
+
def add_subset(self, name, label, count):
|
|
142
|
+
self["subsets"].append(dict(name=name, label=label, count=count))
|
|
143
|
+
|
|
144
|
+
def add_action(self, name, label, icon=None, batch=True):
|
|
145
|
+
self["actions"].append(dict(name=name, label=label, icon=icon, batch=batch))
|
|
146
|
+
|
|
147
|
+
def add_flag(self, name, label, checked=False):
|
|
148
|
+
self["flags"].append(dict(name=name, label=label, checked=checked))
|
|
149
|
+
|
|
150
|
+
def add_filter(self, ftype, name, label, value, choices=None):
|
|
151
|
+
self["filters"].append(
|
|
152
|
+
dict(type=ftype, name=name, label=label, value=value, choices=choices)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def pagination(self, size, page, total, sizes):
|
|
156
|
+
self["pagination"].update(size=size, page=page, total=total, sizes=sizes)
|
|
157
|
+
|
|
158
|
+
def add_row(self, row):
|
|
159
|
+
self["rows"].append(row)
|
|
160
|
+
|
|
161
|
+
def row(self, value=None, checkable=False, deleted=False):
|
|
162
|
+
self["rows"].append(
|
|
163
|
+
[dict(name="#", value=value, checkable=checkable, deleted=deleted)]
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def cell(self, name, value, style=None, url=None, actions=None):
|
|
167
|
+
self["rows"][-1].append(
|
|
168
|
+
dict(name=name, value=value, style=style, url=url, actions=actions)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class TemplateContent(dict):
|
|
173
|
+
def __init__(self, name, context):
|
|
174
|
+
self["type"] = "html"
|
|
175
|
+
self["content"] = render_to_string(name, context)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class Banner(dict):
|
|
179
|
+
def __init__(self, src):
|
|
180
|
+
self["type"] = "banner"
|
|
181
|
+
self["src"] = src
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class Map(dict):
|
|
185
|
+
def __init__(self, latitude, longitude, width="100%", height=400):
|
|
186
|
+
self["type"] = "map"
|
|
187
|
+
self["latitude"] = str(latitude)
|
|
188
|
+
self["longitude"] = str(longitude)
|
|
189
|
+
self["width"] = width
|
|
190
|
+
self["height"] = height
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class Steps(dict):
|
|
194
|
+
def __init__(self, icon=None):
|
|
195
|
+
self["type"] = "steps"
|
|
196
|
+
self["icon"] = icon
|
|
197
|
+
self["steps"] = []
|
|
198
|
+
|
|
199
|
+
def append(self, name, done):
|
|
200
|
+
number = len(self["steps"]) + 1
|
|
201
|
+
self["steps"].append(dict(number=number, name=name, done=bool(done)))
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class WebConf(dict):
|
|
205
|
+
def __init__(self, caller, receiver):
|
|
206
|
+
self["type"] = "webconf"
|
|
207
|
+
self["caller"] = caller
|
|
208
|
+
self["receiver"] = receiver
|
|
209
|
+
|
|
210
|
+
class ZoomMeet(dict):
|
|
211
|
+
def __init__(self, number, password, name):
|
|
212
|
+
self["type"] = "zoommeet"
|
|
213
|
+
self["number"] = number
|
|
214
|
+
self["password"] = password
|
|
215
|
+
self["name"] = name
|
|
216
|
+
|
|
217
|
+
class Navbar(dict):
|
|
218
|
+
def __init__(self, title, subtitle=None, logo=None, user=None, search=False, roles=None):
|
|
219
|
+
self["type"] = "navbar"
|
|
220
|
+
self["title"] = title
|
|
221
|
+
self["subtitle"] = subtitle
|
|
222
|
+
self["logo"] = logo
|
|
223
|
+
self["user"] = user
|
|
224
|
+
self["usermenu"] = []
|
|
225
|
+
self["adder"] = []
|
|
226
|
+
self["tools"] = []
|
|
227
|
+
self["settings"] = []
|
|
228
|
+
self["actions"] = []
|
|
229
|
+
self["toolbar"] = []
|
|
230
|
+
self["search"] = search
|
|
231
|
+
self["roles"] = roles
|
|
232
|
+
|
|
233
|
+
def add_action(self, entrypoint, name, url, modal=True, icon=None):
|
|
234
|
+
self[entrypoint].append(dict(name=name, url=url, modal=modal, icon=icon))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class Menu(dict):
|
|
238
|
+
def __init__(self, items, user=None, image=None):
|
|
239
|
+
self["type"] = "menu"
|
|
240
|
+
self["items"] = items
|
|
241
|
+
self["user"] = user
|
|
242
|
+
self["image"] = image
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class Footer(dict):
|
|
246
|
+
def __init__(self, version):
|
|
247
|
+
self["type"] = "navbar"
|
|
248
|
+
self["version"] = version
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class Application(dict):
|
|
252
|
+
def __init__(self, icon=None, navbar=None, menu=None, footer=None, oauth=(), sponsors=()):
|
|
253
|
+
self["type"] = "application"
|
|
254
|
+
self["icon"] = icon
|
|
255
|
+
self["navbar"] = navbar
|
|
256
|
+
self["menu"] = menu
|
|
257
|
+
self["footer"] = footer
|
|
258
|
+
self["oauth"] = oauth
|
|
259
|
+
self["sponsors"] = sponsors
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class Response(dict):
|
|
263
|
+
|
|
264
|
+
def __init__(self, message=None, redirect=None, store=None, **kwargs):
|
|
265
|
+
self["type"] = "response"
|
|
266
|
+
self["message"] = message
|
|
267
|
+
self["redirect"] = redirect or '..'
|
|
268
|
+
self["store"] = store or {}
|
|
269
|
+
self.update(**kwargs)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class IconSet(dict):
|
|
273
|
+
def __init__(self):
|
|
274
|
+
self["type"] = "iconset"
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class Grid(dict):
|
|
278
|
+
def __init__(self):
|
|
279
|
+
self["type"] = "grid"
|
|
280
|
+
self["items"] = []
|
|
281
|
+
|
|
282
|
+
def append(self, component):
|
|
283
|
+
self["items"].append(component)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class Scheduler(dict):
|
|
287
|
+
INTERVALS = {1: ["00"], 2: ["00", "30"]}
|
|
288
|
+
|
|
289
|
+
def __init__(
|
|
290
|
+
self,
|
|
291
|
+
start_time=7,
|
|
292
|
+
end_time=20,
|
|
293
|
+
chucks=2,
|
|
294
|
+
start_day=None,
|
|
295
|
+
days=14,
|
|
296
|
+
single_selection=False,
|
|
297
|
+
input_name="schedule",
|
|
298
|
+
readonly=False,
|
|
299
|
+
):
|
|
300
|
+
self["type"] = "scheduler"
|
|
301
|
+
self["single_selection"] = single_selection
|
|
302
|
+
self["input_name"] = input_name
|
|
303
|
+
self["readonly"] = readonly
|
|
304
|
+
self.end_day = start_day or datetime.now()
|
|
305
|
+
self.end_day = datetime(self.end_day.year, self.end_day.month, self.end_day.day)
|
|
306
|
+
self.times = []
|
|
307
|
+
for hour in range(start_time, end_time + 1):
|
|
308
|
+
for minute in Scheduler.INTERVALS[chucks]:
|
|
309
|
+
self.times.append("{}:{}".format(str(hour).rjust(2, "0"), minute))
|
|
310
|
+
self.days = []
|
|
311
|
+
for n in range(0, days):
|
|
312
|
+
self.days.append(self.end_day.strftime("%d/%m/%Y"))
|
|
313
|
+
self.end_day = self.end_day + timedelta(days=1)
|
|
314
|
+
self.end_day = datetime(self.end_day.year, self.end_day.month, self.end_day.day, 23, 59, 59)
|
|
315
|
+
self["slots"] = {}
|
|
316
|
+
for day in self.days:
|
|
317
|
+
self["slots"][day] = {k: None for k in self.times}
|
|
318
|
+
|
|
319
|
+
self["matrix"] = []
|
|
320
|
+
row = [dict(text='', icon=None, color=None)]
|
|
321
|
+
for day in self.days:
|
|
322
|
+
row.append(dict(text=day, icon=None, color=None))
|
|
323
|
+
self["matrix"].append(row)
|
|
324
|
+
for time in self.times:
|
|
325
|
+
row = [dict(text=time, icon=None, color=None)]
|
|
326
|
+
for day in self.days:
|
|
327
|
+
row.append(self["slots"][day][time])
|
|
328
|
+
self["matrix"].append(row)
|
|
329
|
+
|
|
330
|
+
def append(self, date_time, text, icon='check'):
|
|
331
|
+
day = date_time.strftime("%d/%m/%Y")
|
|
332
|
+
time = date_time.strftime("%H:%M")
|
|
333
|
+
value = dict(text=text, icon=icon)
|
|
334
|
+
self["slots"][day][time] = value
|
|
335
|
+
j = self.days.index(day) + 1 if day in self.days else -1
|
|
336
|
+
x = self.times.index(time) + 1 if time in self.times else -1
|
|
337
|
+
self["matrix"][x][j] = value
|
|
338
|
+
|
|
339
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from uuid import uuid1
|
|
2
|
+
from django.db.models import Model as DjangoModel
|
|
3
|
+
from django.db.models import *
|
|
4
|
+
from django.utils.translation import gettext_lazy as _
|
|
5
|
+
from .. import ModelMixin
|
|
6
|
+
|
|
7
|
+
class CharField(CharField):
|
|
8
|
+
def __init__(self, *args, **kwargs):
|
|
9
|
+
self.mask = kwargs.pop('mask', None)
|
|
10
|
+
kwargs.setdefault('max_length', 255)
|
|
11
|
+
super().__init__(*args, **kwargs)
|
|
12
|
+
|
|
13
|
+
def formfield(self, *args, **kwargs):
|
|
14
|
+
field = super().formfield(*args, **kwargs)
|
|
15
|
+
field.mask = self.mask
|
|
16
|
+
return field
|
|
17
|
+
|
|
18
|
+
class IntegerField(IntegerField):
|
|
19
|
+
def __init__(self, *args, **kwargs):
|
|
20
|
+
self.mask = kwargs.pop('mask', None)
|
|
21
|
+
super().__init__(*args, **kwargs)
|
|
22
|
+
|
|
23
|
+
def formfield(self, *args, **kwargs):
|
|
24
|
+
field = super().formfield(*args, **kwargs)
|
|
25
|
+
field.mask = self.mask
|
|
26
|
+
return field
|
|
27
|
+
|
|
28
|
+
class ForeignKey(ForeignKey):
|
|
29
|
+
def __init__(self, to, on_delete=None, **kwargs):
|
|
30
|
+
self.pick = kwargs.pop('pick', False)
|
|
31
|
+
self.addable = kwargs.pop('addable', False)
|
|
32
|
+
super().__init__(to, on_delete or CASCADE, **kwargs)
|
|
33
|
+
|
|
34
|
+
def formfield(self, *args, **kwargs):
|
|
35
|
+
from .. import forms
|
|
36
|
+
kwargs.update(form_class=forms.ModelChoiceField, pick=self.pick)
|
|
37
|
+
field = super().formfield(*args, **kwargs)
|
|
38
|
+
return field
|
|
39
|
+
|
|
40
|
+
class OneToManyField(ManyToManyField):
|
|
41
|
+
def __init__(self, *args, **kwargs):
|
|
42
|
+
self.fields = kwargs.pop('fields', '__all__')
|
|
43
|
+
super().__init__(*args, **kwargs)
|
|
44
|
+
|
|
45
|
+
def formfield(self, *args, **kwargs):
|
|
46
|
+
from .. import forms
|
|
47
|
+
kwargs.update(form_class=forms.OneToManyField, fields=self.fields)
|
|
48
|
+
field = super().formfield(*args, model=self.related_model, **kwargs)
|
|
49
|
+
field.label = self.verbose_name
|
|
50
|
+
return field
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class OneToOneField(OneToOneField):
|
|
54
|
+
def __init__(self, *args, **kwargs):
|
|
55
|
+
self.fields = kwargs.pop('fields', '__all__')
|
|
56
|
+
super().__init__(*args, **kwargs)
|
|
57
|
+
|
|
58
|
+
def formfield(self, *args, **kwargs):
|
|
59
|
+
from .. import forms
|
|
60
|
+
kwargs.update(form_class=forms.OneToOneField, fields=self.fields)
|
|
61
|
+
field = super().formfield(*args, model=self.related_model, **kwargs)
|
|
62
|
+
field.label = self.verbose_name
|
|
63
|
+
field.required2 = not self.blank
|
|
64
|
+
return field
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ManyToManyField(ManyToManyField):
|
|
68
|
+
def __init__(self, *args, **kwargs):
|
|
69
|
+
self.pick = kwargs.pop('pick', False)
|
|
70
|
+
self.addable = kwargs.pop('addable', False)
|
|
71
|
+
super().__init__(*args, **kwargs)
|
|
72
|
+
|
|
73
|
+
def formfield(self, *args, **kwargs):
|
|
74
|
+
from .. import forms
|
|
75
|
+
kwargs.update(form_class=forms.ModelMultipleChoiceField, pick=self.pick)
|
|
76
|
+
field = super().formfield(*args, **kwargs)
|
|
77
|
+
return field
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class DecimalField(DecimalField):
|
|
81
|
+
def __init__(self, *args, **kwargs):
|
|
82
|
+
kwargs['decimal_places'] = kwargs.pop('decimal_places', 2)
|
|
83
|
+
kwargs['max_digits'] = kwargs.pop('max_digits', 9)
|
|
84
|
+
super().__init__(*args, **kwargs)
|
|
85
|
+
|
|
86
|
+
def formfield(self, *args, **kwargs):
|
|
87
|
+
from .. import forms
|
|
88
|
+
kwargs.update(form_class=forms.DecimalField)
|
|
89
|
+
return super().formfield(*args, **kwargs)
|
|
90
|
+
|
|
91
|
+
class ColorField(CharField):
|
|
92
|
+
|
|
93
|
+
def formfield(self, *args, **kwargs):
|
|
94
|
+
from .. import forms
|
|
95
|
+
kwargs.update(form_class=forms.ColorField)
|
|
96
|
+
return super().formfield(*args, **kwargs)
|
|
97
|
+
|
|
98
|
+
class TextField(TextField):
|
|
99
|
+
def __init__(self, *args, **kwargs):
|
|
100
|
+
self.formatted= kwargs.pop('formatted', False)
|
|
101
|
+
super().__init__(*args, **kwargs)
|
|
102
|
+
|
|
103
|
+
class FileField(FileField):
|
|
104
|
+
def __init__(self, *args, extensions=('pdf',), max_size=5, **kwargs):
|
|
105
|
+
self.extensions= extensions
|
|
106
|
+
self.max_size = max_size
|
|
107
|
+
super().__init__(*args, **kwargs)
|
|
108
|
+
|
|
109
|
+
def formfield(self, *args, **kwargs):
|
|
110
|
+
from .. import forms
|
|
111
|
+
kwargs.update(extensions=self.extensions, max_size=self.max_size)
|
|
112
|
+
kwargs.update(form_class=forms.FileField)
|
|
113
|
+
return super().formfield(*args, **kwargs)
|
|
114
|
+
|
|
115
|
+
def generate_filename(self, instance, filename):
|
|
116
|
+
filename = '{}.{}'.format(uuid1().hex, filename.split('.')[-1].lower())
|
|
117
|
+
print(filename)
|
|
118
|
+
return super().generate_filename(instance, filename)
|
|
119
|
+
|
|
120
|
+
class ImageField(ImageField):
|
|
121
|
+
def __init__(self, *args, extensions=('png', 'jpg', 'jpeg'), width=None, height=None, **kwargs):
|
|
122
|
+
self.extensions= extensions
|
|
123
|
+
self.width = width
|
|
124
|
+
self.height = height
|
|
125
|
+
super().__init__(*args, **kwargs)
|
|
126
|
+
|
|
127
|
+
def formfield(self, *args, **kwargs):
|
|
128
|
+
from .. import forms
|
|
129
|
+
kwargs.update(extensions=self.extensions, width=self.width, height=self.height)
|
|
130
|
+
kwargs.update(form_class=forms.ImageField)
|
|
131
|
+
return super().formfield(*args, **kwargs)
|
|
132
|
+
|
|
133
|
+
def generate_filename(self, instance, filename):
|
|
134
|
+
filename = '{}.{}'.format(uuid1().hex, filename.split('.')[-1].lower())
|
|
135
|
+
print(filename)
|
|
136
|
+
return super().generate_filename(instance, filename)
|
|
137
|
+
|
|
138
|
+
class Model(DjangoModel, ModelMixin):
|
|
139
|
+
class Meta:
|
|
140
|
+
abstract = True
|