mirror of
https://github.com/Eugeny/tabby-web.git
synced 2025-06-20 03:20:06 +00:00
wip
This commit is contained in:
parent
29a3b34dd2
commit
74fb173d80
@ -1,2 +0,0 @@
|
||||
errorlog="-"
|
||||
workers=4
|
250
poetry.lock
generated
250
poetry.lock
generated
@ -1,3 +1,11 @@
|
||||
[[package]]
|
||||
name = "appdirs"
|
||||
version = "1.4.4"
|
||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.3.4"
|
||||
@ -66,6 +74,38 @@ six = "*"
|
||||
[package.extras]
|
||||
visualize = ["graphviz (>0.5.1)", "Twisted (>=16.1.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "21.6b0"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2"
|
||||
|
||||
[package.dependencies]
|
||||
appdirs = "*"
|
||||
click = ">=7.1.2"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
pathspec = ">=0.8.1,<1"
|
||||
regex = ">=2020.1.8"
|
||||
toml = ">=0.10.1"
|
||||
typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""}
|
||||
typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"]
|
||||
python2 = ["typed-ast (>=1.4.2)"]
|
||||
uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2021.5.30"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "1.14.5"
|
||||
@ -93,6 +133,14 @@ Django = ">=2.2"
|
||||
[package.extras]
|
||||
tests = ["pytest", "pytest-django", "pytest-asyncio", "async-generator", "async-timeout", "coverage (>=4.5,<5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "chardet"
|
||||
version = "4.0.0"
|
||||
description = "Universal encoding detector for Python 2 and 3"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.0.1"
|
||||
@ -308,11 +356,11 @@ idna = ">=2.5"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.2"
|
||||
version = "2.10"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
@ -349,6 +397,14 @@ category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mysqlclient"
|
||||
version = "2.0.3"
|
||||
@ -370,6 +426,14 @@ rsa = ["cryptography (>=3.0.0,<4)"]
|
||||
signals = ["blinker (>=1.4.0)"]
|
||||
signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.8.1"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "promise"
|
||||
version = "2.3"
|
||||
@ -500,15 +564,29 @@ optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.15.1"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
name = "regex"
|
||||
version = "2021.7.6"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.25.1"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
chardet = ">=3.0.2,<5"
|
||||
idna = ">=2.5,<3"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
|
||||
[package.extras]
|
||||
security = ["cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)"]
|
||||
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||
|
||||
[[package]]
|
||||
@ -534,6 +612,14 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "2.13.0"
|
||||
description = "Python helper for Semantic Versioning (http://semver.org/)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "service-identity"
|
||||
version = "21.1.0"
|
||||
@ -607,6 +693,14 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "twisted"
|
||||
version = "20.3.0"
|
||||
@ -652,6 +746,14 @@ all = ["zope.interface (>=5.2.0)", "twisted (>=20.3.0)"]
|
||||
dev = ["wheel", "pytest (>=2.6.4)", "pytest-cov (>=1.8.1)", "pep8 (>=1.6.2)", "sphinx (>=1.2.3)", "pyenchant (>=1.6.6)", "sphinxcontrib-spelling (>=2.1.2)", "sphinx-rtd-theme (>=0.1.9)", "tox (>=2.1.1)", "mock (==1.3.0)", "twine (>=1.6.5)", "tox-gh-actions (>=2.2.0)"]
|
||||
twisted = ["zope.interface (>=5.2.0)", "twisted (>=20.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "typed-ast"
|
||||
version = "1.4.3"
|
||||
description = "a fork of Python 2 and 3 ast modules with type comment support"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "3.10.0.0"
|
||||
@ -660,6 +762,19 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.6"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotlipy (>=0.6.0)"]
|
||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.14.0"
|
||||
@ -726,9 +841,13 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "894aba6b24869dde338f2fdcb2b4ed6f62e6cfbc9a2f934c4ee73cf61b88c36c"
|
||||
content-hash = "e15a4f9c7fdbf146c22cdd14ac7e67c7fa975a1db04f10c34a6b4c8aa8c9c91e"
|
||||
|
||||
[metadata.files]
|
||||
appdirs = [
|
||||
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
||||
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
|
||||
]
|
||||
asgiref = [
|
||||
{file = "asgiref-3.3.4-py3-none-any.whl", hash = "sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee"},
|
||||
{file = "asgiref-3.3.4.tar.gz", hash = "sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78"},
|
||||
@ -745,6 +864,14 @@ automat = [
|
||||
{file = "Automat-20.2.0-py2.py3-none-any.whl", hash = "sha256:b6feb6455337df834f6c9962d6ccf771515b7d939bca142b29c20c2376bc6111"},
|
||||
{file = "Automat-20.2.0.tar.gz", hash = "sha256:7979803c74610e11ef0c0d68a2942b152df52da55336e0c9d58daf1831cbdf33"},
|
||||
]
|
||||
black = [
|
||||
{file = "black-21.6b0-py3-none-any.whl", hash = "sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"},
|
||||
{file = "black-21.6b0.tar.gz", hash = "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
||||
{file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
|
||||
]
|
||||
cffi = [
|
||||
{file = "cffi-1.14.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991"},
|
||||
{file = "cffi-1.14.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1"},
|
||||
@ -800,6 +927,10 @@ channels = [
|
||||
{file = "channels-3.0.3-py3-none-any.whl", hash = "sha256:3f15bdd2138bb4796e76ea588a0a344b12a7964ea9b2e456f992fddb988a4317"},
|
||||
{file = "channels-3.0.3.tar.gz", hash = "sha256:056b72e51080a517a0f33a0a30003e03833b551d75394d6636c885d4edb8188f"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
|
||||
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"},
|
||||
{file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"},
|
||||
@ -878,8 +1009,8 @@ hyperlink = [
|
||||
{file = "hyperlink-21.0.0.tar.gz", hash = "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
|
||||
{file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
|
||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||
]
|
||||
importlib-metadata = [
|
||||
{file = "importlib_metadata-4.4.0-py3-none-any.whl", hash = "sha256:960d52ba7c21377c990412aca380bf3642d734c2eaab78a2c39319f67c6a5786"},
|
||||
@ -893,6 +1024,10 @@ mccabe = [
|
||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
|
||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
|
||||
]
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
mysqlclient = [
|
||||
{file = "mysqlclient-2.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3"},
|
||||
{file = "mysqlclient-2.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7"},
|
||||
@ -904,6 +1039,10 @@ oauthlib = [
|
||||
{file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"},
|
||||
{file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"},
|
||||
]
|
||||
pathspec = [
|
||||
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},
|
||||
{file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"},
|
||||
]
|
||||
promise = [
|
||||
{file = "promise-2.3.tar.gz", hash = "sha256:dfd18337c523ba4b6a58801c164c1904a9d4d1b1747c7d5dbf45b693a49d93d0"},
|
||||
]
|
||||
@ -973,9 +1112,52 @@ pytz = [
|
||||
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||
]
|
||||
regex = [
|
||||
{file = "regex-2021.7.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-win32.whl", hash = "sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b"},
|
||||
{file = "regex-2021.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-win32.whl", hash = "sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5"},
|
||||
{file = "regex-2021.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-win32.whl", hash = "sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0"},
|
||||
{file = "regex-2021.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-win32.whl", hash = "sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035"},
|
||||
{file = "regex-2021.7.6-cp39-cp39-win_amd64.whl", hash = "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c"},
|
||||
{file = "regex-2021.7.6.tar.gz", hash = "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.15.1-py2.py3-none-any.whl", hash = "sha256:ff753b2196cd18b1bbeddc9dcd5c864056599f7a7d9a4fb5677e723efa2b7fb9"},
|
||||
{file = "requests-2.15.1.tar.gz", hash = "sha256:e5659b9315a0610505e050bb7190bf6fa2ccee1ac295f2b760ef9d8a03ebbb2e"},
|
||||
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
|
||||
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
|
||||
]
|
||||
requests-oauthlib = [
|
||||
{file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"},
|
||||
@ -986,6 +1168,10 @@ rx = [
|
||||
{file = "Rx-1.6.1-py2.py3-none-any.whl", hash = "sha256:7357592bc7e881a95e0c2013b73326f704953301ab551fbc8133a6fadab84105"},
|
||||
{file = "Rx-1.6.1.tar.gz", hash = "sha256:13a1d8d9e252625c173dc795471e614eadfe1cf40ffc684e08b8fff0d9748c23"},
|
||||
]
|
||||
semver = [
|
||||
{file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"},
|
||||
{file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"},
|
||||
]
|
||||
service-identity = [
|
||||
{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"},
|
||||
@ -1007,6 +1193,10 @@ sqlparse = [
|
||||
{file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
|
||||
{file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
|
||||
]
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
]
|
||||
twisted = [
|
||||
{file = "Twisted-20.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:cdbc4c7f0cd7a2218b575844e970f05a1be1861c607b0e048c9bceca0c4d42f7"},
|
||||
{file = "Twisted-20.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:d267125cc0f1e8a0eed6319ba4ac7477da9b78a535601c49ecd20c875576433a"},
|
||||
@ -1036,11 +1226,47 @@ txaio = [
|
||||
{file = "txaio-21.2.1-py2.py3-none-any.whl", hash = "sha256:c16b55f9a67b2419cfdf8846576e2ec9ba94fe6978a83080c352a80db31c93fb"},
|
||||
{file = "txaio-21.2.1.tar.gz", hash = "sha256:7d6f89745680233f1c4db9ddb748df5e88d2a7a37962be174c0fd04c8dba1dc8"},
|
||||
]
|
||||
typed-ast = [
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"},
|
||||
{file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"},
|
||||
{file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"},
|
||||
{file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"},
|
||||
{file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"},
|
||||
{file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"},
|
||||
{file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"},
|
||||
]
|
||||
typing-extensions = [
|
||||
{file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"},
|
||||
{file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"},
|
||||
{file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"},
|
||||
{file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"},
|
||||
]
|
||||
uvicorn = [
|
||||
{file = "uvicorn-0.14.0-py3-none-any.whl", hash = "sha256:2a76bb359171a504b3d1c853409af3adbfa5cef374a4a59e5881945a97a93eae"},
|
||||
{file = "uvicorn-0.14.0.tar.gz", hash = "sha256:45ad7dfaaa7d55cab4cd1e85e03f27e9d60bc067ddc59db52a2b0aeca8870292"},
|
||||
|
@ -20,9 +20,12 @@ mysqlclient = "^2.0.3"
|
||||
uvicorn = "^0.14.0"
|
||||
gunicorn = "^20.1.0"
|
||||
Twisted = "20.3.0"
|
||||
semver = "^2.13.0"
|
||||
requests = "^2.25.1"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
flake8 = "^3.9.2"
|
||||
black = {version = "^21.6b0", allow-prereleases = true}
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
@ -27,6 +27,12 @@ export interface InstanceInfo {
|
||||
login_enabled: boolean
|
||||
}
|
||||
|
||||
export interface Gateway {
|
||||
host: string
|
||||
port: number
|
||||
url: string
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class InstanceInfoResolver implements Resolve<Observable<InstanceInfo>> {
|
||||
constructor (private http: HttpClient) { }
|
||||
|
@ -3,9 +3,11 @@
|
||||
.d-flex.align-items-center.py-2.px-4
|
||||
.me-auto
|
||||
label Active config
|
||||
.title {{configService.activeConfig.modified_at}}
|
||||
.title
|
||||
fa-icon([icon]='_configIcon')
|
||||
span.ms-2 {{configService.activeConfig.created_at|date:"medium"}}
|
||||
|
||||
button.btn.btn-semi.me-2((click)='configService.duplicateConfig()')
|
||||
button.btn.btn-semi.me-2((click)='configService.duplicateActiveConfig()')
|
||||
fa-icon([icon]='_copyIcon', [fixedWidth]='true')
|
||||
|
||||
button.btn.btn-semi((click)='deleteConfig()')
|
||||
@ -16,25 +18,26 @@
|
||||
div(ngbDropdown)
|
||||
button.btn.btn-semi(ngbDropdownToggle) {{configService.activeVersion.version}}
|
||||
div(ngbDropdownMenu)
|
||||
a(
|
||||
*ngFor='let version of versions',
|
||||
button(
|
||||
*ngFor='let version of configService.versions',
|
||||
ngbDropdownItem,
|
||||
[class.active]='version == configService.activeVersion',
|
||||
(click)='selectVersion(version)'
|
||||
) {{version.version}}
|
||||
|
||||
div(*ngIf='configService.configs.length > 1')
|
||||
.dropdown-header All configs
|
||||
.px-4.pt-3(*ngIf='configService.configs.length > 1')
|
||||
h5 Other configs
|
||||
|
||||
ng-container(*ngFor='let config of configService.configs')
|
||||
a(
|
||||
*ngIf='config !== configService.activeConfig',
|
||||
ngbDropdownItem,
|
||||
(click)='selectConfig(config)',
|
||||
href='#'
|
||||
) Config modified at {{config.modified_at}}
|
||||
.list-group.list-group-light
|
||||
ng-container(*ngFor='let config of configService.configs')
|
||||
button.list-group-item.list-group-item-action(
|
||||
*ngIf='config !== configService.activeConfig',
|
||||
(click)='selectConfig(config)'
|
||||
)
|
||||
fa-icon([icon]='_configIcon')
|
||||
span Config created at {{config.created_at|date:"medium"}}
|
||||
|
||||
.p-3
|
||||
button.btn.btn-semi.w-100((click)='configService.createNewConfig()')
|
||||
.py-3.px-4
|
||||
button.btn.btn-semi.w-100((click)='createNewConfig()')
|
||||
fa-icon([icon]='_addIcon', [fixedWidth]='true')
|
||||
span New config
|
||||
|
@ -2,7 +2,8 @@ import { Component } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faCopy, faFile, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Config, Version } from '../api'
|
||||
|
||||
@Component({
|
||||
selector: 'config-modal',
|
||||
@ -11,6 +12,9 @@ import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
})
|
||||
export class ConfigModalComponent {
|
||||
_addIcon = faPlus
|
||||
_copyIcon = faCopy
|
||||
_deleteIcon = faTrash
|
||||
_configIcon = faFile
|
||||
|
||||
constructor (
|
||||
private modalInstance: NgbActiveModal,
|
||||
@ -26,4 +30,20 @@ export class ConfigModalComponent {
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
async createNewConfig () {
|
||||
const config = await this.configService.createNewConfig()
|
||||
await this.configService.selectConfig(config)
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
async selectConfig (config: Config) {
|
||||
await this.configService.selectConfig(config)
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
async selectVersion (version: Version) {
|
||||
await this.configService.selectVersion(version)
|
||||
this.modalInstance.dismiss()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
.intro
|
||||
h1 Hey.
|
||||
div My name is Eugene and I've built a nice terminal app, #[em.ms-1 just for you].
|
||||
div Crossplatform, local, SSH, serial - it's all there.
|
||||
div Go on, try it out 👇
|
||||
div Crossplatform, local, SSH, serial, Telnet - it's all there.
|
||||
div Here's a demo 👇
|
||||
|
||||
iframe(#iframe)
|
||||
|
||||
|
@ -103,7 +103,7 @@ export class HomeComponent {
|
||||
|
||||
async ngAfterViewInit () {
|
||||
const versions = await this.http.get('/api/1/versions').toPromise()
|
||||
versions.sort((a, b) => semverGT(a, b))
|
||||
versions.sort((a, b) => semverGT(a.version, b.version))
|
||||
this.connector = new DemoConnector(this.iframe.nativeElement.contentWindow, versions[0])
|
||||
this.iframe.nativeElement.src = '/terminal'
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
.sidebar
|
||||
img.logo(src='{{_logo}}')
|
||||
|
||||
button.btn((click)='openConfig()')
|
||||
fa-icon([icon]='_cogIcon', [fixedWidth]='true')
|
||||
button.btn.mt-auto((click)='openConfig()')
|
||||
fa-icon([icon]='_configIcon', [fixedWidth]='true')
|
||||
|
||||
button.btn((click)='openSettings()')
|
||||
fa-icon([icon]='_settingsIcon', [fixedWidth]='true')
|
||||
|
||||
button.btn.mt-auto((click)='logout()')
|
||||
button.btn.mt-3((click)='logout()')
|
||||
fa-icon([icon]='_logoutIcon', [fixedWidth]='true')
|
||||
|
||||
.terminal([hidden]='!showApp')
|
||||
|
@ -2,7 +2,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
|
||||
import { faCog, faCopy, faTrash, faPlus, faSignOutAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faCog, faFile, faPlus, faSignOutAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { LoginService } from '../services/login.service'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { SettingsModalComponent } from './settingsModal.component'
|
||||
@ -19,12 +19,10 @@ import { Router } from '@angular/router'
|
||||
})
|
||||
export class MainComponent {
|
||||
_logo = require('../assets/logo.svg')
|
||||
_cogIcon = faCog
|
||||
_settingsIcon = faCog
|
||||
_logoutIcon = faSignOutAlt
|
||||
_copyIcon = faCopy
|
||||
_addIcon = faPlus
|
||||
_deleteIcon = faTrash
|
||||
_configIcon = faFile
|
||||
|
||||
showApp = false
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
.modal-header
|
||||
h5.modal-title Settings
|
||||
|
||||
.modal-body
|
||||
.mb-3
|
||||
.form-check.form-switch
|
||||
@ -27,6 +28,13 @@
|
||||
)
|
||||
label Gateway authentication token
|
||||
|
||||
div(*ngIf='appConnector.sockets.length')
|
||||
h5 Active connections
|
||||
.list-group.list-group-flush
|
||||
.list-group-item(*ngFor='let socket of appConnector.sockets')
|
||||
div {{socket.options.host}}:{{socket.options.port}}
|
||||
.text-muted via {{socket.url}}
|
||||
|
||||
.modal-footer
|
||||
button.btn.btn-primary((click)='apply()') Apply
|
||||
button.btn.btn-secondary((click)='cancel()') Cancel
|
||||
|
@ -3,6 +3,7 @@ import { LoginService } from '../services/login.service'
|
||||
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { User } from '../api'
|
||||
import { AppConnectorService } from '../services/appConnector.service'
|
||||
|
||||
@Component({
|
||||
selector: 'settings-modal',
|
||||
@ -14,6 +15,7 @@ export class SettingsModalComponent {
|
||||
customGatewayEnabled = false
|
||||
|
||||
constructor (
|
||||
public appConnector: AppConnectorService,
|
||||
private modalInstance: NgbActiveModal,
|
||||
private loginService: LoginService,
|
||||
) {
|
||||
|
@ -4,13 +4,15 @@ import { debounceTime } from 'rxjs/operators'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { LoginService } from '../services/login.service'
|
||||
import { Config, Version } from '../api'
|
||||
import { Config, Gateway, Version } from '../api'
|
||||
|
||||
export class SocketProxy {
|
||||
connect$ = new Subject<void>()
|
||||
data$ = new Subject<Buffer>()
|
||||
error$ = new Subject<Buffer>()
|
||||
close$ = new Subject<Buffer>()
|
||||
|
||||
url: string
|
||||
webSocket: WebSocket
|
||||
initialBuffer: Buffer
|
||||
options: {
|
||||
@ -22,12 +24,18 @@ export class SocketProxy {
|
||||
this.initialBuffer = Buffer.from('')
|
||||
}
|
||||
|
||||
connect (options) {
|
||||
async connect (options) {
|
||||
this.options = options
|
||||
this.webSocket = new WebSocket(
|
||||
this.appConnector.loginService.user.custom_connection_gateway ||
|
||||
`ws://${location.host}/api/1/gateway/tcp`
|
||||
)
|
||||
this.url = this.appConnector.loginService.user.custom_connection_gateway
|
||||
if (!this.url) {
|
||||
try {
|
||||
this.url = (await this.appConnector.chooseConnectionGateway()).url
|
||||
} catch (err) {
|
||||
this.error$.next(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.webSocket = new WebSocket(this.url)
|
||||
this.webSocket.onmessage = async event => {
|
||||
if (typeof(event.data) === 'string') {
|
||||
this.handleServiceMessage(JSON.parse(event.data))
|
||||
@ -35,6 +43,9 @@ export class SocketProxy {
|
||||
this.data$.next(Buffer.from(await event.data.arrayBuffer()))
|
||||
}
|
||||
}
|
||||
this.webSocket.onclose = () => {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
handleServiceMessage (msg) {
|
||||
@ -68,20 +79,23 @@ export class SocketProxy {
|
||||
}
|
||||
|
||||
write (chunk: Buffer): void {
|
||||
if (!this.webSocket.readyState) {
|
||||
if (!this.webSocket?.readyState) {
|
||||
this.initialBuffer = Buffer.concat([this.initialBuffer, chunk])
|
||||
} else {
|
||||
this.webSocket.send(chunk)
|
||||
}
|
||||
}
|
||||
|
||||
close (error: Error): void {
|
||||
close (error?: Error): void {
|
||||
this.webSocket.close()
|
||||
if (error) {
|
||||
this.error$.next(error)
|
||||
}
|
||||
this.connect$.complete()
|
||||
this.data$.complete()
|
||||
this.error$.complete()
|
||||
this.close$.next()
|
||||
this.close$.complete()
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,6 +104,7 @@ export class AppConnectorService {
|
||||
private configUpdate = new Subject<string>()
|
||||
private config: Config
|
||||
private version: Version
|
||||
sockets: SocketProxy[] = []
|
||||
|
||||
constructor (
|
||||
private http: HttpClient,
|
||||
@ -135,6 +150,15 @@ export class AppConnectorService {
|
||||
}
|
||||
|
||||
createSocket () {
|
||||
return new SocketProxy(this)
|
||||
const socket = new SocketProxy(this)
|
||||
this.sockets.push(socket)
|
||||
socket.close$.subscribe(() => {
|
||||
this.sockets = this.sockets.filter(x => x !== socket)
|
||||
})
|
||||
return socket
|
||||
}
|
||||
|
||||
async chooseConnectionGateway (): Promise<Gateway> {
|
||||
return await this.http.post('/api/1/gateways/choose', {}).toPromise()
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,17 @@ export class ConfigService {
|
||||
await this.http.put('/api/1/user', this.user).toPromise()
|
||||
}
|
||||
|
||||
async createNewConfig () {
|
||||
this.configs.push(await this.http.post('/api/1/configs', {
|
||||
async createNewConfig (): Promise<Config> {
|
||||
const config = await this.http.post('/api/1/configs', {
|
||||
content: '{}',
|
||||
last_used_with_version: this._activeVersion.version,
|
||||
}).toPromise())
|
||||
last_used_with_version: this._activeVersion?.version ?? this.getLatestStableVersion().version,
|
||||
}).toPromise()
|
||||
this.configs.push(config)
|
||||
return config
|
||||
}
|
||||
|
||||
getLatestStableVersion () {
|
||||
return this.versions[0]
|
||||
}
|
||||
|
||||
async duplicateActiveConfig () {
|
||||
@ -60,6 +66,8 @@ export class ConfigService {
|
||||
this._activeConfig = config
|
||||
this.activeConfig$.next(config)
|
||||
this.selectVersion(matchingVersion)
|
||||
this.loginService.user.active_config = config.id
|
||||
await this.loginService.updateUser()
|
||||
}
|
||||
|
||||
async selectDefaultConfig () {
|
||||
@ -71,7 +79,7 @@ export class ConfigService {
|
||||
private async init () {
|
||||
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))
|
||||
this.versions.sort((a, b) => semverGT(a.version, b.version))
|
||||
|
||||
if (!this.configs.length) {
|
||||
await this.createNewConfig()
|
||||
|
@ -27,16 +27,26 @@ async function start () {
|
||||
return window['module'].exports
|
||||
}
|
||||
|
||||
async function prefetchURL (url) {
|
||||
await (await fetch(url)).text()
|
||||
}
|
||||
|
||||
const baseUrl = `${connector.getDistURL()}/${appVersion}`
|
||||
await webRequire(`${baseUrl}/tabby-web-container/dist/preload.js`)
|
||||
await webRequire(`${baseUrl}/tabby-web-container/dist/bundle.js`)
|
||||
const coreURLs = [
|
||||
`${baseUrl}/tabby-web-container/dist/preload.js`,
|
||||
`${baseUrl}/tabby-web-container/dist/bundle.js`,
|
||||
]
|
||||
|
||||
await Promise.all(coreURLs.map(prefetchURL))
|
||||
|
||||
for (const url of coreURLs) {
|
||||
await webRequire(url)
|
||||
}
|
||||
|
||||
const tabby = window['Tabby']
|
||||
|
||||
const pluginModules = []
|
||||
for (const plugin of connector.getPluginsToLoad()) {
|
||||
pluginModules.push(await tabby.loadPlugin(`${baseUrl}/${plugin}`))
|
||||
}
|
||||
const pluginURLs = connector.getPluginsToLoad().map(x => `${baseUrl}/${x}`)
|
||||
const pluginModules = await tabby.loadPlugins(pluginURLs)
|
||||
|
||||
document.querySelector('app-root')['style'].display = 'flex'
|
||||
|
||||
|
@ -52,8 +52,8 @@ $font-size-sm: .85rem;
|
||||
|
||||
$line-height-base: 1.6;
|
||||
|
||||
$border-radius: .4rem;
|
||||
$border-radius-lg: .6rem;
|
||||
$border-radius: .35rem;
|
||||
$border-radius-lg: .35rem;
|
||||
$border-radius-sm: .2rem;
|
||||
|
||||
$box-shadow: 0 .5rem 1rem rgba($black, .5) !default;
|
||||
@ -79,6 +79,7 @@ $link-hover-decoration: none;
|
||||
$component-active-color: $white;
|
||||
$component-active-bg: $blue;
|
||||
|
||||
$list-group-color: $body-color;
|
||||
$list-group-bg: $table-bg;
|
||||
$list-group-border-color: $table-border-color;
|
||||
|
||||
@ -145,6 +146,7 @@ $navbar-padding-x: 0;
|
||||
$dropdown-bg: $body-bg;
|
||||
$dropdown-color: $body-color;
|
||||
$dropdown-border-width: 1px;
|
||||
$dropdown-border-color: #ffffff24;
|
||||
$dropdown-header-color: $gray-500;
|
||||
|
||||
$dropdown-link-color: $body-color;
|
||||
@ -182,7 +184,10 @@ $modal-content-bg: $body-bg;
|
||||
$modal-content-border-color: $body-bg;
|
||||
$modal-header-border-width: 0;
|
||||
$modal-footer-border-width: 0;
|
||||
$modal-content-border-width: 0;
|
||||
|
||||
$modal-content-border-color: #ffffff24;
|
||||
$modal-content-border-width: 1px;
|
||||
|
||||
|
||||
$progress-bg: $table-bg;
|
||||
$progress-height: 3px;
|
||||
|
@ -1,11 +1,14 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from .models import User, Config
|
||||
from .models import Gateway, User, Config
|
||||
|
||||
|
||||
class CustomUserAdmin(UserAdmin):
|
||||
fieldsets = UserAdmin.fieldsets + (
|
||||
(None, {'fields': ('custom_connection_gateway', 'custom_connection_gateway_token')}),
|
||||
)
|
||||
|
||||
|
||||
admin.site.register(User, CustomUserAdmin)
|
||||
admin.site.register(Config)
|
||||
admin.site.register(Gateway)
|
||||
|
@ -1,9 +1,10 @@
|
||||
import os
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import logout
|
||||
from rest_framework import fields
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.exceptions import PermissionDenied, NotFound
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||
@ -12,7 +13,7 @@ from rest_framework.viewsets import GenericViewSet, ModelViewSet
|
||||
from rest_framework.serializers import ModelSerializer, Serializer
|
||||
from rest_framework_dataclasses.serializers import DataclassSerializer
|
||||
|
||||
from .models import Config, User
|
||||
from .models import Config, Gateway, User
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -25,6 +26,17 @@ class AppVersionSerializer(DataclassSerializer):
|
||||
dataclass = AppVersion
|
||||
|
||||
|
||||
class GatewaySerializer(ModelSerializer):
|
||||
url = fields.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
fields = '__all__'
|
||||
model = Gateway
|
||||
|
||||
def get_url(self, gw):
|
||||
return f'{"wss" if gw.secure else "ws"}://{gw.host}:{gw.port}/'
|
||||
|
||||
|
||||
class ConfigSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = Config
|
||||
@ -103,3 +115,14 @@ class InstanceInfoViewSet(RetrieveModelMixin, GenericViewSet):
|
||||
return {
|
||||
'login_enabled': settings.ENABLE_LOGIN,
|
||||
}
|
||||
|
||||
|
||||
class ChooseGatewayViewSet(RetrieveModelMixin, GenericViewSet):
|
||||
queryset = Gateway.objects.filter(enabled=True)
|
||||
serializer_class = GatewaySerializer
|
||||
|
||||
def get_object(self):
|
||||
gateways = list(self.queryset)
|
||||
if not len(gateways):
|
||||
raise NotFound()
|
||||
return random.choice(gateways)
|
||||
|
0
tabby/app/management/__init__.py
Normal file
0
tabby/app/management/__init__.py
Normal file
0
tabby/app/management/commands/__init__.py
Normal file
0
tabby/app/management/commands/__init__.py
Normal file
56
tabby/app/management/commands/add_version.py
Normal file
56
tabby/app/management/commands/add_version.py
Normal file
@ -0,0 +1,56 @@
|
||||
import logging
|
||||
import requests
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Downloads a new app version'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('version', type=str)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
version = options['version']
|
||||
target: Path = settings.APP_DIST_PATH / version
|
||||
|
||||
plugin_list = [
|
||||
'tabby-web-container',
|
||||
'tabby-core',
|
||||
'tabby-settings',
|
||||
'tabby-terminal',
|
||||
'tabby-ssh',
|
||||
'tabby-community-color-schemes',
|
||||
'tabby-web',
|
||||
'tabby-web-demo',
|
||||
]
|
||||
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
tempdir = Path(tempdir)
|
||||
for plugin in plugin_list:
|
||||
logging.info(f'Resolving {plugin}@{version}')
|
||||
response = requests.get(f'{settings.NPM_REGISTRY}/{plugin}/{version}')
|
||||
response.raise_for_status()
|
||||
info = response.json()
|
||||
url = info['dist']['tarball']
|
||||
|
||||
logging.info(f'Downloading {plugin}@{version} from {url}')
|
||||
response = requests.get(url)
|
||||
|
||||
with tempfile.NamedTemporaryFile('wb') as f:
|
||||
f.write(response.content)
|
||||
plugin_final_target = Path(tempdir) / plugin
|
||||
|
||||
with tempfile.TemporaryDirectory() as extraction_tmp:
|
||||
subprocess.check_call(
|
||||
['tar', '-xzf', f.name, '-C', str(extraction_tmp)]
|
||||
)
|
||||
shutil.move(Path(extraction_tmp) / 'package', plugin_final_target)
|
||||
|
||||
if target.exists():
|
||||
shutil.rmtree(target)
|
||||
shutil.copytree(tempdir, target)
|
@ -1,8 +1,10 @@
|
||||
# Generated by Django 3.2.3 on 2021-06-05 21:23
|
||||
# Generated by Django 3.2.3 on 2021-07-08 17:43
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.auth.models
|
||||
import django.contrib.auth.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
@ -29,8 +31,11 @@ class Migration(migrations.Migration):
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
|
||||
('active_version', models.CharField(max_length=32, null=True)),
|
||||
('custom_connection_gateway', models.CharField(max_length=255, null=True)),
|
||||
('custom_connection_gateway_token', models.CharField(max_length=255, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('modified_at', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'user',
|
||||
@ -41,4 +46,30 @@ class Migration(migrations.Migration):
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Config',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('content', models.TextField(default='{}')),
|
||||
('last_used_with_version', models.CharField(max_length=32, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('modified_at', models.DateTimeField(auto_now=True)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='configs', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='active_config',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='app.config'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='user_permissions',
|
||||
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
|
||||
),
|
||||
]
|
||||
|
@ -1,48 +0,0 @@
|
||||
# Generated by Django 3.2.3 on 2021-06-05 21:37
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='active_version',
|
||||
field=models.CharField(max_length=32, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='modified_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Config',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('content', models.TextField(default='{}')),
|
||||
('last_used_with_version', models.CharField(max_length=32, null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('modified_at', models.DateTimeField(auto_now=True)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='configs', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='active_config',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='app.config'),
|
||||
),
|
||||
]
|
23
tabby/app/migrations/0002_gateway.py
Normal file
23
tabby/app/migrations/0002_gateway.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.2.3 on 2021-07-08 20:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Gateway',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('host', models.CharField(max_length=255)),
|
||||
('port', models.IntegerField(default=1234)),
|
||||
('enabled', models.BooleanField(default=True)),
|
||||
('secure', models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.3 on 2021-06-20 20:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0002_auto_20210605_2137'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='custom_connection_gateway',
|
||||
field=models.CharField(max_length=255, null=True),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.3 on 2021-06-20 20:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0003_user_custom_connection_gateway'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='custom_connection_gateway_token',
|
||||
field=models.CharField(max_length=255, null=True),
|
||||
),
|
||||
]
|
@ -22,7 +22,11 @@ class User(AbstractUser):
|
||||
modified_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
||||
# @receiver(user_logged_in)
|
||||
# def post_login(sender, user, request, **kwargs):
|
||||
# if not user.active_config:
|
||||
# user.active_config = Config.objects.filter()
|
||||
class Gateway(models.Model):
|
||||
host = models.CharField(max_length=255)
|
||||
port = models.IntegerField(default=1234)
|
||||
enabled = models.BooleanField(default=True)
|
||||
secure = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.host}:{self.port}'
|
||||
|
@ -14,6 +14,7 @@ urlpatterns = [
|
||||
path('api/1/auth/logout', api.LogoutView.as_view()),
|
||||
path('api/1/user', api.UserViewSet.as_view({'get': 'retrieve', 'put': 'update'})),
|
||||
path('api/1/instance-info', api.InstanceInfoViewSet.as_view({'get': 'retrieve'})),
|
||||
path('api/1/gateways/choose', api.ChooseGatewayViewSet.as_view({'post': 'retrieve'})),
|
||||
|
||||
re_path('^(|login|app)$', views.IndexView.as_view()),
|
||||
|
||||
|
@ -21,6 +21,6 @@ class AppDistView(APIView):
|
||||
return static.serve(request, os.path.join(version, path), document_root=str(settings.APP_DIST_PATH))
|
||||
|
||||
|
||||
class BuildView(APIView):
|
||||
def get(self, request, path=None, format=None):
|
||||
return static.serve(request, path, document_root=str(settings.BASE_DIR / 'build'))
|
||||
# class BuildView(APIView):
|
||||
# def get(self, request, path=None, format=None):
|
||||
# return static.serve(request, path, document_root=str(settings.BASE_DIR / 'build'))
|
||||
|
@ -109,6 +109,29 @@ USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'formatters': {
|
||||
'simple': {
|
||||
'format': '%(levelname)s %(message)s'
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'level': 'INFO',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple'
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {
|
||||
'handlers': ['console'],
|
||||
'propagate': False,
|
||||
'level': 'INFO',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
||||
@ -140,7 +163,8 @@ SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email']
|
||||
|
||||
LOGIN_REDIRECT_URL = '/app'
|
||||
|
||||
APP_DIST_PATH = os.getenv('APP_DIST_PATH', BASE_DIR / 'app-dist')
|
||||
APP_DIST_PATH = Path(os.getenv('APP_DIST_PATH', BASE_DIR / 'app-dist'))
|
||||
NPM_REGISTRY = os.getenv('NPM_REGISTRY', 'https://registry.npmjs.org').rstrip('/')
|
||||
|
||||
for key in [
|
||||
'SOCIAL_AUTH_GITHUB_KEY',
|
||||
@ -168,6 +192,12 @@ for key in [
|
||||
globals()[key] = int(globals()[key]) if globals()[key] else None
|
||||
|
||||
|
||||
for key in [
|
||||
'ENABLE_LOGIN',
|
||||
]:
|
||||
globals()[key] = int(globals()[key]) if globals()[key] else None
|
||||
|
||||
|
||||
for key in [
|
||||
'CONNECTION_GATEWAY_AUTH_CA',
|
||||
'CONNECTION_GATEWAY_AUTH_CERTIFICATE',
|
||||
|
Loading…
x
Reference in New Issue
Block a user