mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-06-09 14:09:57 +00:00
wip
This commit is contained in:
parent
15d1fe4a46
commit
0b55657200
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
"""Django's command-line utility for administrative tasks."""
|
"""Django's command-line utility for administrative tasks."""
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
149
poetry.lock
generated
149
poetry.lock
generated
@ -136,6 +136,14 @@ twisted = {version = ">=18.7", extras = ["tls"]}
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["hypothesis (==4.23)", "pytest (>=3.10,<4.0)", "pytest-asyncio (>=0.8,<1.0)"]
|
tests = ["hypothesis (==4.23)", "pytest (>=3.10,<4.0)", "pytest-asyncio (>=0.8,<1.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defusedxml"
|
||||||
|
version = "0.7.1"
|
||||||
|
description = "XML bomb protection for Python stdlib modules"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "3.2.3"
|
version = "3.2.3"
|
||||||
@ -256,6 +264,19 @@ category = "dev"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oauthlib"
|
||||||
|
version = "3.1.1"
|
||||||
|
description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
rsa = ["cryptography (>=3.0.0,<4)"]
|
||||||
|
signals = ["blinker (>=1.4.0)"]
|
||||||
|
signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyasn1"
|
name = "pyasn1"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@ -299,6 +320,20 @@ category = "dev"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyjwt"
|
||||||
|
version = "2.1.0"
|
||||||
|
description = "JSON Web Token implementation in Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
crypto = ["cryptography (>=3.3.1,<4.0.0)"]
|
||||||
|
dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1,<4.0.0)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"]
|
||||||
|
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
|
||||||
|
tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyopenssl"
|
name = "pyopenssl"
|
||||||
version = "20.0.1"
|
version = "20.0.1"
|
||||||
@ -315,6 +350,21 @@ six = ">=1.5.2"
|
|||||||
docs = ["sphinx", "sphinx-rtd-theme"]
|
docs = ["sphinx", "sphinx-rtd-theme"]
|
||||||
test = ["flaky", "pretend", "pytest (>=3.0.1)"]
|
test = ["flaky", "pretend", "pytest (>=3.0.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python3-openid"
|
||||||
|
version = "3.2.0"
|
||||||
|
description = "OpenID support for modern servers and consumers."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
defusedxml = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
mysql = ["mysql-connector-python"]
|
||||||
|
postgresql = ["psycopg2"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytz"
|
name = "pytz"
|
||||||
version = "2021.1"
|
version = "2021.1"
|
||||||
@ -323,6 +373,33 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.15.1"
|
||||||
|
description = "Python HTTP for Humans."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"]
|
||||||
|
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests-oauthlib"
|
||||||
|
version = "1.3.0"
|
||||||
|
description = "OAuthlib authentication support for Requests."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
oauthlib = ">=3.0.0"
|
||||||
|
requests = ">=2.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "service-identity"
|
name = "service-identity"
|
||||||
version = "21.1.0"
|
version = "21.1.0"
|
||||||
@ -352,6 +429,42 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "social-auth-app-django"
|
||||||
|
version = "4.0.0"
|
||||||
|
description = "Python Social Authentication, Django integration."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
six = "*"
|
||||||
|
social-auth-core = ">=3.3.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "social-auth-core"
|
||||||
|
version = "4.1.0"
|
||||||
|
description = "Python social authentication made simple."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
cryptography = ">=1.4"
|
||||||
|
defusedxml = ">=0.5.0rc1"
|
||||||
|
oauthlib = ">=1.0.3"
|
||||||
|
PyJWT = ">=2.0.0"
|
||||||
|
python3-openid = ">=3.0.10"
|
||||||
|
requests = ">=2.9.1"
|
||||||
|
requests-oauthlib = ">=0.6.1"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["python-jose (>=3.0.0)", "python3-saml (>=1.2.1)", "cryptography (>=2.1.1)"]
|
||||||
|
allpy3 = ["python-jose (>=3.0.0)", "python3-saml (>=1.2.1)", "cryptography (>=2.1.1)"]
|
||||||
|
azuread = ["cryptography (>=2.1.1)"]
|
||||||
|
openidconnect = ["python-jose (>=3.0.0)"]
|
||||||
|
saml = ["python3-saml (>=1.2.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "sqlparse"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -464,7 +577,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.7"
|
python-versions = "^3.7"
|
||||||
content-hash = "3922460ced69b5e33ce174cf478542b18bf7bc793d32e262fe46a4b7d9a2a047"
|
content-hash = "ddf1bd292c78d2b6919ec1a9eb9b76b48ff4d97e7a20a3a46783dcdbf5ec1163"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
asgiref = [
|
asgiref = [
|
||||||
@ -560,6 +673,10 @@ daphne = [
|
|||||||
{file = "daphne-3.0.2-py3-none-any.whl", hash = "sha256:a9af943c79717bc52fe64a3c236ae5d3adccc8b5be19c881b442d2c3db233393"},
|
{file = "daphne-3.0.2-py3-none-any.whl", hash = "sha256:a9af943c79717bc52fe64a3c236ae5d3adccc8b5be19c881b442d2c3db233393"},
|
||||||
{file = "daphne-3.0.2.tar.gz", hash = "sha256:76ffae916ba3aa66b46996c14fa713e46004788167a4873d647544e750e0e99f"},
|
{file = "daphne-3.0.2.tar.gz", hash = "sha256:76ffae916ba3aa66b46996c14fa713e46004788167a4873d647544e750e0e99f"},
|
||||||
]
|
]
|
||||||
|
defusedxml = [
|
||||||
|
{file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"},
|
||||||
|
{file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"},
|
||||||
|
]
|
||||||
django = [
|
django = [
|
||||||
{file = "Django-3.2.3-py3-none-any.whl", hash = "sha256:7e0a1393d18c16b503663752a8b6790880c5084412618990ce8a81cc908b4962"},
|
{file = "Django-3.2.3-py3-none-any.whl", hash = "sha256:7e0a1393d18c16b503663752a8b6790880c5084412618990ce8a81cc908b4962"},
|
||||||
{file = "Django-3.2.3.tar.gz", hash = "sha256:13ac78dbfd189532cad8f383a27e58e18b3d33f80009ceb476d7fcbfc5dcebd8"},
|
{file = "Django-3.2.3.tar.gz", hash = "sha256:13ac78dbfd189532cad8f383a27e58e18b3d33f80009ceb476d7fcbfc5dcebd8"},
|
||||||
@ -599,6 +716,10 @@ mccabe = [
|
|||||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
||||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
||||||
]
|
]
|
||||||
|
oauthlib = [
|
||||||
|
{file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"},
|
||||||
|
{file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"},
|
||||||
|
]
|
||||||
pyasn1 = [
|
pyasn1 = [
|
||||||
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
|
{file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
|
||||||
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
|
{file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
|
||||||
@ -641,14 +762,31 @@ pyflakes = [
|
|||||||
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
|
{file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
|
||||||
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
|
{file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
|
||||||
]
|
]
|
||||||
|
pyjwt = [
|
||||||
|
{file = "PyJWT-2.1.0-py3-none-any.whl", hash = "sha256:934d73fbba91b0483d3857d1aff50e96b2a892384ee2c17417ed3203f173fca1"},
|
||||||
|
{file = "PyJWT-2.1.0.tar.gz", hash = "sha256:fba44e7898bbca160a2b2b501f492824fc8382485d3a6f11ba5d0c1937ce6130"},
|
||||||
|
]
|
||||||
pyopenssl = [
|
pyopenssl = [
|
||||||
{file = "pyOpenSSL-20.0.1-py2.py3-none-any.whl", hash = "sha256:818ae18e06922c066f777a33f1fca45786d85edfe71cd043de6379337a7f274b"},
|
{file = "pyOpenSSL-20.0.1-py2.py3-none-any.whl", hash = "sha256:818ae18e06922c066f777a33f1fca45786d85edfe71cd043de6379337a7f274b"},
|
||||||
{file = "pyOpenSSL-20.0.1.tar.gz", hash = "sha256:4c231c759543ba02560fcd2480c48dcec4dae34c9da7d3747c508227e0624b51"},
|
{file = "pyOpenSSL-20.0.1.tar.gz", hash = "sha256:4c231c759543ba02560fcd2480c48dcec4dae34c9da7d3747c508227e0624b51"},
|
||||||
]
|
]
|
||||||
|
python3-openid = [
|
||||||
|
{file = "python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf"},
|
||||||
|
{file = "python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b"},
|
||||||
|
]
|
||||||
pytz = [
|
pytz = [
|
||||||
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
||||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||||
]
|
]
|
||||||
|
requests = [
|
||||||
|
{file = "requests-2.15.1-py2.py3-none-any.whl", hash = "sha256:ff753b2196cd18b1bbeddc9dcd5c864056599f7a7d9a4fb5677e723efa2b7fb9"},
|
||||||
|
{file = "requests-2.15.1.tar.gz", hash = "sha256:e5659b9315a0610505e050bb7190bf6fa2ccee1ac295f2b760ef9d8a03ebbb2e"},
|
||||||
|
]
|
||||||
|
requests-oauthlib = [
|
||||||
|
{file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"},
|
||||||
|
{file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"},
|
||||||
|
{file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"},
|
||||||
|
]
|
||||||
service-identity = [
|
service-identity = [
|
||||||
{file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"},
|
{file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"},
|
||||||
{file = "service_identity-21.1.0-py2.py3-none-any.whl", hash = "sha256:f0b0caac3d40627c3c04d7a51b6e06721857a0e10a8775f2d1d7e72901b3a7db"},
|
{file = "service_identity-21.1.0-py2.py3-none-any.whl", hash = "sha256:f0b0caac3d40627c3c04d7a51b6e06721857a0e10a8775f2d1d7e72901b3a7db"},
|
||||||
@ -657,6 +795,15 @@ six = [
|
|||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
]
|
]
|
||||||
|
social-auth-app-django = [
|
||||||
|
{file = "social-auth-app-django-4.0.0.tar.gz", hash = "sha256:2c69e57df0b30c9c1823519c5f1992cbe4f3f98fdc7d95c840e091a752708840"},
|
||||||
|
{file = "social_auth_app_django-4.0.0-py2-none-any.whl", hash = "sha256:df5212370bd250108987c4748419a1a1d0cec750878856c2644c36aaa0fd3e58"},
|
||||||
|
{file = "social_auth_app_django-4.0.0-py3-none-any.whl", hash = "sha256:567ad0e028311541d7dfed51d3bf2c60440a6fd236d5d4d06c5a618b3d6c57c5"},
|
||||||
|
]
|
||||||
|
social-auth-core = [
|
||||||
|
{file = "social-auth-core-4.1.0.tar.gz", hash = "sha256:5ab43b3b15dce5f059db69cc3082c216574739f0edbc98629c8c6e8769c67eb4"},
|
||||||
|
{file = "social_auth_core-4.1.0-py3-none-any.whl", hash = "sha256:983b53167ac56e7ba4909db555602a6e7a98c97ca47183bb222eb85ba627bf2b"},
|
||||||
|
]
|
||||||
sqlparse = [
|
sqlparse = [
|
||||||
{file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
|
{file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
|
||||||
{file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
|
{file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
|
||||||
|
@ -11,6 +11,7 @@ django-rest-framework = "^0.1.0"
|
|||||||
channels = "^3.0.3"
|
channels = "^3.0.3"
|
||||||
uvloop = "^0.15.2"
|
uvloop = "^0.15.2"
|
||||||
djangorestframework-dataclasses = "^0.9"
|
djangorestframework-dataclasses = "^0.9"
|
||||||
|
social-auth-app-django = "^4.0.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
flake8 = "^3.9.2"
|
flake8 = "^3.9.2"
|
||||||
|
@ -5,6 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|||||||
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
||||||
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'
|
||||||
import { AppComponent } from './components/app.component'
|
import { AppComponent } from './components/app.component'
|
||||||
|
import { MainComponent } from './components/main.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -17,6 +18,7 @@ import { AppComponent } from './components/app.component'
|
|||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
MainComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,55 +1,2 @@
|
|||||||
.sidebar
|
main(*ngIf='ready && user')
|
||||||
img.logo(src='{{_logo}}')
|
login(*ngIf='ready && !user')
|
||||||
|
|
||||||
div(ngbDropdown, placement='bottom-right')
|
|
||||||
button.btn.btn-secondary(ngbDropdownToggle)
|
|
||||||
fa-icon([icon]='_cogIcon', [fixedWidth]='true')
|
|
||||||
|
|
||||||
.config-menu(ngbDropdownMenu)
|
|
||||||
.header(*ngIf='getActiveConfig()')
|
|
||||||
.dropdown-header Active config
|
|
||||||
.title {{getActiveConfig().modified_at}}
|
|
||||||
div(*ngIf='activeVersion')
|
|
||||||
div App version:
|
|
||||||
div(ngbDropdown)
|
|
||||||
button.btn.btn-secondary(ngbDropdownToggle) {{activeVersion.version}}
|
|
||||||
div(ngbDropdownMenu)
|
|
||||||
a(
|
|
||||||
*ngFor='let version of versions',
|
|
||||||
ngbDropdownItem,
|
|
||||||
[class.active]='version == activeVersion',
|
|
||||||
(click)='selectVersion(version)'
|
|
||||||
) {{version.version}}
|
|
||||||
|
|
||||||
.btn-toolbar
|
|
||||||
button.btn.btn-light.w-50((click)='duplicateConfig()')
|
|
||||||
fa-icon([icon]='_copyIcon', [fixedWidth]='true')
|
|
||||||
span Duplicate
|
|
||||||
|
|
||||||
button.btn.btn-light.w-50((click)='deleteConfig()')
|
|
||||||
fa-icon([icon]='_deleteIcon', [fixedWidth]='true')
|
|
||||||
span Delete
|
|
||||||
|
|
||||||
div(*ngIf='configs.length > 1')
|
|
||||||
.dropdown-header All configs
|
|
||||||
|
|
||||||
ng-container(*ngFor='let config of configs')
|
|
||||||
a(
|
|
||||||
*ngIf='config !== getActiveConfig()',
|
|
||||||
ngbDropdownItem,
|
|
||||||
(click)='selectConfig(config)'
|
|
||||||
) Config modified at {{config.modified_at}}
|
|
||||||
|
|
||||||
button.btn.btn-light.w-100((click)='createNewConfig()')
|
|
||||||
fa-icon([icon]='_addIcon', [fixedWidth]='true')
|
|
||||||
span New config
|
|
||||||
|
|
||||||
div(ngbDropdown, placement='bottom-right')
|
|
||||||
button.btn.btn-secondary(ngbDropdownToggle)
|
|
||||||
fa-icon([icon]='_userIcon', [fixedWidth]='true')
|
|
||||||
|
|
||||||
div(ngbDropdownMenu)
|
|
||||||
a(ngbDropdownItem, (click)='logout()') Logout
|
|
||||||
|
|
||||||
.terminal([hidden]='!activeVersion')
|
|
||||||
iframe(#iframe)
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
:host {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 64px;
|
|
||||||
flex: none;
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.terminal {
|
|
||||||
flex: 1 1 0;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.config-menu {
|
|
||||||
.header {
|
|
||||||
border-bottom: 1px solid black;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,5 @@
|
|||||||
import * as semverGT from 'semver/functions/gt'
|
import { Component } from '@angular/core'
|
||||||
import { Component, ElementRef, ViewChild } from '@angular/core'
|
|
||||||
import { HttpClient } from '@angular/common/http'
|
import { HttpClient } from '@angular/common/http'
|
||||||
import { AppConnectorService } from '../services/appConnector.service'
|
|
||||||
|
|
||||||
import { faCog, faUser, faCopy, faTrash, faPlus } from '@fortawesome/free-solid-svg-icons'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app',
|
selector: 'app',
|
||||||
@ -11,95 +7,18 @@ import { faCog, faUser, faCopy, faTrash, faPlus } from '@fortawesome/free-solid-
|
|||||||
styleUrls: ['./app.component.scss'],
|
styleUrls: ['./app.component.scss'],
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
_logo = require('../assets/logo.svg')
|
user: any
|
||||||
_cogIcon = faCog
|
ready = false
|
||||||
_userIcon = faUser
|
|
||||||
_copyIcon = faCopy
|
|
||||||
_addIcon = faPlus
|
|
||||||
_deleteIcon = faTrash
|
|
||||||
|
|
||||||
configs: any[] = []
|
|
||||||
versions: any[] = []
|
|
||||||
activeVersion?: any
|
|
||||||
@ViewChild('iframe') iframe: ElementRef
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private appConnector: AppConnectorService,
|
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
) {
|
) { }
|
||||||
window.addEventListener('message', event => {
|
|
||||||
if (event.data === 'request-connector') {
|
|
||||||
this.iframe.nativeElement.contentWindow['__connector__'] = this.appConnector
|
|
||||||
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async ngAfterViewInit () {
|
async ngOnInit () {
|
||||||
this.configs = await this.http.get('/api/1/configs').toPromise()
|
const user = await this.http.get('/api/1/user').toPromise()
|
||||||
this.versions = await this.http.get('/api/1/versions').toPromise()
|
if (user.id) {
|
||||||
|
this.user = user
|
||||||
this.versions.sort((a, b) => semverGT(a, b))
|
|
||||||
|
|
||||||
if (!this.configs.length) {
|
|
||||||
await this.createNewConfig()
|
|
||||||
}
|
}
|
||||||
|
this.ready = true
|
||||||
this.selectConfig(this.configs[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
async createNewConfig () {
|
|
||||||
this.configs.push(await this.http.post('/api/1/configs', {
|
|
||||||
content: '{}',
|
|
||||||
last_used_with_version: this.versions[0].version,
|
|
||||||
}).toPromise())
|
|
||||||
}
|
|
||||||
|
|
||||||
async duplicateConfig () {
|
|
||||||
const copy = {...this.appConnector.config, pk: undefined}
|
|
||||||
this.configs.push(await this.http.post('/api/1/configs', copy).toPromise())
|
|
||||||
}
|
|
||||||
|
|
||||||
unloadApp () {
|
|
||||||
delete this.activeVersion
|
|
||||||
this.iframe.nativeElement.src = 'about:blank'
|
|
||||||
}
|
|
||||||
|
|
||||||
loadApp (version) {
|
|
||||||
this.iframe.nativeElement.src = `/terminal?${version.version}`
|
|
||||||
this.activeVersion = version
|
|
||||||
}
|
|
||||||
|
|
||||||
getActiveConfig () {
|
|
||||||
return this.appConnector.config
|
|
||||||
}
|
|
||||||
|
|
||||||
selectVersion (version: any) {
|
|
||||||
// TODO check config incompatibility
|
|
||||||
this.unloadApp()
|
|
||||||
setTimeout(() => {
|
|
||||||
this.loadApp(version)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectConfig (config: any) {
|
|
||||||
let matchingVersion = this.versions.find(x => x.version === config.last_used_with_version)
|
|
||||||
if (!matchingVersion) {
|
|
||||||
// TODO ask to upgrade
|
|
||||||
matchingVersion = this.versions[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.appConnector.config = config
|
|
||||||
|
|
||||||
const result = await this.http.patch(`/api/1/configs/${config.id}`, {
|
|
||||||
last_used_with_version: matchingVersion.version,
|
|
||||||
}).toPromise()
|
|
||||||
Object.assign(config, result)
|
|
||||||
|
|
||||||
this.selectVersion(matchingVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
async logout () {
|
|
||||||
await this.http.post('/api/1/auth/logout', null).toPromise()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
57
src/components/main.component.pug
Normal file
57
src/components/main.component.pug
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
.sidebar
|
||||||
|
img.logo(src='{{_logo}}')
|
||||||
|
|
||||||
|
div(ngbDropdown, placement='bottom-right')
|
||||||
|
button.btn(ngbDropdownToggle)
|
||||||
|
fa-icon([icon]='_cogIcon', [fixedWidth]='true')
|
||||||
|
|
||||||
|
.config-menu(ngbDropdownMenu)
|
||||||
|
.header(*ngIf='getActiveConfig()')
|
||||||
|
.d-flex.align-items-center.py-2.px-4
|
||||||
|
.me-auto
|
||||||
|
label Active config
|
||||||
|
.title {{getActiveConfig().modified_at}}
|
||||||
|
|
||||||
|
button.btn.btn-semi.me-2((click)='duplicateConfig()')
|
||||||
|
fa-icon([icon]='_copyIcon', [fixedWidth]='true')
|
||||||
|
|
||||||
|
button.btn.btn-semi((click)='deleteConfig()')
|
||||||
|
fa-icon([icon]='_deleteIcon', [fixedWidth]='true')
|
||||||
|
|
||||||
|
.d-flex.align-items-center.py-2.px-4(*ngIf='activeVersion')
|
||||||
|
.me-auto App version:
|
||||||
|
div(ngbDropdown)
|
||||||
|
button.btn.btn-semi(ngbDropdownToggle) {{activeVersion.version}}
|
||||||
|
div(ngbDropdownMenu)
|
||||||
|
a(
|
||||||
|
*ngFor='let version of versions',
|
||||||
|
ngbDropdownItem,
|
||||||
|
[class.active]='version == activeVersion',
|
||||||
|
(click)='selectVersion(version)'
|
||||||
|
) {{version.version}}
|
||||||
|
|
||||||
|
div(*ngIf='configs.length > 1')
|
||||||
|
.dropdown-header All configs
|
||||||
|
|
||||||
|
ng-container(*ngFor='let config of configs')
|
||||||
|
a(
|
||||||
|
*ngIf='config !== getActiveConfig()',
|
||||||
|
ngbDropdownItem,
|
||||||
|
(click)='selectConfig(config)',
|
||||||
|
href='#'
|
||||||
|
) Config modified at {{config.modified_at}}
|
||||||
|
|
||||||
|
.p-3
|
||||||
|
button.btn.btn-semi.w-100((click)='createNewConfig()')
|
||||||
|
fa-icon([icon]='_addIcon', [fixedWidth]='true')
|
||||||
|
span New config
|
||||||
|
|
||||||
|
div(ngbDropdown, placement='bottom-right')
|
||||||
|
button.btn(ngbDropdownToggle)
|
||||||
|
fa-icon([icon]='_userIcon', [fixedWidth]='true')
|
||||||
|
|
||||||
|
div(ngbDropdownMenu)
|
||||||
|
a(ngbDropdownItem, (click)='logout()', href='#') Logout
|
||||||
|
|
||||||
|
.terminal([hidden]='!activeVersion')
|
||||||
|
iframe(#iframe)
|
61
src/components/main.component.scss
Normal file
61
src/components/main.component.scss
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
@import "../theme/vars";
|
||||||
|
|
||||||
|
:host {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 64px;
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>button, >[ngbdropdown] > button {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal {
|
||||||
|
flex: 1 1 0;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
background: $body-bg;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.config-menu {
|
||||||
|
.header {
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
}
|
||||||
|
}
|
106
src/components/main.component.ts
Normal file
106
src/components/main.component.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import * as semverGT from 'semver/functions/gt'
|
||||||
|
import { Component, ElementRef, ViewChild } from '@angular/core'
|
||||||
|
import { HttpClient } from '@angular/common/http'
|
||||||
|
import { AppConnectorService } from '../services/appConnector.service'
|
||||||
|
|
||||||
|
import { faCog, faUser, faCopy, faTrash, faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'main',
|
||||||
|
templateUrl: './main.component.pug',
|
||||||
|
styleUrls: ['./main.component.scss'],
|
||||||
|
})
|
||||||
|
export class MainComponent {
|
||||||
|
_logo = require('../assets/logo.svg')
|
||||||
|
_cogIcon = faCog
|
||||||
|
_userIcon = faUser
|
||||||
|
_copyIcon = faCopy
|
||||||
|
_addIcon = faPlus
|
||||||
|
_deleteIcon = faTrash
|
||||||
|
|
||||||
|
configs: any[] = []
|
||||||
|
versions: any[] = []
|
||||||
|
activeVersion?: any
|
||||||
|
@ViewChild('iframe') iframe: ElementRef
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private appConnector: AppConnectorService,
|
||||||
|
private http: HttpClient,
|
||||||
|
) {
|
||||||
|
window.addEventListener('message', event => {
|
||||||
|
if (event.data === 'request-connector') {
|
||||||
|
this.iframe.nativeElement.contentWindow['__connector__'] = this.appConnector
|
||||||
|
this.iframe.nativeElement.contentWindow.postMessage('connector-ready', '*')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngAfterViewInit () {
|
||||||
|
this.configs = await this.http.get('/api/1/configs').toPromise()
|
||||||
|
this.versions = await this.http.get('/api/1/versions').toPromise()
|
||||||
|
|
||||||
|
this.versions.sort((a, b) => semverGT(a, b))
|
||||||
|
|
||||||
|
if (!this.configs.length) {
|
||||||
|
await this.createNewConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectConfig(this.configs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
async createNewConfig () {
|
||||||
|
this.configs.push(await this.http.post('/api/1/configs', {
|
||||||
|
content: '{}',
|
||||||
|
last_used_with_version: this.versions[0].version,
|
||||||
|
}).toPromise())
|
||||||
|
}
|
||||||
|
|
||||||
|
async duplicateConfig () {
|
||||||
|
const copy = {...this.appConnector.config, pk: undefined}
|
||||||
|
this.configs.push(await this.http.post('/api/1/configs', copy).toPromise())
|
||||||
|
}
|
||||||
|
|
||||||
|
unloadApp () {
|
||||||
|
delete this.activeVersion
|
||||||
|
this.iframe.nativeElement.src = 'about:blank'
|
||||||
|
}
|
||||||
|
|
||||||
|
loadApp (version) {
|
||||||
|
this.iframe.nativeElement.src = `/terminal?${version.version}`
|
||||||
|
this.activeVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveConfig () {
|
||||||
|
return this.appConnector.config
|
||||||
|
}
|
||||||
|
|
||||||
|
selectVersion (version: any) {
|
||||||
|
// TODO check config incompatibility
|
||||||
|
this.unloadApp()
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loadApp(version)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectConfig (config: any) {
|
||||||
|
let matchingVersion = this.versions.find(x => x.version === config.last_used_with_version)
|
||||||
|
if (!matchingVersion) {
|
||||||
|
// TODO ask to upgrade
|
||||||
|
matchingVersion = this.versions[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.appConnector.config = config
|
||||||
|
|
||||||
|
const result = await this.http.patch(`/api/1/configs/${config.id}`, {
|
||||||
|
last_used_with_version: matchingVersion.version,
|
||||||
|
}).toPromise()
|
||||||
|
Object.assign(config, result)
|
||||||
|
|
||||||
|
this.selectVersion(matchingVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
async logout () {
|
||||||
|
await this.http.post('/api/1/auth/logout', null).toPromise()
|
||||||
|
location.href = '/'
|
||||||
|
}
|
||||||
|
}
|
@ -6,4 +6,4 @@ body {
|
|||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "node_modules/bootstrap/scss/bootstrap";
|
@import "./theme/index.scss"
|
||||||
|
64
src/theme/index.scss
Normal file
64
src/theme/index.scss
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
@import "vars";
|
||||||
|
|
||||||
|
@import "~bootstrap/scss/functions";
|
||||||
|
@import "~bootstrap/scss/variables";
|
||||||
|
@import "~bootstrap/scss/mixins";
|
||||||
|
@import "~bootstrap/scss/utilities";
|
||||||
|
|
||||||
|
@import "~bootstrap/scss/root";
|
||||||
|
@import "~bootstrap/scss/reboot";
|
||||||
|
@import "~bootstrap/scss/type";
|
||||||
|
// @import "~bootstrap/scss/images";
|
||||||
|
@import "~bootstrap/scss/containers";
|
||||||
|
@import "~bootstrap/scss/grid";
|
||||||
|
// @import "~bootstrap/scss/tables";
|
||||||
|
@import "~bootstrap/scss/forms";
|
||||||
|
@import "~bootstrap/scss/buttons";
|
||||||
|
@import "~bootstrap/scss/transitions";
|
||||||
|
@import "~bootstrap/scss/dropdown";
|
||||||
|
@import "~bootstrap/scss/button-group";
|
||||||
|
// @import "~bootstrap/scss/nav";
|
||||||
|
// @import "~bootstrap/scss/navbar";
|
||||||
|
// @import "~bootstrap/scss/card";
|
||||||
|
// @import "~bootstrap/scss/accordion";
|
||||||
|
// @import "~bootstrap/scss/breadcrum/b";
|
||||||
|
// @import "~bootstrap/scss/pagination";
|
||||||
|
@import "~bootstrap/scss/badge";
|
||||||
|
// @import "~bootstrap/scss/alert";
|
||||||
|
// @import "~bootstrap/scss/progress";
|
||||||
|
@import "~bootstrap/scss/list-group";
|
||||||
|
// @import "~bootstrap/scss/close";
|
||||||
|
// @import "~bootstrap/scss/toasts";
|
||||||
|
// @import "~bootstrap/scss/modal";
|
||||||
|
// @import "~bootstrap/scss/tooltip";
|
||||||
|
// @import "~bootstrap/scss/popover";
|
||||||
|
// @import "~bootstrap/scss/carousel";
|
||||||
|
// @import "~bootstrap/scss/spinners";
|
||||||
|
// @import "~bootstrap/scss/offcanvas";
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
@import "~bootstrap/scss/helpers";
|
||||||
|
@import "~bootstrap/scss/utilities/api";
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track
|
||||||
|
{
|
||||||
|
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
||||||
|
background-color: $gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar
|
||||||
|
{
|
||||||
|
height: 6px;
|
||||||
|
width: 6px;
|
||||||
|
background-color: #F5F5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb
|
||||||
|
{
|
||||||
|
background-color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
box-shadow: $dropdown-box-shadow;
|
||||||
|
}
|
187
src/theme/vars.scss
Normal file
187
src/theme/vars.scss
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
$white: #fff;
|
||||||
|
$gray-100: #f8f9fa;
|
||||||
|
$gray-200: #e9ecef;
|
||||||
|
$gray-300: #dee2e6;
|
||||||
|
$gray-400: #ced4da;
|
||||||
|
$gray-500: #adb5bd;
|
||||||
|
$gray-600: #6c757d;
|
||||||
|
$gray-700: #495057;
|
||||||
|
$gray-800: #343a40;
|
||||||
|
$gray-900: #212529;
|
||||||
|
$black: #000;
|
||||||
|
|
||||||
|
|
||||||
|
$red: #d9534f !default;
|
||||||
|
$orange: #f0ad4e !default;
|
||||||
|
$yellow: #ffd500 !default;
|
||||||
|
$green: #5cb85c !default;
|
||||||
|
$blue: #0275d8 !default;
|
||||||
|
$teal: #5bc0de !default;
|
||||||
|
$pink: #ff5b77 !default;
|
||||||
|
$purple: #613d7c !default;
|
||||||
|
$semi: rgba(0,0,0, .5);
|
||||||
|
|
||||||
|
|
||||||
|
@import "~bootstrap/scss/functions";
|
||||||
|
|
||||||
|
$table-bg: rgba(255,255,255,.05);
|
||||||
|
$table-bg-hover: rgba(255,255,255,.1);
|
||||||
|
$table-border-color: rgba(255,255,255,.1);
|
||||||
|
|
||||||
|
$theme-colors: (
|
||||||
|
primary: $blue,
|
||||||
|
secondary: #38434e,
|
||||||
|
success: $green,
|
||||||
|
info: $blue,
|
||||||
|
warning: $orange,
|
||||||
|
danger: $red,
|
||||||
|
light: $gray-300,
|
||||||
|
dark: #0e151d,
|
||||||
|
rare: $purple,
|
||||||
|
semi: $semi
|
||||||
|
);
|
||||||
|
|
||||||
|
$body-color: #ccc;
|
||||||
|
$body-bg: #0c131b;
|
||||||
|
|
||||||
|
$font-family-sans-serif: "Source Sans Pro";
|
||||||
|
$font-family-monospace: "Source Code Pro";
|
||||||
|
$font-size-base: 14rem / 16;
|
||||||
|
$font-size-lg: 1.28rem;
|
||||||
|
$font-size-sm: .85rem;
|
||||||
|
|
||||||
|
$line-height-base: 1.6;
|
||||||
|
|
||||||
|
$border-radius: .4rem;
|
||||||
|
$border-radius-lg: .6rem;
|
||||||
|
$border-radius-sm: .2rem;
|
||||||
|
|
||||||
|
$box-shadow: 0 .5rem 1rem rgba($black, .5) !default;
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
|
$headings-color: #ced9e2;
|
||||||
|
$headings-font-weight: lighter;
|
||||||
|
|
||||||
|
$input-btn-padding-y: .3rem;
|
||||||
|
$input-btn-padding-x: .9rem;
|
||||||
|
$input-btn-line-height: 1.6;
|
||||||
|
$input-btn-line-height-sm: 1.8;
|
||||||
|
$input-btn-line-height-lg: 1.8;
|
||||||
|
$btn-focus-width: 1px;
|
||||||
|
|
||||||
|
$h4-font-size: 18px;
|
||||||
|
|
||||||
|
$link-color: $gray-400;
|
||||||
|
$link-hover-color: $white;
|
||||||
|
$link-hover-decoration: none;
|
||||||
|
|
||||||
|
$component-active-color: $white;
|
||||||
|
$component-active-bg: #2f3a42;
|
||||||
|
|
||||||
|
$list-group-bg: $table-bg;
|
||||||
|
$list-group-border-color: $table-border-color;
|
||||||
|
|
||||||
|
$list-group-item-padding-y: 0.8rem;
|
||||||
|
$list-group-item-padding-x: 1rem;
|
||||||
|
|
||||||
|
$list-group-hover-bg: $table-bg-hover;
|
||||||
|
$list-group-active-bg: rgba(255,255,255,.2);
|
||||||
|
$list-group-active-color: $component-active-color;
|
||||||
|
$list-group-active-border-color: translate;
|
||||||
|
|
||||||
|
$list-group-action-color: $body-color;
|
||||||
|
$list-group-action-hover-color: white;
|
||||||
|
|
||||||
|
$list-group-action-active-color: $component-active-color;
|
||||||
|
$list-group-action-active-bg: $list-group-active-bg;
|
||||||
|
|
||||||
|
$alert-padding-y: 0.9rem;
|
||||||
|
$alert-padding-x: 1.25rem;
|
||||||
|
|
||||||
|
$transition-base: all .15s ease-in-out;
|
||||||
|
$transition-fade: opacity .1s linear;
|
||||||
|
$transition-collapse: height .35s ease;
|
||||||
|
$btn-transition: all .15s ease-in-out;
|
||||||
|
|
||||||
|
$popover-bg: $body-bg;
|
||||||
|
$popover-body-color: $body-color;
|
||||||
|
$popover-header-bg: $table-bg-hover;
|
||||||
|
$popover-header-color: $headings-color;
|
||||||
|
$popover-arrow-color: $popover-bg;
|
||||||
|
$popover-max-width: 360px;
|
||||||
|
|
||||||
|
$btn-border-width: 2px;
|
||||||
|
|
||||||
|
$input-bg: #181e23;
|
||||||
|
$input-disabled-bg: #2e3235;
|
||||||
|
|
||||||
|
$input-color: #ddd;
|
||||||
|
$input-border-color: $input-bg;
|
||||||
|
$input-border-width: 2px;
|
||||||
|
|
||||||
|
$input-focus-bg: $input-bg;
|
||||||
|
$input-focus-border-color: rgba(171, 171, 171, 0.61);
|
||||||
|
$input-focus-color: $input-color;
|
||||||
|
|
||||||
|
$input-group-addon-color: $input-color;
|
||||||
|
$input-group-addon-bg: $input-bg;
|
||||||
|
$input-group-addon-border-color: transparent;
|
||||||
|
$input-group-btn-border-color: $input-bg;
|
||||||
|
|
||||||
|
$nav-tabs-border-radius: 0;
|
||||||
|
$nav-tabs-border-color: transparent;
|
||||||
|
$nav-tabs-border-width: 2px;
|
||||||
|
$nav-tabs-link-hover-border-color: transparent;
|
||||||
|
$nav-tabs-link-active-color: #eee;
|
||||||
|
$nav-tabs-link-active-bg: transparent;
|
||||||
|
$nav-tabs-link-active-border-color: #eee;
|
||||||
|
|
||||||
|
$navbar-padding-y: 0;
|
||||||
|
$navbar-padding-x: 0;
|
||||||
|
|
||||||
|
$dropdown-bg: $body-bg;
|
||||||
|
$dropdown-color: $body-color;
|
||||||
|
$dropdown-border-width: 1px;
|
||||||
|
$dropdown-header-color: $gray-500;
|
||||||
|
|
||||||
|
$dropdown-link-color: $body-color;
|
||||||
|
$dropdown-link-hover-color: #eee;
|
||||||
|
$dropdown-link-hover-bg: rgba(255,255,255,.04);
|
||||||
|
$dropdown-link-active-color: white;
|
||||||
|
$dropdown-link-active-bg: rgba(0, 0, 0, .2);
|
||||||
|
$dropdown-item-padding-y: 0.5rem;
|
||||||
|
$dropdown-item-padding-x: 1.5rem;
|
||||||
|
|
||||||
|
|
||||||
|
$code-color: $orange;
|
||||||
|
$code-bg: rgba(0, 0, 0, .25);
|
||||||
|
$code-padding-y: 3px;
|
||||||
|
$code-padding-x: 5px;
|
||||||
|
$pre-bg: $dropdown-bg;
|
||||||
|
$pre-color: $dropdown-link-color;
|
||||||
|
|
||||||
|
$badge-font-size: 0.75rem;
|
||||||
|
$badge-font-weight: bold;
|
||||||
|
$badge-padding-y: 4px;
|
||||||
|
$badge-padding-x: 6px;
|
||||||
|
|
||||||
|
|
||||||
|
$custom-control-indicator-size: 1.2rem;
|
||||||
|
$custom-control-indicator-bg: $body-bg;
|
||||||
|
$custom-control-indicator-border-color: lighten($body-bg, 25%);
|
||||||
|
$custom-control-indicator-checked-bg: theme-color("primary");
|
||||||
|
$custom-control-indicator-checked-color: $body-bg;
|
||||||
|
$custom-control-indicator-checked-border-color: transparent;
|
||||||
|
$custom-control-indicator-active-bg: rgba(255, 255, 0, 0.5);
|
||||||
|
|
||||||
|
|
||||||
|
$modal-content-bg: $body-bg;
|
||||||
|
$modal-content-border-color: $body-bg;
|
||||||
|
$modal-header-border-width: 0;
|
||||||
|
$modal-footer-border-color: #222;
|
||||||
|
$modal-footer-border-width: 1px;
|
||||||
|
$modal-content-border-width: 0;
|
||||||
|
|
||||||
|
$progress-bg: $table-bg;
|
||||||
|
$progress-height: 3px;
|
@ -2,15 +2,16 @@ import os
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
|
from rest_framework import fields
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer, Field
|
||||||
from rest_framework_dataclasses.serializers import DataclassSerializer
|
from rest_framework_dataclasses.serializers import DataclassSerializer
|
||||||
|
|
||||||
from .models import Config
|
from .models import Config, User
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -61,6 +62,26 @@ class AppVersionViewSet(ListModelMixin, GenericViewSet):
|
|||||||
).data)
|
).data)
|
||||||
|
|
||||||
|
|
||||||
|
class UserSerializer(ModelSerializer):
|
||||||
|
id = fields.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ('id', 'username', 'active_config')
|
||||||
|
read_only_fields = ('id', 'username')
|
||||||
|
|
||||||
|
|
||||||
|
class UserViewSet(RetrieveModelMixin, GenericViewSet):
|
||||||
|
queryset = User.objects.all()
|
||||||
|
serializer_class = UserSerializer
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return self.request.user
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(APIView):
|
class LogoutView(APIView):
|
||||||
def post(self, request, format=None):
|
def post(self, request, format=None):
|
||||||
logout(request)
|
logout(request)
|
||||||
|
return Response(None)
|
||||||
|
@ -12,6 +12,7 @@ router.register('api/1/versions', api.AppVersionViewSet, basename='app-versions'
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('api/1/auth/logout', api.LogoutView.as_view()),
|
path('api/1/auth/logout', api.LogoutView.as_view()),
|
||||||
|
path('api/1/user', api.UserViewSet.as_view({'get': 'retrieve'})),
|
||||||
|
|
||||||
path('', views.IndexView.as_view()),
|
path('', views.IndexView.as_view()),
|
||||||
path('terminal', views.TerminalView.as_view()),
|
path('terminal', views.TerminalView.as_view()),
|
||||||
|
@ -39,6 +39,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'channels',
|
'channels',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
|
'social_django',
|
||||||
'terminus.app',
|
'terminus.app',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -19,5 +19,6 @@ from .app.urls import urlpatterns
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', include(urlpatterns)),
|
path('', include(urlpatterns)),
|
||||||
|
path('', include('social_django.urls', namespace='social')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user