Fix dashboards
This commit is contained in:
parent
d539a72e6a
commit
5434c7d6ef
6 changed files with 330 additions and 74 deletions
240
pdm.lock
generated
240
pdm.lock
generated
|
@ -5,7 +5,7 @@
|
|||
groups = ["default", "dev", "mqtt"]
|
||||
strategy = ["cross_platform"]
|
||||
lock_version = "4.4.1"
|
||||
content_hash = "sha256:c76681e48baaf1b76e410a3d5cf54e6712a74ced0429536b2246b79dad62446f"
|
||||
content_hash = "sha256:07dee91945ef2f5557c7130b7ab9fee6bbba2763ce65a3cc18f0d3c89429c30f"
|
||||
|
||||
[[package]]
|
||||
name = "aiomqtt"
|
||||
|
@ -263,6 +263,41 @@ files = [
|
|||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "contourpy"
|
||||
version = "1.2.0"
|
||||
requires_python = ">=3.9"
|
||||
summary = "Python library for calculating contours of 2D quadrilateral grids"
|
||||
dependencies = [
|
||||
"numpy<2.0,>=1.20",
|
||||
]
|
||||
files = [
|
||||
{file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"},
|
||||
{file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"},
|
||||
{file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"},
|
||||
{file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"},
|
||||
{file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"},
|
||||
{file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"},
|
||||
{file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "41.0.5"
|
||||
|
@ -297,6 +332,16 @@ files = [
|
|||
{file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cycler"
|
||||
version = "0.12.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Composable style cycles"
|
||||
files = [
|
||||
{file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"},
|
||||
{file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "decorator"
|
||||
version = "5.1.1"
|
||||
|
@ -371,6 +416,32 @@ files = [
|
|||
{file = "fiona-1.9.5.tar.gz", hash = "sha256:99e2604332caa7692855c2ae6ed91e1fffdf9b59449aa8032dd18e070e59a2f7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fonttools"
|
||||
version = "4.50.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Tools to manipulate font files"
|
||||
files = [
|
||||
{file = "fonttools-4.50.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3dfb102e7f63b78c832e4539969167ffcc0375b013080e6472350965a5fe8048"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e58fe34cb379ba3d01d5d319d67dd3ce7ca9a47ad044ea2b22635cd2d1247fc"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c673ab40d15a442a4e6eb09bf007c1dda47c84ac1e2eecbdf359adacb799c24"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b3ac35cdcd1a4c90c23a5200212c1bb74fa05833cc7c14291d7043a52ca2aaa"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8844e7a2c5f7ecf977e82eb6b3014f025c8b454e046d941ece05b768be5847ae"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f849bd3c5c2249b49c98eca5aaebb920d2bfd92b3c69e84ca9bddf133e9f83f0"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-win32.whl", hash = "sha256:39293ff231b36b035575e81c14626dfc14407a20de5262f9596c2cbb199c3625"},
|
||||
{file = "fonttools-4.50.0-cp311-cp311-win_amd64.whl", hash = "sha256:c33d5023523b44d3481624f840c8646656a1def7630ca562f222eb3ead16c438"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b4a886a6dbe60100ba1cd24de962f8cd18139bd32808da80de1fa9f9f27bf1dc"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b2ca1837bfbe5eafa11313dbc7edada79052709a1fffa10cea691210af4aa1fa"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0493dd97ac8977e48ffc1476b932b37c847cbb87fd68673dee5182004906828"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77844e2f1b0889120b6c222fc49b2b75c3d88b930615e98893b899b9352a27ea"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3566bfb8c55ed9100afe1ba6f0f12265cd63a1387b9661eb6031a1578a28bad1"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:35e10ddbc129cf61775d58a14f2d44121178d89874d32cae1eac722e687d9019"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-win32.whl", hash = "sha256:cc8140baf9fa8f9b903f2b393a6c413a220fa990264b215bf48484f3d0bf8710"},
|
||||
{file = "fonttools-4.50.0-cp312-cp312-win_amd64.whl", hash = "sha256:0ccc85fd96373ab73c59833b824d7a73846670a0cb1f3afbaee2b2c426a8f931"},
|
||||
{file = "fonttools-4.50.0-py3-none-any.whl", hash = "sha256:48fa36da06247aa8282766cfd63efff1bb24e55f020f29a335939ed3844d20d3"},
|
||||
{file = "fonttools-4.50.0.tar.gz", hash = "sha256:fa5cf61058c7dbb104c2ac4e782bf1b2016a8cf2f69de6e4dd6a865d2c969bb5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geoalchemy2"
|
||||
version = "0.14.3"
|
||||
|
@ -508,6 +579,95 @@ files = [
|
|||
{file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kiwisolver"
|
||||
version = "1.4.5"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A fast implementation of the Cassowary constraint solver"
|
||||
files = [
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"},
|
||||
{file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"},
|
||||
{file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"},
|
||||
{file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"},
|
||||
{file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"},
|
||||
{file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"},
|
||||
{file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"},
|
||||
{file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"},
|
||||
{file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"},
|
||||
{file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"},
|
||||
{file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"},
|
||||
{file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"},
|
||||
{file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"},
|
||||
{file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"},
|
||||
{file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"},
|
||||
{file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"},
|
||||
{file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"},
|
||||
{file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"},
|
||||
{file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib"
|
||||
version = "3.8.3"
|
||||
requires_python = ">=3.9"
|
||||
summary = "Python plotting package"
|
||||
dependencies = [
|
||||
"contourpy>=1.0.1",
|
||||
"cycler>=0.10",
|
||||
"fonttools>=4.22.0",
|
||||
"kiwisolver>=1.3.1",
|
||||
"numpy<2,>=1.21",
|
||||
"packaging>=20.0",
|
||||
"pillow>=8",
|
||||
"pyparsing>=2.3.1",
|
||||
"python-dateutil>=2.7",
|
||||
]
|
||||
files = [
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900"},
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e"},
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7"},
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65"},
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0"},
|
||||
{file = "matplotlib-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7"},
|
||||
{file = "matplotlib-3.8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39"},
|
||||
{file = "matplotlib-3.8.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e"},
|
||||
{file = "matplotlib-3.8.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc"},
|
||||
{file = "matplotlib-3.8.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26"},
|
||||
{file = "matplotlib-3.8.3.tar.gz", hash = "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matplotlib-inline"
|
||||
version = "0.1.6"
|
||||
|
@ -680,6 +840,64 @@ files = [
|
|||
{file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "10.2.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python Imaging Library (Fork)"
|
||||
files = [
|
||||
{file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"},
|
||||
{file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"},
|
||||
{file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"},
|
||||
{file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"},
|
||||
{file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"},
|
||||
{file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"},
|
||||
{file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotly"
|
||||
version = "5.20.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "An open-source, interactive data visualization library for Python"
|
||||
dependencies = [
|
||||
"packaging",
|
||||
"tenacity>=6.2.0",
|
||||
]
|
||||
files = [
|
||||
{file = "plotly-5.20.0-py3-none-any.whl", hash = "sha256:837a9c8aa90f2c0a2f0d747b82544d014dc2a2bdde967b5bb1da25b53932d1a9"},
|
||||
{file = "plotly-5.20.0.tar.gz", hash = "sha256:bf901c805d22032cfa534b2ff7c5aa6b0659e037f19ec1e0cca7f585918b5c89"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty-errors"
|
||||
version = "1.2.25"
|
||||
|
@ -865,6 +1083,16 @@ files = [
|
|||
{file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.1.2"
|
||||
requires_python = ">=3.6.8"
|
||||
summary = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
files = [
|
||||
{file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"},
|
||||
{file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyproj"
|
||||
version = "3.6.1"
|
||||
|
@ -1178,6 +1406,16 @@ files = [
|
|||
{file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tenacity"
|
||||
version = "8.2.3"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Retry code until it succeeds"
|
||||
files = [
|
||||
{file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"},
|
||||
{file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traitlets"
|
||||
version = "5.14.0"
|
||||
|
|
|
@ -27,6 +27,8 @@ dependencies = [
|
|||
"websockets>=12.0",
|
||||
"aiosqlite>=0.19.0",
|
||||
"psycopg>=3.1.18",
|
||||
"plotly>=5.20.0",
|
||||
"matplotlib>=3.8.3",
|
||||
]
|
||||
requires-python = ">=3.11,<4"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__: str = '2023.4.dev51+g15fe7fa.d20240318'
|
||||
__version__: str = '2023.4.dev53+gd539a72.d20240320'
|
|
@ -1,6 +1,7 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
from json import dumps
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, APIRouter, HTTPException, status, responses
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
@ -14,8 +15,8 @@ from gisaf.database import fastapi_db_session as db_session
|
|||
from gisaf.models.authentication import User
|
||||
from gisaf.models.dashboard import (
|
||||
DashboardPage, DashboardPageSection,
|
||||
DashboadPageSectionType, DashboardPage_,
|
||||
DashboardGroup, DashboardHome,
|
||||
DashboardPageMetaData,
|
||||
DashboardGroup, DashboardHome, Dashboard, DashboardSection
|
||||
)
|
||||
from gisaf.models.misc import NotADataframeError
|
||||
from gisaf.security import get_current_active_user
|
||||
|
@ -46,10 +47,12 @@ async def get_groups(
|
|||
) -> list[DashboardGroup]:
|
||||
query = select(DashboardPage)
|
||||
data = await db_session.exec(query)
|
||||
groups: dict[str, DashboardPage_] = {}
|
||||
groups: dict[str, DashboardPageMetaData] = {}
|
||||
for page in data.all():
|
||||
page_field = DashboardPage_(name=page.name, group=page.group,
|
||||
description=page.description)
|
||||
page_field = DashboardPageMetaData(name=page.name, group=page.group,
|
||||
description=page.description,
|
||||
viewable_role=page.viewable_role
|
||||
)
|
||||
group = groups.get(page.group)
|
||||
if group is None:
|
||||
group = DashboardGroup(name=page.group, pages=[page_field])
|
||||
|
@ -80,9 +83,10 @@ async def get_home() -> DashboardHome:
|
|||
async def get_dashboard_page(group: str, name: str,
|
||||
db_session: db_session,
|
||||
user: User = Depends(get_current_active_user),
|
||||
) -> DashboardPage_:
|
||||
query1 = select(DashboardPage).where((DashboardPage.name==name)
|
||||
& (DashboardPage.group==group))
|
||||
) -> Dashboard:
|
||||
query1 = select(DashboardPage).\
|
||||
options(selectinload(DashboardPage.sections)).\
|
||||
where((DashboardPage.name==name) & (DashboardPage.group==group))
|
||||
data1 = await db_session.exec(query1)
|
||||
page = data1.one_or_none()
|
||||
if not page:
|
||||
|
@ -98,7 +102,7 @@ async def get_dashboard_page(group: str, name: str,
|
|||
username = user.username if user is not None else "Anonymous"
|
||||
logger.info(f'{username} tried to access dashboard page {name}')
|
||||
raise HTTPException(status.HTTP_401_UNAUTHORIZED)
|
||||
dp = DashboardPage_(
|
||||
dp = Dashboard(
|
||||
name=page.name,
|
||||
group=page.group,
|
||||
description=page.description,
|
||||
|
@ -111,7 +115,7 @@ async def get_dashboard_page(group: str, name: str,
|
|||
for p in page.expanded_panes.split(',')
|
||||
] if page.expanded_panes else [],
|
||||
sections=[
|
||||
DashboadPageSectionType(
|
||||
DashboardSection(
|
||||
name=dps.name,
|
||||
plot=dps.get_plot_url()
|
||||
)
|
||||
|
@ -126,7 +130,7 @@ async def get_dashboard_page(group: str, name: str,
|
|||
if isinstance(df, gpd.GeoDataFrame):
|
||||
gdf = pd.DataFrame(df.drop(columns=['geometry']))
|
||||
df = gdf
|
||||
dp.dfData = df.to_json(orient='table', double_precision=2)
|
||||
dp.dfData = df.reset_index().to_dict(orient='records')
|
||||
except NotADataframeError:
|
||||
logger.warning(f'Dashboard: cannot read dataframe for page {page.name}')
|
||||
except Exception as err:
|
||||
|
|
|
@ -21,7 +21,7 @@ from gisaf.models.info import (LegendItem, ModelAction, ModelInfo,
|
|||
TagActions)
|
||||
from gisaf.models.measures import MeasuresItem
|
||||
from gisaf.models.survey import Equipment, SurveyMeta, Surveyor
|
||||
from gisaf.config import Survey, conf
|
||||
from gisaf.config import conf
|
||||
from gisaf.models.bootstrap import BootstrapData
|
||||
from gisaf.models.store import Store, StoreNameOnly
|
||||
from gisaf.models.project import Project
|
||||
|
@ -29,14 +29,12 @@ from gisaf.models.authentication import UserRoleLink #, ACL
|
|||
from gisaf.database import pandas_query, fastapi_db_session as db_session
|
||||
from gisaf.security import (
|
||||
Token,
|
||||
authenticate_user, get_current_user, create_access_token,
|
||||
authenticate_user, get_current_active_user, create_access_token,
|
||||
)
|
||||
from gisaf.registry import registry, NotInRegistry
|
||||
from gisaf.custom_store_base import BaseStore
|
||||
from gisaf.redis_tools import store as redis_store
|
||||
from gisaf.models.info import (
|
||||
FeatureInfo, InfoItem, Attachment, InfoCategory
|
||||
)
|
||||
from gisaf.models.info import FeatureInfo
|
||||
from gisaf.live_utils import get_live_feature_info
|
||||
from gisaf.plugins import manager as plugin_manager, NoSuchAction
|
||||
from gisaf.utils import gisTypeSymbolMap
|
||||
|
@ -53,7 +51,7 @@ api = APIRouter(
|
|||
|
||||
@api.get('/bootstrap')
|
||||
async def bootstrap(
|
||||
user: Annotated[UserRead, Depends(get_current_user)]) -> BootstrapData:
|
||||
user: Annotated[UserRead, Depends(get_current_active_user)]) -> BootstrapData:
|
||||
return BootstrapData(user=user)
|
||||
|
||||
|
||||
|
@ -78,7 +76,7 @@ async def login_for_access_token(
|
|||
|
||||
@api.get('/logout')
|
||||
async def logout(
|
||||
user: Annotated[UserRead, Depends(get_current_user)]):
|
||||
user: Annotated[UserRead, Depends(get_current_active_user)]):
|
||||
logger.info(f'{user.username} ({user.id}) logged out')
|
||||
|
||||
|
||||
|
@ -100,7 +98,7 @@ async def get_roles(
|
|||
|
||||
@api.get('/acls')
|
||||
async def get_acls(db_session: db_session,
|
||||
user: Annotated[User, Depends(get_current_user)]) -> list[UserRoleLink]:
|
||||
user: Annotated[User, Depends(get_current_active_user)]) -> list[UserRoleLink]:
|
||||
"""New: ACLs returned as UserRoleLink"""
|
||||
if not user or not user.has_role('manager'):
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||
|
|
|
@ -3,8 +3,10 @@ from pickle import loads
|
|||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import logging
|
||||
# from typing import Any
|
||||
|
||||
from sqlmodel import Field, Relationship, String
|
||||
from matplotlib.figure import Figure
|
||||
from sqlmodel import Field, Relationship, String, JSON
|
||||
from pydantic import BaseModel
|
||||
import pandas as pd
|
||||
|
||||
|
@ -13,12 +15,10 @@ from gisaf.models.metadata import gisaf
|
|||
from gisaf.models.models_base import Model
|
||||
from gisaf.models.misc import NotADataframeError
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
except ImportError:
|
||||
plt = None # type: ignore
|
||||
|
||||
|
||||
class DashboardPageSource(Model, table=True):
|
||||
|
@ -34,17 +34,26 @@ class DashboardPageCommon:
|
|||
Base class for DashboardPage and DashboardPageSection, where some methods
|
||||
are common, eg. attachments
|
||||
"""
|
||||
name: str
|
||||
df: bytes
|
||||
plot: bytes
|
||||
#plot: dict[str, Any] | None = Field(sa_type=JSON(none_as_null=True)) # type: ignore
|
||||
attachment: str | None
|
||||
html: str | None = None
|
||||
|
||||
def get_attachment_url(self):
|
||||
## Serve through web front-end (nginx static file)
|
||||
if not self.attachment:
|
||||
return
|
||||
base_storage_url = conf.dashboard.base_storage_url
|
||||
if not base_storage_url:
|
||||
base_storage_url = '/dashboard-attachment/'
|
||||
return f'{base_storage_url}{self.group}/{self.attachment}'
|
||||
def ensure_dir_exists(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def save_plot(self, plot):
|
||||
def get_plot_file_path(self) -> Path:
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_attachment_file_name(self) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_plot_file_name(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def save_plot(self, plot: plt.Axes | plt.Figure): # type: ignore
|
||||
"""
|
||||
Render the matplotlib plot (or figure) and save it in the filesystem
|
||||
:param plot: matplotlib plot or figure...
|
||||
|
@ -53,15 +62,14 @@ class DashboardPageCommon:
|
|||
self.ensure_dir_exists()
|
||||
|
||||
## Different types of figures supported
|
||||
fig = None
|
||||
if plt:
|
||||
if isinstance(plot, plt.Axes):
|
||||
fig = plot.figure
|
||||
elif isinstance(plot, plt.Figure):
|
||||
fig = plot
|
||||
if fig:
|
||||
fig.savefig(self.get_plot_file_path(), bbox_inches='tight')
|
||||
plt.close(fig)
|
||||
fig: Figure | None = None
|
||||
if isinstance(plot, plt.Axes): # type: ignore
|
||||
fig = plot.figure # type: ignore
|
||||
elif isinstance(plot, plt.Figure): # type: ignore
|
||||
fig = plot
|
||||
if fig:
|
||||
fig.savefig(self.get_plot_file_path(), bbox_inches='tight')
|
||||
plt.close(fig)
|
||||
|
||||
if plot and not fig:
|
||||
logger.warning('Cannot save dashboard attachment (unknown attachment type)')
|
||||
|
@ -71,7 +79,7 @@ class DashboardPageCommon:
|
|||
#f'in {self.get_attachment_file_name()}')
|
||||
return self.get_plot_file_name()
|
||||
|
||||
def save_attachment(self, attached, name=None):
|
||||
def save_attachment(self, attached, name=None) -> str | None:
|
||||
"""
|
||||
Save the attachment in the filesystem
|
||||
:param attached: matplotlib plot or figure...
|
||||
|
@ -84,11 +92,11 @@ class DashboardPageCommon:
|
|||
self.ensure_dir_exists()
|
||||
|
||||
## Different types of figures supported
|
||||
fig = None
|
||||
fig: Figure | None = None
|
||||
if plt:
|
||||
if isinstance(attached, plt.Axes):
|
||||
fig = attached.figure
|
||||
elif isinstance(attached, plt.Figure):
|
||||
if isinstance(attached, plt.Axes): # type: ignore
|
||||
fig = attached.figure # type: ignore
|
||||
elif isinstance(attached, plt.Figure): # type: ignore
|
||||
fig = attached
|
||||
if fig:
|
||||
fig.savefig(self.get_attachment_file_name(), bbox_inches='tight')
|
||||
|
@ -96,7 +104,7 @@ class DashboardPageCommon:
|
|||
|
||||
if attached and not fig:
|
||||
logger.warning('Cannot save dashboard attachment (unknown attachment type)')
|
||||
return
|
||||
return None
|
||||
|
||||
#logger.info(f'Saved attachment of dashboard page {self.group}/{self.name} '
|
||||
#f'in {self.get_attachment_file_name()}')
|
||||
|
@ -114,10 +122,18 @@ class DashboardPageCommon:
|
|||
raise NotADataframeError()
|
||||
|
||||
def get_plot(self):
|
||||
return loads(self.plot)
|
||||
if self.plot is not None:
|
||||
return loads(self.plot)
|
||||
|
||||
|
||||
class DashboardPage(Model, DashboardPageCommon, table=True):
|
||||
class DashboardPageMetaData(BaseModel):
|
||||
name: str
|
||||
group: str
|
||||
description: str
|
||||
viewable_role: str | None = None
|
||||
|
||||
|
||||
class DashboardPage(Model, DashboardPageCommon, DashboardPageMetaData, table=True):
|
||||
__tablename__ = 'dashboard_page' # type: ignore
|
||||
__table_args__ = gisaf.table_args
|
||||
|
||||
|
@ -125,19 +141,12 @@ class DashboardPage(Model, DashboardPageCommon, table=True):
|
|||
menu = 'Dashboard'
|
||||
|
||||
id: int = Field(primary_key=True)
|
||||
name: str
|
||||
notebook: str
|
||||
group: str
|
||||
description: str
|
||||
attachment: str
|
||||
html: str
|
||||
viewable_role: str
|
||||
df: bytes
|
||||
plot: bytes
|
||||
source_id: int = Field(foreign_key=gisaf.table('dashboard_page_source.id'))
|
||||
time: datetime
|
||||
expanded_panes: str
|
||||
time: datetime | None = Field(default_factory=datetime.now)
|
||||
notebook: str | None = None
|
||||
source_id: int | None = Field(foreign_key=gisaf.table('dashboard_page_source.id'))
|
||||
expanded_panes: str | None
|
||||
source: DashboardPageSource = Relationship()
|
||||
sections: list['DashboardPageSection'] = Relationship()
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.group:s}/{self.name:s}'
|
||||
|
@ -169,6 +178,15 @@ class DashboardPage(Model, DashboardPageCommon, table=True):
|
|||
else:
|
||||
raise UserWarning('Cannot save attachment: no notebook/base_storage_dir in gisaf config')
|
||||
|
||||
def get_attachment_url(self):
|
||||
## Serve through web front-end (nginx static file)
|
||||
if not self.attachment:
|
||||
return
|
||||
base_storage_url = conf.dashboard.base_storage_url
|
||||
if not base_storage_url:
|
||||
base_storage_url = '/dashboard-attachment/'
|
||||
return f'{base_storage_url}{self.group}/{self.attachment}'
|
||||
|
||||
def get_notebook_url(self):
|
||||
if self.notebook:
|
||||
base_url = conf.dashboard.base_source_url
|
||||
|
@ -188,13 +206,9 @@ class DashboardPageSection(Model, DashboardPageCommon, table=True):
|
|||
id: str = Field(primary_key=True)
|
||||
name: str
|
||||
dashboard_page_id: int = Field(foreign_key=gisaf.table('dashboard_page.id'))
|
||||
dashboard_page: DashboardPage = Relationship()
|
||||
dashboard_page: DashboardPage = Relationship(back_populates='sections')
|
||||
|
||||
description: str
|
||||
attachment: str
|
||||
html: str
|
||||
df: bytes
|
||||
plot: str
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.name} for dashboard page #{self.dashboard_page_id}'
|
||||
|
@ -266,28 +280,28 @@ class Widget(Model, table=True):
|
|||
menu = 'Dashboard'
|
||||
|
||||
|
||||
class DashboadPageSectionType(BaseModel):
|
||||
class DashboardSection(BaseModel):
|
||||
name: str
|
||||
plot: str
|
||||
|
||||
|
||||
class DashboardPage_(BaseModel):
|
||||
class Dashboard(BaseModel):
|
||||
name: str
|
||||
group: str
|
||||
description: str
|
||||
time: datetime | None = Field(default_factory=datetime.now)
|
||||
html: str | None = None
|
||||
attachment: str | None = None
|
||||
dfData: str | None = None
|
||||
dfData: list = []
|
||||
plotData: str | None = None
|
||||
notebook: str | None = None
|
||||
expandedPanes: list[str] | None = None
|
||||
sections: list[DashboadPageSectionType] | None = None
|
||||
sections: list[DashboardSection] | None = None
|
||||
|
||||
|
||||
class DashboardGroup(BaseModel):
|
||||
name: str
|
||||
pages: list[DashboardPage_]
|
||||
pages: list[DashboardPageMetaData]
|
||||
|
||||
|
||||
class DashboardHome(BaseModel):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue