mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-02-15 19:19:42 +00:00
Compare commits
11 Commits
63a2f6d47b
...
combine-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfaeb41080 | ||
|
|
16671c6e1e | ||
|
|
0cd75cb313 | ||
|
|
b2c16cefad | ||
|
b1a2859f1b
|
|||
|
dc71c2de62
|
|||
| 8863d86ed0 | |||
|
|
6550ed2318 | ||
|
|
c9759a6339 | ||
|
|
b637c4e452 | ||
|
|
8986b94b07 |
17
Pipfile
17
Pipfile
@@ -21,7 +21,8 @@ dj-static = "~=0.0.6"
|
||||
Django = "~=3.2"
|
||||
django-debug-toolbar = "~=3.2"
|
||||
django-filter = "~=2.4.0"
|
||||
django-ical = "~=1.8.3"
|
||||
django-ical = "~=1.7.1"
|
||||
django-recurrence = "~=1.10.3"
|
||||
django-registration-redux = "~=2.9"
|
||||
django-reversion = "~=3.0.9"
|
||||
django-widget-tweaks = "~=1.4.8"
|
||||
@@ -75,6 +76,7 @@ django-hCaptcha = "*"
|
||||
importlib-metadata = "*"
|
||||
django-hcaptcha = "*"
|
||||
"z3c.rml" = "*"
|
||||
pikepdf = "*"
|
||||
django-queryable-properties = "*"
|
||||
django-mass-edit = "*"
|
||||
selenium = "~=3.141.0"
|
||||
@@ -89,11 +91,14 @@ pluggy = "*"
|
||||
pytest-splinter = "*"
|
||||
pytest = "*"
|
||||
pytest-reverse = "*"
|
||||
pytest-xdist = {extras = [ "psutil",], version = "*"}
|
||||
PyPOM = {extras = [ "splinter",], version = "*"}
|
||||
|
||||
[requires]
|
||||
python_version = "3.10"
|
||||
python_version = "3.9"
|
||||
|
||||
[pipenv]
|
||||
allow_prereleases = true
|
||||
[dev-packages.pytest-xdist]
|
||||
extras = [ "psutil",]
|
||||
version = "*"
|
||||
|
||||
[dev-packages.PyPOM]
|
||||
extras = [ "splinter",]
|
||||
version = "*"
|
||||
|
||||
517
Pipfile.lock
generated
517
Pipfile.lock
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "96e25ba04c8709eba5d40776ff20cb82e3abecfd9916b8bd9dd4c594d46e2098"
|
||||
"sha256": "2e2fb4b609c10fc42db6bbd69ca73800629fbcaceec664e1fcc79d4b37bc0eb1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.10"
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
@@ -155,11 +155,11 @@
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
|
||||
"sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
|
||||
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
|
||||
"sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2022.12.7"
|
||||
"version": "==2023.5.7"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
@@ -193,6 +193,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"cssselect2": {
|
||||
"hashes": [
|
||||
"sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a",
|
||||
"sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"cssutils": {
|
||||
"hashes": [
|
||||
"sha256:a2fcf06467553038e98fea9cfe36af2bf14063eb147a70958cfcaa8f5786acaf",
|
||||
@@ -233,11 +241,11 @@
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121",
|
||||
"sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d"
|
||||
"sha256:031365bae96814da19c10706218c44dff3b654cc4de20a98bd2d29b9bde469f0",
|
||||
"sha256:21cc991466245d659ab79cb01204f9515690f8dae00e5eabde307f14d24d4d7d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2.16"
|
||||
"version": "==3.2.19"
|
||||
},
|
||||
"django-debug-toolbar": {
|
||||
"hashes": [
|
||||
@@ -272,11 +280,11 @@
|
||||
},
|
||||
"django-ical": {
|
||||
"hashes": [
|
||||
"sha256:0d5595c5bc954e401b59b27a9a86962557f0d3b965e9f5860244cd6bc450e8ab",
|
||||
"sha256:d3f97d163c03ea795e0722d5031e7f3806037ac913c814b0cfee54464f06978e"
|
||||
"sha256:6df4dc61eb4abc55816bd16a949e497bea99828c7de648438ace7f1f85eeb405",
|
||||
"sha256:bd5c874d2eb81329f220174cc0dde7be385f4574ce6c8a2d1579d7fd564a94f3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.8.3"
|
||||
"version": "==1.7.3"
|
||||
},
|
||||
"django-mass-edit": {
|
||||
"hashes": [
|
||||
@@ -296,11 +304,11 @@
|
||||
},
|
||||
"django-recurrence": {
|
||||
"hashes": [
|
||||
"sha256:0c65f30872599b5813a9bab6952dada23c55894f28674490a753ada559f14bc5",
|
||||
"sha256:9c89444e651a78c587f352c5f63eda48ab2f53996347b9fcdff2d248f4fcff70"
|
||||
"sha256:715f681f6af029ff3a8d73c7b1460abd8cbc5d5a5001efcb127032e84d9cb963",
|
||||
"sha256:9053b44b78b7fbfe3530673edfdd6d2f562105f8a192bc6a4b906a3df4f95f59"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.11.1"
|
||||
"index": "pypi",
|
||||
"version": "==1.10.3"
|
||||
},
|
||||
"django-registration-redux": {
|
||||
"hashes": [
|
||||
@@ -392,6 +400,7 @@
|
||||
"sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947",
|
||||
"sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1",
|
||||
"sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd",
|
||||
"sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3",
|
||||
"sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92",
|
||||
"sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3",
|
||||
"sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457",
|
||||
@@ -417,6 +426,7 @@
|
||||
"sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de",
|
||||
"sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f",
|
||||
"sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b",
|
||||
"sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5",
|
||||
"sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7",
|
||||
"sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a",
|
||||
"sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c",
|
||||
@@ -522,11 +532,11 @@
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3",
|
||||
"sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"
|
||||
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
|
||||
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==22.0"
|
||||
"version": "==23.1"
|
||||
},
|
||||
"pep517": {
|
||||
"hashes": [
|
||||
@@ -538,42 +548,45 @@
|
||||
},
|
||||
"pikepdf": {
|
||||
"hashes": [
|
||||
"sha256:005e6908ab572cde909873ca5177013c066167567a3ae53520e0fe5b1197f8f0",
|
||||
"sha256:1495449007b34985409650f1f99bd9d469a1c1d90d43dd576aee2ad60c7788ab",
|
||||
"sha256:28803e1b730ffa65e4668baefc8a602c2d6f620f1caea6cb25672b15b1e9473b",
|
||||
"sha256:37370179e4f742623f08c6d7d70322ee167be8605053eb6f23ad6135fecea9db",
|
||||
"sha256:38107a9048cd6a6b0146b7227e6acef11a0c6975f61fe9a14020e226fb88ec27",
|
||||
"sha256:40a649c71ec36795ee9d487024fbcc2f483b868ef37a5398dc49a3c6823fbbcf",
|
||||
"sha256:4acbf4e711ce93e8130f38ede1e497d5fe35b4c1eaa8628ffa1ca21284b66d4e",
|
||||
"sha256:4c331fc1bb8ffdb5f04502610d1f010fffceea122d9f8429c35e4e0207afc36b",
|
||||
"sha256:78c5c9476edf890e4bb078c446a86f676ff78f49fc33d2f10cac90affe84a1b3",
|
||||
"sha256:799e981f03718a9d9a7db1467121e987f21582925c049287572c9f982f8d77ea",
|
||||
"sha256:7b59f96e8ce9faa35e1ebce662cf33ad33a3351bd6026136c849170876139ca0",
|
||||
"sha256:7e461cc756765544b85cec43b2af99609732d27680bb96e6fc9c81b2d27944cc",
|
||||
"sha256:80f31a4565e17f5f65dc38f1a5b41d469cc7ce1449b32c2a1fb36cccc746a99a",
|
||||
"sha256:87c7ca31ab818121edd4d9f12d81c1b56f61eec56ada1644d68ec8b10bf27622",
|
||||
"sha256:87d04107a048537ca132b88e12b4a9d1236362ccd0d3351b80da42f31fcfcda5",
|
||||
"sha256:897c0bc83c03b8e65153afb482a790d4b0e7adf603bc11de6293aff3c123a457",
|
||||
"sha256:8c8a622c2bd82b4e86fd174f5739abd95872733d0d50760d664a5abcc5b5b533",
|
||||
"sha256:96eb80ce4f9661987033b73bf0106cf7cc804745e8381436cda7f5cc7224b8b5",
|
||||
"sha256:980d49f443f872728cfab76d56c5a330b049e58c5e47354281fb410dde81c1ad",
|
||||
"sha256:9e25cb1efb4242080f8bed1d51f7541a39b8124df8342ef01970e8fa69a7594b",
|
||||
"sha256:a43f8d8d389d7b5999a5ef76623fa88ec54791ad746d77409ec6956ce8de6a34",
|
||||
"sha256:a68da2e0be0264442eead7fa1e63aab63a491c80ba9c5eee527ff99ec5883bcc",
|
||||
"sha256:ac0ef9a15d125157955f5001d3eaf7dc62f37863d2172e12434b9efad4b89bf0",
|
||||
"sha256:acc9f49f3b45f158295c7539268d88d00b41f660d4aa42dd507a1469ce81f0eb",
|
||||
"sha256:b4b05498f2d80478302cdece2385ff4b4ce62874f883622a52f0efee8cfdb68e",
|
||||
"sha256:bb7a7da762976e43ff96cdb3056997280ba47b45ac319cce89a709f34c24ed58",
|
||||
"sha256:bda12c977eaee121c34c0d3869a0cd87c95c42ee3c5b9e1c5a66b88c8beb3886",
|
||||
"sha256:c42eef99232f6aef231466bf9ebeddc47f81784e7e04df25ba6dce482f45ee0b",
|
||||
"sha256:c80d5455965171ad60db38e1a10e063a03e40e4549f8d616c186bfdfcc40475a",
|
||||
"sha256:de30dbf6e847bbac7df424d98e550a97ab0cea9b327eddc95d4c26350b20022b",
|
||||
"sha256:e2252fb75f6b8b6441b880505e8f2484492821b8f3c8a94e628b8104bbeeb66f",
|
||||
"sha256:ecd7ada50e556d6364553f80106e05a3fc11dcba5e45337684e85108d18e8560",
|
||||
"sha256:fffdfd4535952756b1f078fa98be5c3da06728f2afc9dff39aed56419a5d1bf6"
|
||||
"sha256:08ca2566c3ddcb633bbfb90c9e2b7134f222ab48f642f056c266fd69a4c0844e",
|
||||
"sha256:15eff12d7b5dc4eeeb9fbe5148d5e93cdc9f632a352d7df5191409837cdada6f",
|
||||
"sha256:24717a49cab8cf0ccb360ae38fefe4b09e23d394086ef6da740071165a2542d8",
|
||||
"sha256:2c1a3a1ae0d787a6819ffb9d456b0ccbf2b8d48ad8b0748f765a6a306b92184b",
|
||||
"sha256:2c653bc771cc6065642f5a734ecb771ff16b5412cf05a5c3435072ac01f84fbe",
|
||||
"sha256:2e9c9cc68bc123b88007b321a494ab054c3ce378ee2f77bba1b90c8bdaaad59e",
|
||||
"sha256:32a7775f8b2117e72fa101427edf4526f0886e785146a7bfdf2a877d27f94dbf",
|
||||
"sha256:4675c743ac873d8a1ff9d06c1d5fab15e9ca66aa1abf73fcbca4b86c976b214e",
|
||||
"sha256:4800fd878876d9a780e2d1125e971d680a0de466440bd6bcbc54ac7cfb925fd6",
|
||||
"sha256:5b1271b200ece3e16ffa97c76ff93c057d3676f2ecee89ae52efd5e4804874ab",
|
||||
"sha256:5b1c975d02e75aa8a0e09679ed23f85b6eddf91ac7c85189dc18f1ef8599ce70",
|
||||
"sha256:5b295d9579081ab46ce7bb463eccbc62e0c60cbe546f29c0a9135abd5cf76a24",
|
||||
"sha256:5f040aa7d9327b6d9087848dc8e35d2b8515bf17a04e2bdb20f8c51931810213",
|
||||
"sha256:62d724e37a2f004f63615513d3f877334e679dd43b6c55cdfe9b8af56ff52400",
|
||||
"sha256:6452fa9d10b15bb60b2343b7ac08123e0c5b87f852250538d32bf556f09b8c3a",
|
||||
"sha256:66679ee6b364b3b9659a72697e053554e2f4c231371173745b59114f00a821e5",
|
||||
"sha256:6b21fde29bd006cb0889e05a0407f0825b5650ae22272ba70720fc68a2e44a0e",
|
||||
"sha256:788df6789df19a381976f6644b78a65da92c5d4fd45714682a1cffb0cd3ff410",
|
||||
"sha256:7a6de8d04df3dc4f37ddbdfdbecdb4c3d20d479699260902ec06fa531cbfbae6",
|
||||
"sha256:80a4546f59bb38121c20fc37305a388b8f9d561c6bbcc77a3415afdd8a7ab16d",
|
||||
"sha256:856e527970fa2516858662906173004568a38f95b46ef95c8231c529f3e71581",
|
||||
"sha256:8874d4d38b2da71837352576c5ec10c03b2a7976124b95721564d8c456c9824b",
|
||||
"sha256:913437609c3e5b9109a2fe1100f52bdcead4e56e8c83ca8a9c3b520cd7720016",
|
||||
"sha256:91fd023805733163927ae04b16d48374f04f03f204f2cfa45d442b052314de83",
|
||||
"sha256:9d9fe5e3fbd54a45fe7678c08d24c1e8347a1e48adcb4f32c6c25ef380f056ca",
|
||||
"sha256:a98fcebb4303b8b2f5cde0d56f2406a53e74a9ad4bc1e1bc12bdc2b3dd4def1f",
|
||||
"sha256:aa7d3831fa016634f2ead255717644ba2dddf462117b8558b783ac2ba94583bb",
|
||||
"sha256:ae0ba99841d80107becaec6ed067b63c455f51a9bb83b0e88efd3a098753735b",
|
||||
"sha256:b77e2e134315d25dd004b4ffbd2d5032352da164b21bc3bd92768379610fa2b5",
|
||||
"sha256:c5a2710aacb1fa25edd77feba51dcadf85a9b735f2190e8b45edf0e1e79b5d1d",
|
||||
"sha256:c768e55caf96024218866a5b5f95fdded2ef001b2d5463d1c89e57d07bdab928",
|
||||
"sha256:d55b1d8eb3b17e55682b91c042c48e2d0c67be4c1e30b7e539a82e03977eed29",
|
||||
"sha256:d57a35b3ed3f8ef98aa528d4981d1376ccc1ba64ab937f2ac2ed0aadee1d5911",
|
||||
"sha256:e35110f69406e5b9cf6330d16106877372f6aa955fdc1a920d53babcd6a5ae3d",
|
||||
"sha256:e3ff858d504312ea07519121d3ecdf1b5bc40541f957d2b85d271a2ca6284b70",
|
||||
"sha256:f721cd86d8ddf0624306fcd1fed3e086387fcb2e32baeafbd1ba92a7c40c5563"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==6.2.6"
|
||||
"index": "pypi",
|
||||
"version": "==6.2.5"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
@@ -861,19 +874,19 @@
|
||||
},
|
||||
"sentry-sdk": {
|
||||
"hashes": [
|
||||
"sha256:3c9bc64025976842c1103cd75d45cff94a7c0cc48fa07770d07a09d2ab8dac30",
|
||||
"sha256:dc0fe6ef2f77a3853b399c75c97d87be7666098817c1c314f8fcdf68a6865914"
|
||||
"sha256:675f6279b6bb1fea09fd61751061f9a90dca3b5929ef631dd50dc8b3aeb245e9",
|
||||
"sha256:8b4ff696c0bdcceb3f70bbb87a57ba84fd3168b1332d493fcd16c137f709578c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.12.0"
|
||||
"version": "==1.11.1"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54",
|
||||
"sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"
|
||||
"sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b",
|
||||
"sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==65.6.3"
|
||||
"version": "==67.7.2"
|
||||
},
|
||||
"simplejson": {
|
||||
"hashes": [
|
||||
@@ -980,6 +993,13 @@
|
||||
"index": "pypi",
|
||||
"version": "==0.3"
|
||||
},
|
||||
"svglib": {
|
||||
"hashes": [
|
||||
"sha256:3ae765d3a9409ee60c0fb4d24c2deb6a80617aa927054f5bcd7fc98f0695e587"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.5.1"
|
||||
},
|
||||
"tini": {
|
||||
"hashes": [
|
||||
"sha256:8062be51e6766c15ec402579fff422d8c2fb46bdb3f0b22bd009f32d8dd79c81",
|
||||
@@ -988,6 +1008,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"tinycss2": {
|
||||
"hashes": [
|
||||
"sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847",
|
||||
"sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.2.1"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
@@ -1045,11 +1073,11 @@
|
||||
},
|
||||
"z3c.rml": {
|
||||
"hashes": [
|
||||
"sha256:547370b5083a8d79b49e8dde03ac9a12818d9a1c4577a0a9e9bc4b0eccc925b7",
|
||||
"sha256:d5d6fec99c3e909cd6305d04fb53b3923685db942abe56e85815629b6f841298"
|
||||
"sha256:100b62a3978a9acbd2d1a043d4c5b1e2e29601dc687a19b604a95570da6af94f",
|
||||
"sha256:a8064fd06581e45fa208ff02707834744b3b776d4e399bc1fcd5f2217b8ecdd1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.2.1"
|
||||
"version": "==4.3.0"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
@@ -1251,86 +1279,166 @@
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"attrs": {
|
||||
"async-generator": {
|
||||
"hashes": [
|
||||
"sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6",
|
||||
"sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"
|
||||
"sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b",
|
||||
"sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==22.1.0"
|
||||
"version": "==1.10"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04",
|
||||
"sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==23.1.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
|
||||
"sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
|
||||
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
|
||||
"sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2022.12.7"
|
||||
"version": "==2023.5.7"
|
||||
},
|
||||
"chardet": {
|
||||
"charset-normalizer": {
|
||||
"hashes": [
|
||||
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
||||
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
||||
"sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6",
|
||||
"sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1",
|
||||
"sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e",
|
||||
"sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373",
|
||||
"sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62",
|
||||
"sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230",
|
||||
"sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be",
|
||||
"sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c",
|
||||
"sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0",
|
||||
"sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448",
|
||||
"sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f",
|
||||
"sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649",
|
||||
"sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d",
|
||||
"sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0",
|
||||
"sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706",
|
||||
"sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a",
|
||||
"sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59",
|
||||
"sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23",
|
||||
"sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5",
|
||||
"sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb",
|
||||
"sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e",
|
||||
"sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e",
|
||||
"sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c",
|
||||
"sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28",
|
||||
"sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d",
|
||||
"sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41",
|
||||
"sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974",
|
||||
"sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce",
|
||||
"sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f",
|
||||
"sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1",
|
||||
"sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d",
|
||||
"sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8",
|
||||
"sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017",
|
||||
"sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31",
|
||||
"sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7",
|
||||
"sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8",
|
||||
"sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e",
|
||||
"sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14",
|
||||
"sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd",
|
||||
"sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d",
|
||||
"sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795",
|
||||
"sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b",
|
||||
"sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b",
|
||||
"sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b",
|
||||
"sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203",
|
||||
"sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f",
|
||||
"sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19",
|
||||
"sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1",
|
||||
"sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a",
|
||||
"sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac",
|
||||
"sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9",
|
||||
"sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0",
|
||||
"sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137",
|
||||
"sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f",
|
||||
"sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6",
|
||||
"sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5",
|
||||
"sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909",
|
||||
"sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f",
|
||||
"sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0",
|
||||
"sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324",
|
||||
"sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755",
|
||||
"sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb",
|
||||
"sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854",
|
||||
"sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c",
|
||||
"sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60",
|
||||
"sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84",
|
||||
"sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0",
|
||||
"sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b",
|
||||
"sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1",
|
||||
"sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531",
|
||||
"sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1",
|
||||
"sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11",
|
||||
"sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326",
|
||||
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
|
||||
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.0"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:00858a6213ea829ab417b6e05ac0a4c22eac7d3aae67c0187de2935d0548786b",
|
||||
"sha256:08fd9ad5dfc490b7403027b20eebb8ac470621ae1ce0b33a13cab9ec8d4aed0a",
|
||||
"sha256:0c52c8f0243a2e4c0b81db2f6468a9084dd380e0b69e931253aa24529eb812f3",
|
||||
"sha256:0e857ef99769a54595c8801086e310dabb8205a1e742d66f6702544aeddfb1ba",
|
||||
"sha256:1b1cca186e74d258d983a1e1a134ffba0b991effbc8e46ee65c5fbf4009dfce1",
|
||||
"sha256:1dcb5c17b361b35d2a339c6031417f8dcce915b09ea55e7214a398833ec9a63f",
|
||||
"sha256:22cca1925841e2655ce35a4e17c21b42dd0de2b85c5d6fe9c5bf4a45f58950f3",
|
||||
"sha256:25ab1d4ae4bce324d427732bf0f7967493405daa0c2675385016102b0a5e87bf",
|
||||
"sha256:2ca9c7735da025b0f0ca00ab15c5290798b62a49feaf312cb895ab4c4bc1575e",
|
||||
"sha256:3008ace59d566e110e9351c855c6bf2f2b4037f772caffdfaa977c485bf96e8e",
|
||||
"sha256:3de7363b0f21ac6fc97767f78036b900006e06eadd3cc72f040d57494405f44c",
|
||||
"sha256:409d14e37de692f94689578cbbb0a26408da9d9354f8ff658e148f1750940b2f",
|
||||
"sha256:425ba4ae75be4e2c9ce336a523265e6e1214ad624e8d18fb638771475dec2ebf",
|
||||
"sha256:42d7ee01583d4db8098510d08e7505db0f5dbb70edc88a7350cafc336ae81048",
|
||||
"sha256:4e07fc0e0dc8bdeae4f23b8ff821c711dcb2537bbc782f61ff726ca07fcfdb9b",
|
||||
"sha256:4f32113f131edcd26266b8bfc9e24698b6dee4d9ea63362b7dd3cf0a351231a6",
|
||||
"sha256:539ca9a37aaab0ed31ccb535039e33170cf2144b8cd5006c48ad724ba2ab5797",
|
||||
"sha256:572867facf73374a9c8686691bf1b43abe3425f31a2a9b48043d0de9f669ad0d",
|
||||
"sha256:583f5b9a414fcabe1c14d82519b9d24dfd69c3505e9030415c3c6b692bff9062",
|
||||
"sha256:590411083d46c182e852e879a533fa99988937a3af96f836cacbc16a1bcfd058",
|
||||
"sha256:5a0bc8377854cc2f447093149bc9774b0628e9db218f85026d7982466840040e",
|
||||
"sha256:5f3ee269b6d32913eccd78eefce6da7d5120d8fbef059c463c028267c1a0d1ce",
|
||||
"sha256:639bc5e8cf323a50d17b52554269e72c21c2cb5ad14ca1b43e095ce60abbc2b3",
|
||||
"sha256:644b9c4e7e951aa210a8150b09f9c02dcea8701d14bff1564a50e054ce0ae48d",
|
||||
"sha256:6591db6f6bbd5120c9475fdb12305a3216355ae4797b0e44528040f6d0d8f73f",
|
||||
"sha256:7538a24505abb5dc61ac3bbf58d5232a76ad6fd2be63cf797c2e1caa9c60077c",
|
||||
"sha256:75598efc204f513cc4d5ca99a8f9103867993c091e5cd62d78c1020a0affc7be",
|
||||
"sha256:7911833a156476096d209569cbe600faf22a057a46c5e8bb19fffc387abad101",
|
||||
"sha256:7f96cd694673191583acaef50ed01c8db3b47f49602b7046a15775fa6f753e9f",
|
||||
"sha256:89230ec0b1f3817237a8f98fc593dec061eebd753cea097772e7abcf5fb9c6bc",
|
||||
"sha256:959d65e8c5f84878a741dcddcbf71ccc22270c6981e5dfe0806517d49be0c1f2",
|
||||
"sha256:98220679df217b9635c3c6a7a490c408f4de169c33ac4f708a86f9e97b2d9b14",
|
||||
"sha256:996c74a93f6fac2099c288e709e7d0bcc37f3c700d878d7d52accdcc2b6550bd",
|
||||
"sha256:9ec68b342a82dc821d4384e7a5b266c2b78bc5ec3a59fcadf8e96445f4002366",
|
||||
"sha256:b3b6582423aeece24478028b8c9127cd1392d584dfade6c925421c91710cdad5",
|
||||
"sha256:b48273db5287a185017f2150eb49581245777ba30c6e749bfd5567afcab27c3f",
|
||||
"sha256:c1b862d4718a103cd090b6b91155503574918c498a381a13970e22785c7ae5a3",
|
||||
"sha256:c87885ca7357e85e9e1550d804c7b2c42d6e4e8260849af499fc2b0dfe58962c",
|
||||
"sha256:c976faf3bed96d2b94ee8b005ff26a075cfbc00782b532342119cbd172481f81",
|
||||
"sha256:ca922b6558e1fe09c2ffc772faaa411f94cb47845d366d7aa6a887d934a25200",
|
||||
"sha256:e0101d0cb004db88891ffb87ddfccd93ee76abbe4c0bf784c4214f467d026dd2",
|
||||
"sha256:e7a0f9ab01ccd873d21584ddcad488ad752944f6a9e5bdff1aefbe5289ffd823",
|
||||
"sha256:e83b73d8edf255187388b8d14c0c0df580bbf8e7099060e590915e3fbcf39598",
|
||||
"sha256:e8b80f94e15676dbaa7ce2cef6e5433cdb2427d3d81ea9fe4c3d788fae3bc4a2",
|
||||
"sha256:e9c1a662c837cf9b4b815f977404475b555fafc0fb12ae92667d0cdbf0f3c9eb",
|
||||
"sha256:eb54a60e3819d60de6828b5bd197996f9ecb2306d280bd532a4a4291f3285658",
|
||||
"sha256:efb09e5004fd1e4d05cf433d7ad7a6784d090c0afd68b46e8ef785ae169a31ed",
|
||||
"sha256:f0ae2fd15eedb5f749cd9b3da01087b7dba2f76cc783866459d8b3f3feb7c969",
|
||||
"sha256:f0aefc3015ae4a188dc48f2ea934ddbdf158c8c4b0b3d5691acfdad684857702",
|
||||
"sha256:f47e5f3c5acbc3b843ae89b042faf64b366a4976099813487161ce3c50649db3",
|
||||
"sha256:fd868a0eb8eb35a84847935fe36a5b285fed2e4b99c2b90cf44778fa0e9418e9"
|
||||
"sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79",
|
||||
"sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a",
|
||||
"sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f",
|
||||
"sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a",
|
||||
"sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa",
|
||||
"sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398",
|
||||
"sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba",
|
||||
"sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d",
|
||||
"sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf",
|
||||
"sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b",
|
||||
"sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518",
|
||||
"sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d",
|
||||
"sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795",
|
||||
"sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2",
|
||||
"sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e",
|
||||
"sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32",
|
||||
"sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745",
|
||||
"sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b",
|
||||
"sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e",
|
||||
"sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d",
|
||||
"sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f",
|
||||
"sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660",
|
||||
"sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62",
|
||||
"sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6",
|
||||
"sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04",
|
||||
"sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c",
|
||||
"sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5",
|
||||
"sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef",
|
||||
"sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc",
|
||||
"sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae",
|
||||
"sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578",
|
||||
"sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466",
|
||||
"sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4",
|
||||
"sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91",
|
||||
"sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0",
|
||||
"sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4",
|
||||
"sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b",
|
||||
"sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe",
|
||||
"sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b",
|
||||
"sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75",
|
||||
"sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b",
|
||||
"sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c",
|
||||
"sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72",
|
||||
"sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b",
|
||||
"sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f",
|
||||
"sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e",
|
||||
"sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53",
|
||||
"sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3",
|
||||
"sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84",
|
||||
"sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==6.6.0b1"
|
||||
"version": "==6.5.0"
|
||||
},
|
||||
"coveralls": {
|
||||
"hashes": [
|
||||
@@ -1356,11 +1464,11 @@
|
||||
},
|
||||
"exceptiongroup": {
|
||||
"hashes": [
|
||||
"sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828",
|
||||
"sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"
|
||||
"sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e",
|
||||
"sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"
|
||||
],
|
||||
"markers": "python_version < '3.11'",
|
||||
"version": "==1.0.4"
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"execnet": {
|
||||
"hashes": [
|
||||
@@ -1370,6 +1478,14 @@
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==1.9.0"
|
||||
},
|
||||
"h11": {
|
||||
"hashes": [
|
||||
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
|
||||
"sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.14.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
|
||||
@@ -1380,18 +1496,27 @@
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
|
||||
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
|
||||
"sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
|
||||
"sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"outcome": {
|
||||
"hashes": [
|
||||
"sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672",
|
||||
"sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.2.0"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3",
|
||||
"sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"
|
||||
"sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61",
|
||||
"sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==22.0"
|
||||
"version": "==23.1"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
@@ -1451,6 +1576,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==2.2.4"
|
||||
},
|
||||
"pysocks": {
|
||||
"hashes": [
|
||||
"sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
|
||||
"sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
|
||||
"sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
|
||||
],
|
||||
"version": "==1.7.1"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71",
|
||||
@@ -1500,7 +1633,6 @@
|
||||
"sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": null,
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"requests": {
|
||||
@@ -1521,18 +1653,33 @@
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54",
|
||||
"sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"
|
||||
"sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b",
|
||||
"sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==65.6.3"
|
||||
"version": "==67.7.2"
|
||||
},
|
||||
"sniffio": {
|
||||
"hashes": [
|
||||
"sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101",
|
||||
"sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.3.0"
|
||||
},
|
||||
"sortedcontainers": {
|
||||
"hashes": [
|
||||
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
|
||||
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
|
||||
],
|
||||
"version": "==2.4.0"
|
||||
},
|
||||
"splinter": {
|
||||
"hashes": [
|
||||
"sha256:4a14a9d1f9d1372c64b666627ef4e103d759379bc1a9bde0c487e00d70976b1e",
|
||||
"sha256:616da85a0c99bef00b59e75eb29e2e48162027c68ccb81a12d1dfe6d26209692"
|
||||
"sha256:1f072570c084f5f7e0c685b6b5d93b1a7959da06cb5da4c3b548dc1b3b0757a0",
|
||||
"sha256:ba9603385deb91ffb92b2e0edeed3da58dce3bfa0e0db1a37143c5e64b83ceb2"
|
||||
],
|
||||
"version": "==0.18.1"
|
||||
"version": "==0.19.0"
|
||||
},
|
||||
"tomli": {
|
||||
"hashes": [
|
||||
@@ -1542,6 +1689,22 @@
|
||||
"markers": "python_version < '3.11'",
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"trio": {
|
||||
"hashes": [
|
||||
"sha256:ce68f1c5400a47b137c5a4de72c7c901bd4e7a24fbdebfe9b41de8c6c04eaacf",
|
||||
"sha256:f1dd0780a89bfc880c7c7994519cb53f62aacb2c25ff487001c0052bd721cdf0"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.22.0"
|
||||
},
|
||||
"trio-websocket": {
|
||||
"hashes": [
|
||||
"sha256:0908435e4eecc49d830ae1c4d6c47b978a75f00594a2be2104d58b61a04cdb53",
|
||||
"sha256:af13e9393f9051111300287947ec595d601758ce3d165328e7d36325135a8d62"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==0.10.2"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc",
|
||||
@@ -1550,6 +1713,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==1.26.13"
|
||||
},
|
||||
"wsproto": {
|
||||
"hashes": [
|
||||
"sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065",
|
||||
"sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.2.0"
|
||||
},
|
||||
"zope.component": {
|
||||
"hashes": [
|
||||
"sha256:607628e4c84f7887a69a958542b5c304663e726b73aba0882e3a3f059bff14f3",
|
||||
@@ -1558,22 +1729,6 @@
|
||||
"index": "pypi",
|
||||
"version": "==4.6.2"
|
||||
},
|
||||
"zope.deferredimport": {
|
||||
"hashes": [
|
||||
"sha256:57b2345e7b5eef47efcd4f634ff16c93e4265de3dcf325afc7315ade48d909e1",
|
||||
"sha256:9a0c211df44aa95f1c4e6d2626f90b400f56989180d3ef96032d708da3d23e0a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.3.1"
|
||||
},
|
||||
"zope.deprecation": {
|
||||
"hashes": [
|
||||
"sha256:0d453338f04bacf91bbfba545d8bcdf529aa829e67b705eac8c1a7fdce66e2df",
|
||||
"sha256:f1480b74995958b24ce37b0ef04d3663d2683e5d6debc96726eff18acf4ea113"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.4.0"
|
||||
},
|
||||
"zope.event": {
|
||||
"hashes": [
|
||||
"sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42",
|
||||
@@ -1685,52 +1840,6 @@
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.2.0"
|
||||
},
|
||||
"zope.proxy": {
|
||||
"hashes": [
|
||||
"sha256:00573dfa755d0703ab84bb23cb6ecf97bb683c34b340d4df76651f97b0bab068",
|
||||
"sha256:092049280f2848d2ba1b57b71fe04881762a220a97b65288bcb0968bb199ec30",
|
||||
"sha256:0cbd27b4d3718b5ec74fc65ffa53c78d34c65c6fd9411b8352d2a4f855220cf1",
|
||||
"sha256:17fc7e16d0c81f833a138818a30f366696653d521febc8e892858041c4d88785",
|
||||
"sha256:19577dfeb70e8a67249ba92c8ad20589a1a2d86a8d693647fa8385408a4c17b0",
|
||||
"sha256:207aa914576b1181597a1516e1b90599dc690c095343ae281b0772e44945e6a4",
|
||||
"sha256:219a7db5ed53e523eb4a4769f13105118b6d5b04ed169a283c9775af221e231f",
|
||||
"sha256:2b50ea79849e46b5f4f2b0247a3687505d32d161eeb16a75f6f7e6cd81936e43",
|
||||
"sha256:5903d38362b6c716e66bbe470f190579c530a5baf03dbc8500e5c2357aa569a5",
|
||||
"sha256:5c24903675e271bd688c6e9e7df5775ac6b168feb87dbe0e4bcc90805f21b28f",
|
||||
"sha256:5ef6bc5ed98139e084f4e91100f2b098a0cd3493d4e76f9d6b3f7b95d7ad0f06",
|
||||
"sha256:61b55ae3c23a126a788b33ffb18f37d6668e79a05e756588d9e4d4be7246ab1c",
|
||||
"sha256:63ddb992931a5e616c87d3d89f5a58db086e617548005c7f9059fac68c03a5cc",
|
||||
"sha256:6943da9c09870490dcfd50c4909c0cc19f434fa6948f61282dc9cb07bcf08160",
|
||||
"sha256:6ad40f85c1207803d581d5d75e9ea25327cd524925699a83dfc03bf8e4ba72b7",
|
||||
"sha256:6b44433a79bdd7af0e3337bd7bbcf53dd1f9b0fa66bf21bcb756060ce32a96c1",
|
||||
"sha256:6bbaa245015d933a4172395baad7874373f162955d73612f0b66b6c2c33b6366",
|
||||
"sha256:7007227f4ea85b40a2f5e5a244479f6a6dfcf906db9b55e812a814a8f0e2c28d",
|
||||
"sha256:74884a0aec1f1609190ec8b34b5d58fb3b5353cf22b96161e13e0e835f13518f",
|
||||
"sha256:7d25fe5571ddb16369054f54cdd883f23de9941476d97f2b92eb6d7d83afe22d",
|
||||
"sha256:7e162bdc5e3baad26b2262240be7d2bab36991d85a6a556e48b9dfb402370261",
|
||||
"sha256:814d62678dc3a30f4aa081982d830b7c342cf230ffc9d030b020cb154eeebf9e",
|
||||
"sha256:8878a34c5313ee52e20aa50b03138af8d472bae465710fb954d133a9bfd3c38d",
|
||||
"sha256:a66a0d94e5b081d5d695e66d6667e91e74d79e273eee95c1747717ba9cb70792",
|
||||
"sha256:a69f5cbf4addcfdf03dda564a671040127a6b7c34cf9fe4973582e68441b63fa",
|
||||
"sha256:b00f9f0c334d07709d3f73a7cb8ae63c6ca1a90c790a63b5e7effa666ef96021",
|
||||
"sha256:b6ed71e4a7b4690447b626f499d978aa13197a0e592950e5d7020308f6054698",
|
||||
"sha256:bdf5041e5851526e885af579d2f455348dba68d74f14a32781933569a327fddf",
|
||||
"sha256:be034360dd34e62608419f86e799c97d389c10a0e677a25f236a971b2f40dac9",
|
||||
"sha256:cc8f590a5eed30b314ae6b0232d925519ade433f663de79cc3783e4b10d662ba",
|
||||
"sha256:cd7a318a15fe6cc4584bf3c4426f092ed08c0fd012cf2a9173114234fe193e11",
|
||||
"sha256:cf19b5f63a59c20306e034e691402b02055c8f4e38bf6792c23cad489162a642",
|
||||
"sha256:cfc781ce442ec407c841e9aa51d0e1024f72b6ec34caa8fdb6ef9576d549acf2",
|
||||
"sha256:dea9f6f8633571e18bc20cad83603072e697103a567f4b0738d52dd0211b4527",
|
||||
"sha256:e4a86a1d5eb2cce83c5972b3930c7c1eac81ab3508464345e2b8e54f119d5505",
|
||||
"sha256:e7106374d4a74ed9ff00c46cc00f0a9f06a0775f8868e423f85d4464d2333679",
|
||||
"sha256:e98a8a585b5668aa9e34d10f7785abf9545fe72663b4bfc16c99a115185ae6a5",
|
||||
"sha256:f64840e68483316eb58d82c376ad3585ca995e69e33b230436de0cdddf7363f9",
|
||||
"sha256:f8f4b0a9e6683e43889852130595c8854d8ae237f2324a053cdd884de936aa9b",
|
||||
"sha256:fc45a53219ed30a7f670a6d8c98527af0020e6fd4ee4c0a8fb59f147f06d816c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.3.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ STAGING = env('STAGING', cast=bool, default=False)
|
||||
CI = env('CI', cast=bool, default=False)
|
||||
|
||||
ALLOWED_HOSTS = ['pyrigs.nottinghamtec.co.uk', 'rigs.nottinghamtec.co.uk', 'pyrigs.herokuapp.com']
|
||||
CSRF_TRUSTED_ORIGINS = []
|
||||
|
||||
if STAGING:
|
||||
ALLOWED_HOSTS.append('.herokuapp.com')
|
||||
@@ -36,7 +35,6 @@ if DEBUG:
|
||||
ALLOWED_HOSTS.append('localhost')
|
||||
ALLOWED_HOSTS.append('example.com')
|
||||
ALLOWED_HOSTS.append('127.0.0.1')
|
||||
CSRF_TRUSTED_ORIGINS.append('.preview.app.github.dev')
|
||||
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
if not DEBUG:
|
||||
|
||||
@@ -321,45 +321,60 @@ class OEmbedView(generic.View):
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
def get_info_string(user):
|
||||
user_str = f"by {user.name} " if user else ""
|
||||
time = timezone.now().strftime('%d/%m/%Y %H:%I')
|
||||
return f"[Paperwork generated {user_str}on {time}"
|
||||
|
||||
|
||||
def render_pdf_response(template, context, append_terms):
|
||||
merger = PdfFileMerger()
|
||||
rml = template.render(context)
|
||||
buffer = rml2pdf.parseString(rml)
|
||||
merger.append(PdfFileReader(buffer))
|
||||
buffer.close()
|
||||
|
||||
if append_terms:
|
||||
terms = urllib.request.urlopen(settings.TERMS_OF_HIRE_URL)
|
||||
merger.append(BytesIO(terms.read()))
|
||||
|
||||
merged = BytesIO()
|
||||
merger.write(merged)
|
||||
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
f = context['filename']
|
||||
response['Content-Disposition'] = f'filename="{f}"'
|
||||
response.write(merged.getvalue())
|
||||
return response
|
||||
|
||||
|
||||
class PrintView(generic.View):
|
||||
append_terms = False
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
obj = get_object_or_404(self.model, pk=self.kwargs['pk'])
|
||||
user_str = f"by {self.request.user.name} " if self.request.user is not None else ""
|
||||
time = timezone.now().strftime('%d/%m/%Y %H:%I')
|
||||
object_name = re.sub(r'[^a-zA-Z0-9 \n\.]', '', obj.name)
|
||||
|
||||
context = {
|
||||
'object': obj,
|
||||
'current_user': self.request.user,
|
||||
'object_name': object_name,
|
||||
'info_string': f"[Paperwork generated {user_str}on {time} - {obj.current_version_id}]",
|
||||
'info_string': get_info_string(self.request.user) + f"- {obj.current_version_id}]",
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
def get(self, request, pk):
|
||||
template = get_template(self.template_name)
|
||||
return render_pdf_response(get_template(self.template_name), self.get_context_data(), self.append_terms)
|
||||
|
||||
merger = PdfFileMerger()
|
||||
|
||||
context = self.get_context_data()
|
||||
class PrintListView(generic.ListView):
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['current_user'] = self.request.user
|
||||
context['info_string'] = get_info_string(self.request.user) + "]"
|
||||
return context
|
||||
|
||||
rml = template.render(context)
|
||||
buffer = rml2pdf.parseString(rml)
|
||||
merger.append(PdfFileReader(buffer))
|
||||
buffer.close()
|
||||
|
||||
if self.append_terms:
|
||||
terms = urllib.request.urlopen(settings.TERMS_OF_HIRE_URL)
|
||||
merger.append(BytesIO(terms.read()))
|
||||
|
||||
merged = BytesIO()
|
||||
merger.write(merged)
|
||||
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
f = context['filename']
|
||||
response['Content-Disposition'] = f'filename="{f}"'
|
||||
response.write(merged.getvalue())
|
||||
return response
|
||||
def get(self, request):
|
||||
self.object_list = self.get_queryset()
|
||||
return render_pdf_response(get_template(self.template_name), self.get_context_data(), False)
|
||||
|
||||
@@ -124,22 +124,6 @@ class EventForm(forms.ModelForm):
|
||||
'purchase_order', 'collector']
|
||||
|
||||
|
||||
class SubhireForm(forms.ModelForm):
|
||||
related_models = {
|
||||
'person': models.Person,
|
||||
'organisation': models.Organisation,
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['start_date'].widget.format = '%Y-%m-%d'
|
||||
self.fields['end_date'].widget.format = '%Y-%m-%d'
|
||||
|
||||
class Meta:
|
||||
model = models.Subhire
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class BaseClientEventAuthorisationForm(forms.ModelForm):
|
||||
tos = forms.BooleanField(required=True, label="Terms of hire")
|
||||
name = forms.CharField(label="Your Name")
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# Generated by Django 3.2.16 on 2022-12-16 14:41
|
||||
|
||||
import RIGS.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import versioning.versioning
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('RIGS', '0045_alter_profile_is_approved'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Subhire',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255)),
|
||||
('description', models.TextField(blank=True, default='')),
|
||||
('status', models.IntegerField(choices=[(0, 'Provisional'), (1, 'Confirmed'), (2, 'Booked'), (3, 'Cancelled')], default=0)),
|
||||
('start_date', models.DateField()),
|
||||
('start_time', models.TimeField(blank=True, null=True)),
|
||||
('end_date', models.DateField(blank=True, null=True)),
|
||||
('end_time', models.TimeField(blank=True, null=True)),
|
||||
('purchase_order', models.CharField(blank=True, default='', max_length=255, verbose_name='PO')),
|
||||
('insurance_value', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||
('quote', models.URLField(default='', validators=[RIGS.validators.validate_url])),
|
||||
('events', models.ManyToManyField(to='RIGS.Event')),
|
||||
('organisation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='RIGS.organisation')),
|
||||
('person', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='RIGS.person')),
|
||||
],
|
||||
options={
|
||||
'permissions': [('subhire_finance', 'Can see financial data for subhire - insurance values')],
|
||||
},
|
||||
bases=(models.Model, versioning.versioning.RevisionMixin),
|
||||
),
|
||||
]
|
||||
272
RIGS/models.py
272
RIGS/models.py
@@ -8,7 +8,7 @@ from urllib.parse import urlparse
|
||||
|
||||
import pytz
|
||||
from django import forms
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, F
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -17,10 +17,9 @@ from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.functional import cached_property
|
||||
from reversion import revisions as reversion
|
||||
from reversion.models import Version
|
||||
from versioning.versioning import RevisionMixin
|
||||
|
||||
from .validators import validate_url
|
||||
|
||||
|
||||
def filter_by_pk(filt, query):
|
||||
# try and parse an int
|
||||
@@ -262,15 +261,15 @@ class EventManager(models.Manager):
|
||||
'venue', 'mic')
|
||||
return events
|
||||
|
||||
def active_dry_hires(self):
|
||||
return self.filter(dry_hire=True, start_date__gte=timezone.now(), is_rig=True)
|
||||
|
||||
def rig_count(self):
|
||||
event_count = self.exclude(status=BaseEvent.CANCELLED).filter(
|
||||
event_count = self.filter(
|
||||
(models.Q(start_date__gte=timezone.now(), end_date__isnull=True, dry_hire=False,
|
||||
is_rig=True)) | # Starts after with no end
|
||||
(models.Q(end_date__gte=timezone.now(), dry_hire=False, is_rig=True)) | # Ends after
|
||||
(models.Q(dry_hire=True, start_date__gte=timezone.now(), is_rig=True)) # Active dry hire
|
||||
is_rig=True) & ~models.Q(
|
||||
status=Event.CANCELLED)) | # Starts after with no end
|
||||
(models.Q(end_date__gte=timezone.now(), dry_hire=False, is_rig=True) & ~models.Q(
|
||||
status=Event.CANCELLED)) | # Ends after
|
||||
(models.Q(dry_hire=True, start_date__gte=timezone.now(), is_rig=True) & ~models.Q(
|
||||
status=Event.CANCELLED)) # Active dry hire
|
||||
).count()
|
||||
return event_count
|
||||
|
||||
@@ -305,29 +304,8 @@ class EventManager(models.Manager):
|
||||
return qs
|
||||
|
||||
|
||||
def find_earliest_event_time(event, datetime_list):
|
||||
# If there is no start time defined, pretend it's midnight
|
||||
startTimeFaked = False
|
||||
if event.has_start_time:
|
||||
startDateTime = datetime.datetime.combine(event.start_date, event.start_time)
|
||||
else:
|
||||
startDateTime = datetime.datetime.combine(event.start_date, datetime.time(00, 00))
|
||||
startTimeFaked = True
|
||||
|
||||
# timezoneIssues - apply the default timezone to the naiive datetime
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
startDateTime = tz.localize(startDateTime)
|
||||
datetime_list.append(startDateTime) # then add it to the list
|
||||
|
||||
earliest = min(datetime_list).astimezone(tz) # find the earliest datetime in the list
|
||||
|
||||
# if we faked it & it's the earliest, better own up
|
||||
if startTimeFaked and earliest == startDateTime:
|
||||
return event.start_date
|
||||
return earliest
|
||||
|
||||
|
||||
class BaseEvent(models.Model, RevisionMixin):
|
||||
@reversion.register(follow=['items'])
|
||||
class Event(models.Model, RevisionMixin):
|
||||
# Done to make it much nicer on the database
|
||||
PROVISIONAL = 0
|
||||
CONFIRMED = 1
|
||||
@@ -343,97 +321,31 @@ class BaseEvent(models.Model, RevisionMixin):
|
||||
name = models.CharField(max_length=255)
|
||||
person = models.ForeignKey('Person', null=True, blank=True, on_delete=models.CASCADE)
|
||||
organisation = models.ForeignKey('Organisation', blank=True, null=True, on_delete=models.CASCADE)
|
||||
venue = models.ForeignKey('Venue', blank=True, null=True, on_delete=models.CASCADE)
|
||||
description = models.TextField(blank=True, default='')
|
||||
notes = models.TextField(blank=True, default='')
|
||||
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
|
||||
dry_hire = models.BooleanField(default=False)
|
||||
is_rig = models.BooleanField(default=True)
|
||||
based_on = models.ForeignKey('Event', on_delete=models.SET_NULL, related_name='future_events', blank=True,
|
||||
null=True)
|
||||
|
||||
# Timing
|
||||
start_date = models.DateField()
|
||||
start_time = models.TimeField(blank=True, null=True)
|
||||
end_date = models.DateField(blank=True, null=True)
|
||||
end_time = models.TimeField(blank=True, null=True)
|
||||
|
||||
purchase_order = models.CharField(max_length=255, blank=True, default='', verbose_name='PO')
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
@property
|
||||
def cancelled(self):
|
||||
return (self.status == self.CANCELLED)
|
||||
|
||||
@property
|
||||
def confirmed(self):
|
||||
return (self.status == self.BOOKED or self.status == self.CONFIRMED)
|
||||
|
||||
@property
|
||||
def has_start_time(self):
|
||||
return self.start_time is not None
|
||||
|
||||
@property
|
||||
def has_end_time(self):
|
||||
return self.end_time is not None
|
||||
|
||||
@property
|
||||
def latest_time(self):
|
||||
"""Returns the end of the event - this function could return either a tzaware datetime, or a naiive date object"""
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
endDate = self.end_date
|
||||
if endDate is None:
|
||||
endDate = self.start_date
|
||||
|
||||
if self.has_end_time:
|
||||
endDateTime = datetime.datetime.combine(endDate, self.end_time)
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
endDateTime = tz.localize(endDateTime)
|
||||
|
||||
return endDateTime
|
||||
|
||||
else:
|
||||
return endDate
|
||||
|
||||
@property
|
||||
def length(self):
|
||||
start = self.earliest_time
|
||||
if isinstance(self.earliest_time, datetime.datetime):
|
||||
start = self.earliest_time.date()
|
||||
end = self.latest_time
|
||||
if isinstance(self.latest_time, datetime.datetime):
|
||||
end = self.latest_time.date()
|
||||
return (end - start).days
|
||||
|
||||
def clean(self):
|
||||
errdict = {}
|
||||
if self.end_date and self.start_date > self.end_date:
|
||||
errdict['end_date'] = ["Unless you've invented time travel, the event can't finish before it has started."]
|
||||
|
||||
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
||||
hasStartAndEnd = self.has_start_time and self.has_end_time
|
||||
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
||||
errdict['end_time'] = ["Unless you've invented time travel, the event can't finish before it has started."]
|
||||
return errdict
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.display_id}: {self.name}"
|
||||
|
||||
@reversion.register(follow=['items'])
|
||||
class Event(BaseEvent):
|
||||
mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True,
|
||||
verbose_name="MIC", on_delete=models.CASCADE)
|
||||
venue = models.ForeignKey('Venue', blank=True, null=True, on_delete=models.CASCADE)
|
||||
notes = models.TextField(blank=True, default='')
|
||||
dry_hire = models.BooleanField(default=False)
|
||||
is_rig = models.BooleanField(default=True)
|
||||
based_on = models.ForeignKey('Event', on_delete=models.SET_NULL, related_name='future_events', blank=True,
|
||||
null=True)
|
||||
|
||||
access_at = models.DateTimeField(blank=True, null=True)
|
||||
meet_at = models.DateTimeField(blank=True, null=True)
|
||||
|
||||
# Dry-hire only
|
||||
# Crew management
|
||||
checked_in_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_checked_in', blank=True, null=True,
|
||||
on_delete=models.CASCADE)
|
||||
mic = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='event_mic', blank=True, null=True,
|
||||
verbose_name="MIC", on_delete=models.CASCADE)
|
||||
|
||||
# Monies
|
||||
purchase_order = models.CharField(max_length=255, blank=True, default='', verbose_name='PO')
|
||||
collector = models.CharField(max_length=255, blank=True, default='', verbose_name='collected by')
|
||||
|
||||
# Authorisation request details
|
||||
@@ -483,10 +395,26 @@ class Event(BaseEvent):
|
||||
def total(self):
|
||||
return Decimal(self.sum_total + self.vat).quantize(Decimal('.01'))
|
||||
|
||||
@property
|
||||
def cancelled(self):
|
||||
return (self.status == self.CANCELLED)
|
||||
|
||||
@property
|
||||
def confirmed(self):
|
||||
return (self.status == self.BOOKED or self.status == self.CONFIRMED)
|
||||
|
||||
@property
|
||||
def hs_done(self):
|
||||
return self.riskassessment is not None and len(self.checklists.all()) > 0
|
||||
|
||||
@property
|
||||
def has_start_time(self):
|
||||
return self.start_time is not None
|
||||
|
||||
@property
|
||||
def has_end_time(self):
|
||||
return self.end_time is not None
|
||||
|
||||
@property
|
||||
def earliest_time(self):
|
||||
"""Finds the earliest time defined in the event - this function could return either a tzaware datetime, or a naiive date object"""
|
||||
@@ -500,47 +428,73 @@ class Event(BaseEvent):
|
||||
if self.meet_at:
|
||||
datetime_list.append(self.meet_at)
|
||||
|
||||
earliest = find_earliest_event_time(self, datetime_list)
|
||||
# If there is no start time defined, pretend it's midnight
|
||||
startTimeFaked = False
|
||||
if self.has_start_time:
|
||||
startDateTime = datetime.datetime.combine(self.start_date, self.start_time)
|
||||
else:
|
||||
startDateTime = datetime.datetime.combine(self.start_date, datetime.time(00, 00))
|
||||
startTimeFaked = True
|
||||
|
||||
# timezoneIssues - apply the default timezone to the naiive datetime
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
startDateTime = tz.localize(startDateTime)
|
||||
datetime_list.append(startDateTime) # then add it to the list
|
||||
|
||||
earliest = min(datetime_list).astimezone(tz) # find the earliest datetime in the list
|
||||
|
||||
# if we faked it & it's the earliest, better own up
|
||||
if startTimeFaked and earliest == startDateTime:
|
||||
return self.start_date
|
||||
|
||||
return earliest
|
||||
|
||||
@property
|
||||
def latest_time(self):
|
||||
"""Returns the end of the event - this function could return either a tzaware datetime, or a naiive date object"""
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
endDate = self.end_date
|
||||
if endDate is None:
|
||||
endDate = self.start_date
|
||||
|
||||
if self.has_end_time:
|
||||
endDateTime = datetime.datetime.combine(endDate, self.end_time)
|
||||
tz = pytz.timezone(settings.TIME_ZONE)
|
||||
endDateTime = tz.localize(endDateTime)
|
||||
|
||||
return endDateTime
|
||||
|
||||
else:
|
||||
return endDate
|
||||
|
||||
@property
|
||||
def internal(self):
|
||||
return bool(self.organisation and self.organisation.union_account)
|
||||
|
||||
@property
|
||||
def authorised(self):
|
||||
if self.internal and hasattr(self, 'authorisation'):
|
||||
if self.internal:
|
||||
return self.authorisation.amount == self.total
|
||||
else:
|
||||
return bool(self.purchase_order)
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
if self.cancelled:
|
||||
return "secondary"
|
||||
elif not self.is_rig:
|
||||
return "info"
|
||||
elif not self.mic:
|
||||
return "danger"
|
||||
elif self.confirmed and self.authorised:
|
||||
if self.dry_hire or self.riskassessment:
|
||||
return "success"
|
||||
else:
|
||||
return "warning"
|
||||
else:
|
||||
return "warning"
|
||||
|
||||
objects = EventManager()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('event_detail', kwargs={'pk': self.pk})
|
||||
|
||||
def get_edit_url(self):
|
||||
return reverse('event_update', kwargs={'pk': self.pk})
|
||||
def __str__(self):
|
||||
return f"{self.display_id}: {self.name}"
|
||||
|
||||
def clean(self):
|
||||
errdict = super().clean()
|
||||
errdict = {}
|
||||
if self.end_date and self.start_date > self.end_date:
|
||||
errdict['end_date'] = ['Unless you\'ve invented time travel, the event can\'t finish before it has started.']
|
||||
|
||||
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
||||
hasStartAndEnd = self.has_start_time and self.has_end_time
|
||||
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
||||
errdict['end_time'] = ['Unless you\'ve invented time travel, the event can\'t finish before it has started.']
|
||||
|
||||
if self.access_at is not None:
|
||||
if self.access_at.date() > self.start_date:
|
||||
@@ -601,56 +555,6 @@ class EventAuthorisation(models.Model, RevisionMixin):
|
||||
return f"{self.event.display_id} (requested by {self.sent_by.initials})"
|
||||
|
||||
|
||||
class SubhireManager(models.Manager):
|
||||
def current_events(self):
|
||||
events = self.exclude(status=BaseEvent.CANCELLED).filter(
|
||||
(models.Q(start_date__gte=timezone.now(), end_date__isnull=True)) | # Starts after with no end
|
||||
(models.Q(end_date__gte=timezone.now().date())) # Ends after
|
||||
).order_by('start_date', 'end_date', 'start_time', 'end_time').select_related('person', 'organisation')
|
||||
|
||||
return events
|
||||
|
||||
def event_count(self):
|
||||
event_count = self.exclude(status=BaseEvent.CANCELLED).filter(
|
||||
(models.Q(start_date__gte=timezone.now(), end_date__isnull=True)) | # Starts after with no end
|
||||
(models.Q(end_date__gte=timezone.now()))
|
||||
).count()
|
||||
return event_count
|
||||
|
||||
|
||||
@reversion.register
|
||||
class Subhire(BaseEvent):
|
||||
insurance_value = models.DecimalField(max_digits=10, decimal_places=2) # TODO Validate if this is over notifiable threshold
|
||||
events = models.ManyToManyField(Event)
|
||||
quote = models.URLField(default='', validators=[validate_url])
|
||||
|
||||
|
||||
objects = SubhireManager()
|
||||
|
||||
@property
|
||||
def display_id(self):
|
||||
return f"S{self.pk:05d}"
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
return "purple"
|
||||
|
||||
def get_edit_url(self):
|
||||
return reverse('subhire_update', kwargs={'pk': self.pk})
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('subhire_detail', kwargs={'pk': self.pk})
|
||||
|
||||
@property
|
||||
def earliest_time(self):
|
||||
return find_earliest_event_time(self, [])
|
||||
|
||||
class Meta:
|
||||
permissions = [
|
||||
('subhire_finance', 'Can see financial data for subhire - insurance values')
|
||||
]
|
||||
|
||||
|
||||
class InvoiceManager(models.Manager):
|
||||
def outstanding_invoices(self):
|
||||
# Manual query is the only way I have found to do this efficiently. Not ideal but needs must
|
||||
@@ -777,6 +681,14 @@ class Payment(models.Model, RevisionMixin):
|
||||
return f"payment of £{self.amount}"
|
||||
|
||||
|
||||
def validate_url(value):
|
||||
if not value:
|
||||
return # Required error is done the field
|
||||
obj = urlparse(value)
|
||||
if obj.hostname not in ('nottinghamtec.sharepoint.com'):
|
||||
raise ValidationError('URL must point to a location on the TEC Sharepoint')
|
||||
|
||||
|
||||
@reversion.register
|
||||
class RiskAssessment(models.Model, RevisionMixin):
|
||||
SMALL = (0, 'Small')
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 63 KiB |
@@ -11,6 +11,7 @@
|
||||
<initialize>
|
||||
<color id="LightGray" RGB="#D3D3D3"/>
|
||||
<color id="DarkGray" RGB="#707070"/>
|
||||
<color id="Brand" RGB="#3853a4"/>
|
||||
</initialize>
|
||||
|
||||
<paraStyle name="style.para" fontName="OpenSans" />
|
||||
@@ -27,6 +28,8 @@
|
||||
<paraStyle name="style.times" fontName="OpenSans" fontSize="10" />
|
||||
<paraStyle name="style.head_titles" fontName="OpenSans-Bold" fontSize="10" />
|
||||
<paraStyle name="style.head_numbers" fontName="OpenSans" fontSize="10" />
|
||||
<paraStyle name="style.emheader" fontName="OpenSans" textColor="White" fontSize="12" backColor="Brand" leading="20" borderPadding="4"/>
|
||||
<paraStyle name="style.breakbefore" parent="emheader" pageBreakBefore="1"/>
|
||||
|
||||
<blockTableStyle id="eventSpecifics">
|
||||
<blockValign value="top"/>
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
{% if perms.RIGS.add_event %}
|
||||
<a class="dropdown-item" href="{% url 'event_create' %}"><span class="fas fa-plus"></span>
|
||||
New Event</a>
|
||||
<a class="dropdown-item" href="{% url 'subhire_create' %}"><span class="fas fa-truck"></span>
|
||||
New Subhire</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -1,131 +1,197 @@
|
||||
{% extends 'base_rigs.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static 'js/moment.js' %}"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// set some button listeners
|
||||
$('#today-button').click(function(){ calendar.today(); });
|
||||
$('#go-to-date-input').change(function(){
|
||||
if(moment($('#go-to-date-input').val()).isValid()){
|
||||
document.getElementById('go-to-date-button').classList.remove('disabled');
|
||||
document.getElementById('go-to-date-button').href = "?month=" + moment($('#go-to-date-input').val()).format("YYYY-MM");
|
||||
} else{
|
||||
document.getElementById('go-to-date-button').classList.add('disabled');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block title %}Calendar{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<style>
|
||||
.week {
|
||||
display:grid;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
grid-auto-flow: dense;
|
||||
grid-gap: 2px 10px;
|
||||
border: 1px solid black;
|
||||
height: 8em;
|
||||
align-content: start;
|
||||
max-width: 100%;
|
||||
}
|
||||
<link href="{% static 'css/main.css' %}" rel='stylesheet' />
|
||||
{% endblock %}
|
||||
|
||||
.day {
|
||||
display:contents;
|
||||
}
|
||||
.day-label {
|
||||
grid-row-start: 1;
|
||||
text-align: right;
|
||||
margin:0;
|
||||
font-size: 1em !important;
|
||||
height: 1em;
|
||||
}
|
||||
{% block js %}
|
||||
<script src="{% static 'js/moment.js' %}"></script>
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
<script>
|
||||
viewToUrl = {
|
||||
'timeGridWeek':'week',
|
||||
'timeGridDay':'day',
|
||||
'dayGridMonth':'month'
|
||||
}
|
||||
viewFromUrl = {
|
||||
'week':'timeGridWeek',
|
||||
'day':'timeGridDay',
|
||||
'month':'dayGridMonth'
|
||||
}
|
||||
var calendar; //Need to access it from jquery ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
|
||||
.week-day, .day-label, .event {
|
||||
padding: 4px 10px;
|
||||
}
|
||||
calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
themeSystem: 'bootstrap',
|
||||
aspectRatio: 1.5,
|
||||
eventTimeFormat: {
|
||||
'hour': '2-digit',
|
||||
'minute': '2-digit',
|
||||
'hour12': false
|
||||
},
|
||||
headerToolbar: false,
|
||||
editable: false,
|
||||
dayMaxEventRows: true, // allow "more" link when too many events
|
||||
events: function(fetchInfo, successCallback, failureCallback) {
|
||||
$.ajax({
|
||||
url: '/api/event',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
start: moment(fetchInfo.startStr).format("YYYY-MM-DD[T]HH:mm:ss"),
|
||||
end: moment(fetchInfo.endStr).format("YYYY-MM-DD[T]HH:mm:ss")
|
||||
},
|
||||
success: function(doc) {
|
||||
var events = [];
|
||||
colours = {
|
||||
'Provisional': '#FFE89B',
|
||||
'Confirmed': '#3AB54A' ,
|
||||
'Booked': '#3AB54A' ,
|
||||
'Cancelled': 'grey' ,
|
||||
'non-rig': '#25AAE2'
|
||||
};
|
||||
$(doc).each(function() {
|
||||
end = $(this).attr('latest')
|
||||
allDay = false
|
||||
if(end.indexOf("T") < 0){ //If latest does not contain a time
|
||||
end = moment(end + " 23:59").format("YYYY-MM-DD[T]HH:mm:ss")
|
||||
allDay = true
|
||||
}
|
||||
|
||||
.event {
|
||||
background-color: #CCC;
|
||||
font-size: 0.8em !important;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
thisEvent = {
|
||||
'start': $(this).attr('earliest'),
|
||||
'end': end,
|
||||
'className': 'modal-href',
|
||||
'title': $(this).attr('title'),
|
||||
'url': $(this).attr('url'),
|
||||
'allDay': allDay
|
||||
}
|
||||
|
||||
.event-end {
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
if($(this).attr('is_rig')===true || $(this).attr('status') === "Cancelled"){
|
||||
thisEvent['color'] = colours[$(this).attr('status')];
|
||||
}else{
|
||||
thisEvent['color'] = colours['non-rig'];
|
||||
}
|
||||
events.push(thisEvent);
|
||||
});
|
||||
successCallback(events);
|
||||
}
|
||||
});
|
||||
},
|
||||
datesSet: function(info) {
|
||||
var view = info.view;
|
||||
// Set the title of the view
|
||||
$('#calendar-header').text(view.title);
|
||||
|
||||
.event-start {
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
// Enable/Disable "Today" button as required
|
||||
let $today = $('#today-button');
|
||||
if(moment().isBetween(view.currentStart, view.currentEnd)){
|
||||
//Today is within the current view
|
||||
$today.prop('disabled', true);
|
||||
}else{
|
||||
$today.prop('disabled', false);
|
||||
}
|
||||
|
||||
.week-day {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
// Set active view select button
|
||||
let $month = $('#month-button');
|
||||
let $week = $('#week-button');
|
||||
let $day = $('#day-button');
|
||||
switch(view.type){
|
||||
case 'dayGridMonth':
|
||||
$month.addClass('active');
|
||||
$week.removeClass('active');
|
||||
$day.removeClass('active');
|
||||
break;
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.event {
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
case 'timeGridWeek':
|
||||
$month.removeClass('active');
|
||||
$week.addClass('active');
|
||||
$day.removeClass('active');
|
||||
break;
|
||||
|
||||
[data-span="1"] { grid-column-end: span 1; }
|
||||
[data-span="2"] { grid-column-end: span 2; }
|
||||
[data-span="3"] { grid-column-end: span 3; }
|
||||
[data-span="4"] { grid-column-end: span 4; }
|
||||
[data-span="5"] { grid-column-end: span 5; }
|
||||
[data-span="6"] { grid-column-end: span 6; }
|
||||
[data-span="7"] { grid-column-end: span 7; }
|
||||
|
||||
.day > a {
|
||||
color: inherit !important;
|
||||
text-decoration: inherit !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
case 'timeGridDay':
|
||||
$month.removeClass('active');
|
||||
$week.removeClass('active');
|
||||
$day.addClass('active');
|
||||
break;
|
||||
}
|
||||
history.replaceState(null,null,"{% url 'web_calendar' %}"+viewToUrl[view.type]+'/'+moment(view.currentStart).format('YYYY-MM-DD')+'/');
|
||||
}
|
||||
});
|
||||
calendar.render();
|
||||
});
|
||||
$(document).ready(function() {
|
||||
// set some button listeners
|
||||
$('#next-button').click(function(){ calendar.next(); });
|
||||
$('#prev-button').click(function(){ calendar.prev(); });
|
||||
$('#today-button').click(function(){ calendar.today(); });
|
||||
$('#month-button').click(function(){ calendar.changeView('dayGridMonth'); });
|
||||
$('#week-button').click(function(){ calendar.changeView('timeGridWeek'); });
|
||||
$('#day-button').click(function(){ calendar.changeView('timeGridDay'); });
|
||||
$('#go-to-date-input').change(function(){
|
||||
if(moment($('#go-to-date-input').val()).isValid()){
|
||||
$('#go-to-date-button').prop('disabled', false);
|
||||
} else{
|
||||
$('#go-to-date-button').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
$('#go-to-date-button').click(function(){
|
||||
day = moment($('#go-to-date-input').val());
|
||||
if(day.isValid()){
|
||||
calendar.gotoDate(day.format("YYYY-MM-DD"));
|
||||
} else{
|
||||
alert('Invalid Date');
|
||||
}
|
||||
});
|
||||
{% if view and date %}
|
||||
// Go to the initial settings, if they're valid
|
||||
view = viewFromUrl['{{view}}'];
|
||||
calendar.changeView(view);
|
||||
day = moment('{{date}}');
|
||||
if(day.isValid()){
|
||||
calendar.gotoDate(day.format("YYYY-MM-DD"));
|
||||
} else{
|
||||
console.log('Supplied date is invalid - using default')
|
||||
}
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mb-1">
|
||||
<a class="btn btn-info col-2" href="{% url 'web_calendar' %}?{{ prev_month }}"><span class="fas fa-chevron-left"></span> Previous Month</a>
|
||||
<div class="form-inline col-4">
|
||||
<div class="input-group">
|
||||
<input type="date" id="go-to-date-input" placeholder="Go to date..." class="form-control">
|
||||
<span class="input-group-append">
|
||||
<a class="btn btn-success" id="go-to-date-button">Go!</a>
|
||||
</span>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="pull-left">
|
||||
<span id="calendar-header" class="h2"></span>
|
||||
</div>
|
||||
<div class="form-inline float-right btn-page my-3">
|
||||
<div class="input-group mx-2">
|
||||
<input type="date" class="form-control" id="go-to-date-input" placeholder="Go to date...">
|
||||
<span class="input-group-append">
|
||||
<button class="btn btn-success" id="go-to-date-button" type="button" disabled>Go!</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="btn-group mx-2">
|
||||
<button type="button" class="btn btn-primary" id="today-button">Today</button>
|
||||
</div>
|
||||
<div class="btn-group mx-2">
|
||||
<button type="button" class="btn btn-secondary" id="prev-button"><span class="fas fa-chevron-left"></span></button>
|
||||
<button type="button" class="btn btn-secondary" id="next-button"><span class="fas fa-chevron-right"></span></button>
|
||||
</div>
|
||||
<div class="btn-group ml-2">
|
||||
<button type="button" class="btn btn-light" id="month-button">Month</button>
|
||||
<button type="button" class="btn btn-light" id="week-button">Week</button>
|
||||
<button type="button" class="btn btn-light" id="day-button">Day</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div id='calendar'></div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary col-2" id="today-button">Today</button>
|
||||
<a class="btn btn-info mx-2 col-2" href="{% url 'web_calendar' %}?{{ next_month }}"><span class="fas fa-chevron-right"></span> Next Month</a>
|
||||
</div>
|
||||
|
||||
<div class="week" style="height: 2em;">
|
||||
<div class="week-day">Monday</div>
|
||||
<div class="week-day">Tuesday</div>
|
||||
<div class="week-day">Wednesday</div>
|
||||
<div class="week-day">Thursday</div>
|
||||
<div class="week-day">Friday</div>
|
||||
<div class="week-day">Saturday</div>
|
||||
<div class="week-day">Sunday</div>
|
||||
</div>
|
||||
{% for week in weeks %}
|
||||
<div class="week">
|
||||
{% for day in week %}
|
||||
{% if day.0 != 0 %}
|
||||
<div class="day" id="{{day.0}}">
|
||||
<h3 class="day-label text-muted">{{day.0}}</h3>
|
||||
{{ day.2|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="day"><span style="grid-row-start: 1;"> <span></div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
{% extends 'base_rigs.html' %}
|
||||
|
||||
{% load button from filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Upcoming Events</div>
|
||||
<div class="card-body">{{ rig_count }}</div>
|
||||
<div class="card-footer"><a href={% url 'rigboard' %}>View</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Upcoming Subhire</div>
|
||||
<div class="card-body">{{ subhire_count }}</div>
|
||||
<div class="card-footer"><a href={% url 'subhire_list' %}>View</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Active Dry Hires</div>
|
||||
<div class="card-body">{{ hire_count }}</div>
|
||||
<div class="card-footer"><a href={% url 'rigboard' %}>View</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -25,10 +25,12 @@
|
||||
{% include 'partials/hs_details.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if event.is_rig and event.internal and perms.RIGS.view_event %}
|
||||
<div class="col-md-8 py-3">
|
||||
{% include 'partials/auth_details.html' %}
|
||||
</div>
|
||||
{% if event.is_rig %}
|
||||
{% if event.is_rig and event.internal and perms.RIGS.view_event %}
|
||||
<div class="col-md-8 py-3">
|
||||
{% include 'partials/auth_details.html' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if not request.is_ajax and perms.RIGS.view_event %}
|
||||
<div class="col-sm-12 text-right">
|
||||
@@ -45,15 +47,9 @@
|
||||
<hr>
|
||||
<p class="dont-break-out">{{ event.notes|markdown }}</p>
|
||||
{% endif %}
|
||||
<h4>Event Items</h4>
|
||||
<br>
|
||||
{% include 'partials/item_table.html' %}
|
||||
</div>
|
||||
{% include 'partials/item_table.html' %}
|
||||
{% if event.subhire_set.count > 0 %}
|
||||
<div class="card-body"><h4>Associated Subhires</h4></div>
|
||||
{% with event.subhire_set.all as events %}
|
||||
{% include 'partials/event_table.html' %}
|
||||
{%endwith%}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not request.is_ajax and perms.RIGS.view_event %}
|
||||
|
||||
@@ -106,10 +106,6 @@
|
||||
title="Things that aren't service-based, like training, meetings and site visits.">
|
||||
<button type="button" class="btn btn-info w-25" data-is_rig="0">Non-Rig</button>
|
||||
</span>
|
||||
<span data-toggle="tooltip"
|
||||
title="Record equipment hired in from other companies">
|
||||
<a href="{% url 'subhire_create' %}" class="btn bg-warning w-25">Subhire</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,5 +47,7 @@
|
||||
class="fas fa-pound-sign"></span>
|
||||
<span class="d-none d-sm-inline">Invoice</span></a>
|
||||
{% endif %}
|
||||
|
||||
<a href="https://docs.google.com/forms/d/e/1FAIpQLSf-TBOuJZCTYc2L8DWdAaC3_Werq0ulsUs8-6G85I6pA9WVsg/viewform" class="btn btn-danger"><span class="fas fa-file-invoice-dollar"></span> <span class="d-none d-sm-inline">Subhire Insurance Form</span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,21 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for event in events %}
|
||||
<tr class="table-{{event.color}}" {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
|
||||
<tr class="{% if event.cancelled %}
|
||||
table-secondary
|
||||
{% elif not event.is_rig %}
|
||||
table-info
|
||||
{% elif not event.mic %}
|
||||
table-danger
|
||||
{% elif event.confirmed and event.authorised %}
|
||||
{% if event.dry_hire or event.riskassessment %}
|
||||
table-success
|
||||
{% else %}
|
||||
table-warning
|
||||
{% endif %}
|
||||
{% else %}
|
||||
table-warning
|
||||
{% endif %}" {% if event.cancelled %}style="opacity: 50% !important;"{% endif %} id="event_row">
|
||||
<!---Number-->
|
||||
<th scope="row" id="event_number">{{ event.display_id }}</th>
|
||||
<!--Dates & Times-->
|
||||
@@ -42,7 +56,7 @@
|
||||
<!---Details-->
|
||||
<td id="event_details" class="w-100">
|
||||
<h4>
|
||||
<a href="{{event.get_absolute_url}}">
|
||||
<a href="{% url 'event_detail' event.pk %}">
|
||||
{{ event.name }}
|
||||
</a>
|
||||
{% if event.venue %}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<button type="button" class="btn btn-success btn-sm item-add"
|
||||
data-toggle="modal"
|
||||
data-target="#itemModal">
|
||||
<span class="fas fa-plus"></span> Add Item
|
||||
<i class="fas fa-plus"></i> Add Item
|
||||
</button>
|
||||
</th>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
{% extends request.is_ajax|yesno:"base_ajax.html,base_rigs.html" %}
|
||||
|
||||
{% load markdown_tags %}
|
||||
{% load button from filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row my-3 py-3">
|
||||
<div class="col-sm-12 text-right mb-2">
|
||||
{% button 'edit' 'subhire_update' object.pk %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% include 'partials/contact_details.html' %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card card-default">
|
||||
<div class="card-header">Hire Details</div>
|
||||
<div class="card-body">
|
||||
<dl class="row">
|
||||
<dt class="col-sm-6">Name</dt>
|
||||
<dd class="col-sm-6">{{ object.name }}</dd>
|
||||
<dt class="col-sm-6">Event Starts</dt>
|
||||
<dd class="col-sm-6">{{ object.start_date|date:"D d M Y" }} {{ object.start_time|date:"H:i" }}</dd>
|
||||
|
||||
<dt class="col-sm-6">Event Ends</dt>
|
||||
<dd class="col-sm-6">{{ object.end_date|date:"D d M Y" }} {{ object.end_time|date:"H:i" }}</dd>
|
||||
|
||||
<dt class="col-sm-6">Status</dt>
|
||||
<dd class="col-sm-6">{{ object.get_status_display }}</dd>
|
||||
|
||||
<dt class="col-sm-6">PO</dt>
|
||||
<dd class="col-sm-6">{{ object.po }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mt-2">
|
||||
<div class="card card-default">
|
||||
<div class="card-header">Equipment Information</div>
|
||||
<div class="card-body">
|
||||
<dl class="row">
|
||||
<dt class="col-sm-6">Description</dt>
|
||||
<dd class="col-sm-6">{{ object.description }}</dd>
|
||||
{% if perms.RIGS.subhire_finance %}
|
||||
<dt class="col-sm-6">Insurance Value</dt>
|
||||
<dd class="col-sm-6">£{{ object.insurance_value }}</dd>
|
||||
{% endif %}
|
||||
<dt class="col-sm-6">Quote</dt>
|
||||
<dd class="col-sm-6"><a href="{{ object.quote }}">View</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 mt-2">
|
||||
<div class="card card-default">
|
||||
<div class="card-header">Associated Event(s)</div>
|
||||
{% with object.events.all as events %}
|
||||
{% include 'partials/event_table.html' %}
|
||||
{%endwith%}
|
||||
</div>
|
||||
</div>
|
||||
{% if not request.is_ajax and perms.RIGS.view_event %}
|
||||
<div class="col-sm-12 text-right">
|
||||
{% include 'partials/last_edited.html' with target="event_history" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% if request.is_ajax %}
|
||||
{% block footer %}
|
||||
{% if perms.RIGS.view_event %}
|
||||
{% include 'partials/last_edited.html' with target="event_history" %}
|
||||
{% endif %}
|
||||
<a href="{% url 'subhire_detail' object.pk %}" class="btn btn-primary">Open Event Page <span class="fas fa-eye"></span></a>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
@@ -1,202 +0,0 @@
|
||||
{% extends 'base_rigs.html' %}
|
||||
|
||||
{% load widget_tweaks %}
|
||||
{% load static %}
|
||||
{% load multiply from filters %}
|
||||
{% load button from filters %}
|
||||
|
||||
{% block css %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/selects.css' %}"/>
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/easymde.min.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block preload_js %}
|
||||
{{ block.super }}
|
||||
<script src="{% static 'js/selects.js' %}"></script>
|
||||
<script src="{% static 'js/easymde.min.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ block.super }}
|
||||
<script src="{% static 'js/autocompleter.js' %}"></script>
|
||||
<script src="{% static 'js/interaction.js' %}"></script>
|
||||
<script src="{% static 'js/tooltip.js' %}"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
setupMDE('#id_description');
|
||||
});
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form class="row" role="form" method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="col-12">
|
||||
{% include 'form_errors.html' %}
|
||||
</div>
|
||||
{# Contact details #}
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="card">
|
||||
<div class="card-header">Contact Details</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group" data-toggle="tooltip">
|
||||
<label for="{{ form.person.id_for_label }}">Primary Contact</label>
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
<select id="{{ form.person.id_for_label }}" name="{{ form.person.name }}" class="selectpicker" data-live-search="true" data-sourceurl="{% url 'api_secure' model='person' %}">
|
||||
{% if person %}
|
||||
<option value="{{form.person.value}}" selected="selected" data-update_url="{% url 'person_update' form.person.value %}">{{ person }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-3 align-right">
|
||||
<div class="btn-group">
|
||||
<a href="{% url 'person_create' %}" class="btn btn-success modal-href"
|
||||
data-target="#{{ form.person.id_for_label }}">
|
||||
<span class="fas fa-plus"></span>
|
||||
</a>
|
||||
<a {% if form.person.value %}href="{% url 'person_update' form.person.value %}"{% endif %} class="btn btn-warning modal-href" id="{{ form.person.id_for_label }}-update" data-target="#{{ form.person.id_for_label }}">
|
||||
<span class="fas fa-user-edit"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.organisation.id_for_label }}">Hire Company</label>
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
<select id="{{ form.organisation.id_for_label }}" name="{{ form.organisation.name }}" class="selectpicker" data-live-search="true" data-sourceurl="{% url 'api_secure' model='organisation' %}">
|
||||
{% if organisation %}
|
||||
<option value="{{form.organisation.value}}" selected="selected" data-update_url="{% url 'organisation_update' form.organisation.value %}">{{ organisation }}</option>
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-3 align-right">
|
||||
<div class="btn-group">
|
||||
<a href="{% url 'organisation_create' %}" class="btn btn-success modal-href"
|
||||
data-target="#{{ form.organisation.id_for_label }}">
|
||||
<span class="fas fa-plus"></span>
|
||||
</a>
|
||||
<a {% if form.organisation.value %}href="{% url 'organisation_update' form.organisation.value %}"{% endif %} class="btn btn-warning modal-href" id="{{ form.organisation.id_for_label }}-update" data-target="#{{ form.organisation.id_for_label }}">
|
||||
<span class="fas fa-edit"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="card">
|
||||
<div class="card-header">Associated Event(s)</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<select multiple name="events" id="events_id" class="selectpicker" data-live-search="true" data-sourceurl="{% url 'api_secure' model='event' %}">
|
||||
{% if object.events.count > 0 %}
|
||||
{% for event in object.events.all %}
|
||||
<option value="{{event.id}}" selected>{{ event }}</option>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# Event details #}
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="card card-default">
|
||||
<div class="card-header">Hire Details</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group" data-toggle="tooltip" title="Name of the event, displays on rigboard and on paperwork">
|
||||
<label for="{{ form.name.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.name.label }}</label>
|
||||
<div class="col-sm-8">
|
||||
{% render_field form.name class+="form-control" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.start_date.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.start_date.label }}</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-7" data-toggle="tooltip" title="Start date for event, required">
|
||||
{% render_field form.start_date class+="form-control" %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-5" data-toggle="tooltip" title="Start time of event, can be left blank">
|
||||
{% render_field form.start_time class+="form-control" step="60" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.end_date.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.end_date.label }}</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-7" data-toggle="tooltip" title="End date of event, leave blank if unknown or same as start date">
|
||||
{% render_field form.end_date class+="form-control" %}
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-5" data-toggle="tooltip" title="End time of event, leave blank if unknown">
|
||||
{% render_field form.end_time class+="form-control" step="60" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" data-toggle="tooltip" title="The current status of the event. Only mark as booked once paperwork is received">
|
||||
<label for="{{ form.status.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.status.label }}</label>
|
||||
<div class="col-sm-8">
|
||||
{% render_field form.status class+="form-control" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.purchase_order.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.purchase_order.label }}</label>
|
||||
<div class="col-sm-8">
|
||||
{% render_field form.purchase_order class+="form-control" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="card">
|
||||
<div class="card-header">Equipment Information</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="{{ form.description.id_for_label }}"
|
||||
class="col-sm-4 col-form-label">{{ form.description.label }}</label>
|
||||
<div class="col-sm-12">
|
||||
{% render_field form.description class+="form-control" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.insurance_value.id_for_label }}"
|
||||
class="col-sm-6 col-form-label">{{ form.insurance_value.label }}</label>
|
||||
<div class="col-sm-8 input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text">£</span></div>
|
||||
{% render_field form.insurance_value class+="form-control" %}
|
||||
</div>
|
||||
<div class="border border-info p-2 rounded mt-1 font-weight-bold" style="border-width: thin thin thin thick !important;">
|
||||
If this value is greater than £50,000 then please email productions@nottinghamtec.co.uk in addition to complete the additional insurance requirements
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="{{ form.quote.id_for_label }}" class="col-sm-6 col-form-label">{{ form.quote.label }} (TEC SharePoint link)</label>
|
||||
<div class="col-sm-12">{% render_field form.quote class+="form-control" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 text-right my-3">
|
||||
{% button 'submit' %}
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -196,8 +196,8 @@ def button(type, url=None, pk=None, clazz="", icon=None, text="", id=None, style
|
||||
text = "Edit"
|
||||
elif type == 'print':
|
||||
clazz += " btn-primary "
|
||||
icon = "fa-print"
|
||||
text = "Print"
|
||||
icon = "fa-download"
|
||||
text = "Export"
|
||||
elif type == 'duplicate':
|
||||
clazz += " btn-info "
|
||||
icon = "fa-copy"
|
||||
|
||||
22
RIGS/urls.py
22
RIGS/urls.py
@@ -43,8 +43,12 @@ urlpatterns = [
|
||||
|
||||
# Rigboard
|
||||
path('rigboard/', login_required(views.RigboardIndex.as_view()), name='rigboard'),
|
||||
re_path(r'^rigboard/calendar/$', login_required()(views.WebCalendar.as_view()),
|
||||
path('rigboard/calendar/', login_required()(views.WebCalendar.as_view()),
|
||||
name='web_calendar'),
|
||||
re_path(r'^rigboard/calendar/(?P<view>(month|week|day))/$',
|
||||
login_required()(views.WebCalendar.as_view()), name='web_calendar'),
|
||||
re_path(r'^rigboard/calendar/(?P<view>(month|week|day))/(?P<date>(\d{4}-\d{2}-\d{2}))/$',
|
||||
login_required()(views.WebCalendar.as_view()), name='web_calendar'),
|
||||
path('rigboard/archive/', RedirectView.as_view(permanent=True, pattern_name='event_archive')),
|
||||
|
||||
|
||||
@@ -66,22 +70,6 @@ urlpatterns = [
|
||||
path('event/<int:pk>/duplicate/', permission_required_with_403('RIGS.add_event')(views.EventDuplicate.as_view()),
|
||||
name='event_duplicate'),
|
||||
|
||||
|
||||
# Subhire
|
||||
path('subhire/<int:pk>/', login_required(views.SubhireDetail.as_view()),
|
||||
name='subhire_detail'),
|
||||
path('subhire/create/', permission_required_with_403('RIGS.add_event')(views.SubhireCreate.as_view()),
|
||||
name='subhire_create'),
|
||||
path('subhire/<int:pk>/edit', permission_required_with_403('RIGS.change_event')(views.SubhireEdit.as_view()),
|
||||
name='subhire_update'),
|
||||
path('subhire/upcoming', login_required(views.SubhireList.as_view()),
|
||||
name='subhire_list'),
|
||||
|
||||
# Dashboards
|
||||
path('dashboard/productions/', views.ProductionsDashboard.as_view(),
|
||||
name='productions_dashboard'),
|
||||
|
||||
|
||||
# Event H&S
|
||||
path('event/hs/', permission_required_with_403('RIGS.view_riskassessment')(views.HSList.as_view()), name='hs_list'),
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
from datetime import datetime, timedelta, date
|
||||
import calendar
|
||||
from calendar import HTMLCalendar
|
||||
from RIGS.models import Event, Subhire
|
||||
|
||||
|
||||
class Calendar(HTMLCalendar):
|
||||
def __init__(self, year=None, month=None):
|
||||
self.year = year
|
||||
self.month = month
|
||||
super(Calendar, self).__init__()
|
||||
|
||||
def get_html(self, day, event):
|
||||
return f"<a href='{event.get_absolute_url()}' class='modal-href' style='display: contents;'><div class='event event-start event-end bg-{event.color}' data-span='{event.length}' style='grid-column-start: calc({day[1]} + 1)'>{event}</div></a>"
|
||||
|
||||
def formatmonth(self, withyear=True):
|
||||
events = Event.objects.filter(start_date__year=self.year, start_date__month=self.month)
|
||||
subhires = Subhire.objects.filter(start_date__year=self.year, start_date__month=self.month)
|
||||
weeks = self.monthdays2calendar(self.year, self.month)
|
||||
data = []
|
||||
|
||||
for week in weeks:
|
||||
weeks_events = []
|
||||
for day in week:
|
||||
events_per_day = events.order_by("start_date").filter(start_date__day=day[0])
|
||||
subhires_per_day = subhires.order_by("start_date").filter(start_date__day=day[0])
|
||||
event_html = ""
|
||||
for event in events_per_day:
|
||||
event_html += self.get_html(day, event)
|
||||
for sh in subhires_per_day:
|
||||
event_html += self.get_html(day, sh)
|
||||
weeks_events.append((day[0], day[1], event_html))
|
||||
data.append(weeks_events)
|
||||
return data
|
||||
|
||||
|
||||
def get_date(req_day):
|
||||
if req_day:
|
||||
year, month = (int(x) for x in req_day.split('-'))
|
||||
return date(year, month, day=1)
|
||||
return datetime.today()
|
||||
|
||||
def prev_month(d):
|
||||
first = d.replace(day=1)
|
||||
prev_month = first - timedelta(days=1)
|
||||
month = f'month={str(prev_month.year)}-{str(prev_month.month)}'
|
||||
return month
|
||||
|
||||
def next_month(d):
|
||||
days_in_month = calendar.monthrange(d.year, d.month)[1]
|
||||
last = d.replace(day=days_in_month)
|
||||
next_month = last + timedelta(days=1)
|
||||
month = f'month={str(next_month.year)}-{str(next_month.month)}'
|
||||
return month
|
||||
@@ -1,10 +0,0 @@
|
||||
from urllib.parse import urlparse
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
def validate_url(value):
|
||||
if not value:
|
||||
return # Required error is done the field
|
||||
obj = urlparse(value)
|
||||
if obj.hostname not in ('nottinghamtec.sharepoint.com'):
|
||||
raise ValidationError('URL must point to a location on the TEC Sharepoint')
|
||||
@@ -3,5 +3,3 @@ from .finance import *
|
||||
from .hs import *
|
||||
from .ical import *
|
||||
from .rigboard import *
|
||||
from .subhire import *
|
||||
from .dashboards import *
|
||||
@@ -1,14 +0,0 @@
|
||||
from django.views import generic
|
||||
from RIGS import models
|
||||
|
||||
|
||||
class ProductionsDashboard(generic.TemplateView):
|
||||
template_name = 'dashboards/productions.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['page_title'] = "Productions Dashboard"
|
||||
context['rig_count'] = models.Event.objects.rig_count()
|
||||
context['subhire_count'] = models.Subhire.objects.event_count()
|
||||
context['hire_count'] = models.Event.objects.active_dry_hires().count()
|
||||
return context
|
||||
@@ -2,6 +2,7 @@ import copy
|
||||
import datetime
|
||||
import re
|
||||
import premailer
|
||||
import simplejson
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
@@ -11,7 +12,9 @@ from django.core.exceptions import SuspiciousOperation
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.template.loader import get_template
|
||||
from django.urls import reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
@@ -19,7 +22,7 @@ from django.views import generic
|
||||
|
||||
from PyRIGS import decorators
|
||||
from PyRIGS.views import OEmbedView, is_ajax, ModalURLMixin, PrintView, get_related
|
||||
from RIGS import models, forms, utils
|
||||
from RIGS import models, forms
|
||||
|
||||
__author__ = 'ghost'
|
||||
|
||||
@@ -37,25 +40,14 @@ class RigboardIndex(generic.TemplateView):
|
||||
return context
|
||||
|
||||
|
||||
class WebCalendar(generic.ListView):
|
||||
model = models.Event
|
||||
class WebCalendar(generic.TemplateView):
|
||||
template_name = 'calendar.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
# use today's date for the calendar
|
||||
d = utils.get_date(self.request.GET.get('month', None))
|
||||
context['prev_month'] = utils.prev_month(d)
|
||||
context['next_month'] = utils.next_month(d)
|
||||
|
||||
# Instantiate our calendar class with today's year and date
|
||||
cal = utils.Calendar(d.year, d.month)
|
||||
|
||||
# Call the formatmonth method, which returns our calendar as a table
|
||||
html_cal = cal.formatmonth(withyear=True)
|
||||
# context['calendar'] = mark_safe(html_cal)
|
||||
context['weeks'] = html_cal
|
||||
context['page_title'] = d.strftime("%B %Y")
|
||||
context['view'] = kwargs.get('view', '')
|
||||
context['date'] = kwargs.get('date', '')
|
||||
# context['page_title'] = "Calendar"
|
||||
return context
|
||||
|
||||
|
||||
@@ -69,6 +61,10 @@ class EventDetail(generic.DetailView, ModalURLMixin):
|
||||
if self.object.dry_hire:
|
||||
title += " <span class='badge badge-secondary'>Dry Hire</span>"
|
||||
context['page_title'] = title
|
||||
if is_ajax(self.request):
|
||||
context['override'] = "base_ajax.html"
|
||||
else:
|
||||
context['override'] = 'base_assets.html'
|
||||
return context
|
||||
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
from django.urls import reverse_lazy
|
||||
from django.views import generic
|
||||
from PyRIGS.views import ModalURLMixin, get_related
|
||||
from RIGS import models, forms
|
||||
|
||||
|
||||
class SubhireDetail(generic.DetailView, ModalURLMixin):
|
||||
template_name = 'subhire_detail.html'
|
||||
model = models.Subhire
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['page_title'] = f"{self.object.display_id} | {self.object.name}"
|
||||
return context
|
||||
|
||||
|
||||
class SubhireCreate(generic.CreateView):
|
||||
model = models.Subhire
|
||||
form_class = forms.SubhireForm
|
||||
template_name = 'subhire_form.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['page_title'] = "New Subhire"
|
||||
context['edit'] = True
|
||||
form = context['form']
|
||||
get_related(form, context)
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('subhire_detail', kwargs={'pk': self.object.pk})
|
||||
|
||||
|
||||
class SubhireEdit(generic.UpdateView):
|
||||
model = models.Subhire
|
||||
form_class = forms.SubhireForm
|
||||
template_name = 'subhire_form.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['page_title'] = f"Edit Subhire: {self.object.display_id} | {self.object.name}"
|
||||
context['edit'] = True
|
||||
form = context['form']
|
||||
get_related(form, context)
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('subhire_detail', kwargs={'pk': self.object.pk})
|
||||
|
||||
|
||||
class SubhireList(generic.TemplateView):
|
||||
template_name = 'rigboard.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['events'] = models.Subhire.objects.current_events()
|
||||
context['page_title'] = "Upcoming Subhire"
|
||||
return context
|
||||
@@ -105,8 +105,7 @@ class Command(BaseCommand):
|
||||
|
||||
for i in range(100):
|
||||
prefix = random.choice(asset_prefixes)
|
||||
asset_id = str(get_available_asset_id(wanted_prefix=prefix))
|
||||
asset_id = prefix + asset_id
|
||||
asset_id = get_available_asset_id(wanted_prefix=prefix)
|
||||
asset = models.Asset(
|
||||
asset_id=asset_id,
|
||||
description=random.choice(asset_description),
|
||||
|
||||
@@ -102,7 +102,8 @@ class AssetManager(models.Manager):
|
||||
|
||||
def get_available_asset_id(wanted_prefix=""):
|
||||
last_asset = Asset.objects.filter(asset_id_prefix=wanted_prefix).last()
|
||||
return 9000 if last_asset is None else wanted_prefix + str(last_asset.asset_id_number + 1)
|
||||
last_asset_id = last_asset.asset_id_number if last_asset else 0
|
||||
return wanted_prefix + str(last_asset_id + 1)
|
||||
|
||||
|
||||
def validate_positive(value):
|
||||
|
||||
@@ -168,7 +168,7 @@ class DuplicateMixin:
|
||||
class AssetDuplicate(DuplicateMixin, AssetIDUrlMixin, AssetCreate):
|
||||
def get_initial(self, *args, **kwargs):
|
||||
initial = super().get_initial(*args, **kwargs)
|
||||
initial["asset_id"] = models.get_available_asset_id(wanted_prefix=self.get_object().asset_id_prefix)
|
||||
initial["asset_id"] = models.get_available_asset_id()
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
@@ -24,6 +24,7 @@ function fonts(done) {
|
||||
function styles(done) {
|
||||
const bs_select = ["bootstrap-select.css", "ajax-bootstrap-select.css"]
|
||||
return gulp.src(['pipeline/source_assets/scss/**/*.scss',
|
||||
'node_modules/fullcalendar/main.css',
|
||||
'node_modules/bootstrap-select/dist/css/bootstrap-select.css',
|
||||
'node_modules/ajax-bootstrap-select/dist/css/ajax-bootstrap-select.css',
|
||||
'node_modules/easymde/dist/easymde.min.css'
|
||||
@@ -58,6 +59,7 @@ function scripts() {
|
||||
'node_modules/html5sortable/dist/html5sortable.min.js',
|
||||
'node_modules/clipboard/dist/clipboard.min.js',
|
||||
'node_modules/moment/moment.js',
|
||||
'node_modules/fullcalendar/main.js',
|
||||
'node_modules/bootstrap-select/dist/js/bootstrap-select.js',
|
||||
'node_modules/ajax-bootstrap-select/dist/js/ajax-bootstrap-select.js',
|
||||
'node_modules/easymde/dist/easymde.min.js',
|
||||
|
||||
318
package-lock.json
generated
318
package-lock.json
generated
@@ -19,6 +19,7 @@
|
||||
"clipboard": "^2.0.8",
|
||||
"cssnano": "^5.0.13",
|
||||
"easymde": "^2.16.1",
|
||||
"fullcalendar": "^5.10.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-flatten": "^0.4.0",
|
||||
@@ -37,7 +38,7 @@
|
||||
"uglify-js": "^3.14.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browser-sync": "^2.27.10"
|
||||
"browser-sync": "^2.27.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -279,10 +280,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/cors": {
|
||||
"version": "2.8.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
|
||||
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==",
|
||||
"dev": true
|
||||
"version": "2.8.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz",
|
||||
"integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.0",
|
||||
@@ -300,9 +304,9 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||
"version": "18.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
|
||||
"integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/normalize-package-data": {
|
||||
@@ -1026,13 +1030,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browser-sync": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.10.tgz",
|
||||
"integrity": "sha512-xKm+6KJmJu6RuMWWbFkKwOCSqQOxYe3nOrFkKI5Tr/ZzjPxyU3pFShKK3tWnazBo/3lYQzN7fzjixG8fwJh1Xw==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.11.tgz",
|
||||
"integrity": "sha512-U5f9u97OYJH66T0MGWWzG9rOQTW6ZmDMj97vsmtqwNS03JAwdLVES8eel2lD3rvAqQCNAFqaJ74NMacBI57vJg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"browser-sync-client": "^2.27.10",
|
||||
"browser-sync-ui": "^2.27.10",
|
||||
"browser-sync-client": "^2.27.11",
|
||||
"browser-sync-ui": "^2.27.11",
|
||||
"bs-recipes": "1.3.4",
|
||||
"bs-snippet-injector": "^2.0.1",
|
||||
"chokidar": "^3.5.1",
|
||||
@@ -1050,7 +1054,7 @@
|
||||
"micromatch": "^4.0.2",
|
||||
"opn": "5.3.0",
|
||||
"portscanner": "2.2.0",
|
||||
"qs": "6.2.3",
|
||||
"qs": "^6.11.0",
|
||||
"raw-body": "^2.3.2",
|
||||
"resp-modifier": "6.0.2",
|
||||
"rx": "4.1.0",
|
||||
@@ -1070,9 +1074,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browser-sync-client": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.10.tgz",
|
||||
"integrity": "sha512-KCFKA1YDj6cNul0VsA28apohtBsdk5Wv8T82ClOZPZMZWxPj4Ny5AUbrj9UlAb/k6pdxE5HABrWDhP9+cjt4HQ==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.11.tgz",
|
||||
"integrity": "sha512-okMNfD2NasL/XD1/BclP3onXjhahisk3e/kTQ5HPDT/lLqdBqNDd6QFcjI5I1ak7na2hxKQSLjryql+7fp5gKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"etag": "1.8.1",
|
||||
@@ -1086,9 +1090,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browser-sync-ui": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.10.tgz",
|
||||
"integrity": "sha512-elbJILq4Uo6OQv6gsvS3Y9vRAJlWu+h8j0JDkF0X/ua+3S6SVbbiWnZc8sNOFlG7yvVGIwBED3eaYQ0iBo1Dtw==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.11.tgz",
|
||||
"integrity": "sha512-1T/Y8Pp1R68aUL7zVSFq0nxtr258xWd/nTasCAHX2M6EsGaswVOFtXsw3bKqsr35z+J+LfVfOdz1HFLYKxdgrA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async-each-series": "0.1.1",
|
||||
@@ -2233,9 +2237,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
|
||||
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
|
||||
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
@@ -2247,7 +2251,7 @@
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3"
|
||||
"ws": "~8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -2321,6 +2325,27 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/engine.io/node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
@@ -3062,6 +3087,11 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fullcalendar": {
|
||||
"version": "5.11.3",
|
||||
"resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-5.11.3.tgz",
|
||||
"integrity": "sha512-SgqiMEA+lWLyEd2jEwtIxdfx41j2CZr4KK00D2Gepj1MnGOjaEi13athnU6xvqMQXXjgJNj+vmlUP69QiuGncQ=="
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -4204,9 +4234,9 @@
|
||||
"integrity": "sha512-rmglSaNttGo4LY33PFW51mgeD1ItvHyfS9cRCD+Cj9Msj/xFaG/sZjLGVtPbtxYJmhY/c8jtw6G07yWhC2ifEw=="
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
@@ -5952,6 +5982,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
@@ -6905,12 +6944,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz",
|
||||
"integrity": "sha512-AY4g8t3LMboim0t6XWFdz6J5OuJ1ZNYu54SXihS/OMpgyCqYmcAJnWqkNSOjSjWmq3xxy+GF9uWQI2lI/7tKIA==",
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
@@ -7626,6 +7671,20 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
"object-inspect": "^1.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
@@ -7813,38 +7872,62 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz",
|
||||
"integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==",
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz",
|
||||
"integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.0",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
"engine.io": "~6.4.1",
|
||||
"socket.io-adapter": "~2.5.2",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-adapter": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
|
||||
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==",
|
||||
"dev": true
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz",
|
||||
"integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ws": "~8.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-adapter/node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz",
|
||||
"integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz",
|
||||
"integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.2.3",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
"socket.io-parser": "~4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -8662,9 +8745,9 @@
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@@ -9427,10 +9510,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/cors": {
|
||||
"version": "2.8.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz",
|
||||
"integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==",
|
||||
"dev": true
|
||||
"version": "2.8.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz",
|
||||
"integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "1.0.0",
|
||||
@@ -9448,9 +9534,9 @@
|
||||
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||
"version": "18.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
|
||||
"integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/normalize-package-data": {
|
||||
@@ -9986,13 +10072,13 @@
|
||||
}
|
||||
},
|
||||
"browser-sync": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.10.tgz",
|
||||
"integrity": "sha512-xKm+6KJmJu6RuMWWbFkKwOCSqQOxYe3nOrFkKI5Tr/ZzjPxyU3pFShKK3tWnazBo/3lYQzN7fzjixG8fwJh1Xw==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.11.tgz",
|
||||
"integrity": "sha512-U5f9u97OYJH66T0MGWWzG9rOQTW6ZmDMj97vsmtqwNS03JAwdLVES8eel2lD3rvAqQCNAFqaJ74NMacBI57vJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browser-sync-client": "^2.27.10",
|
||||
"browser-sync-ui": "^2.27.10",
|
||||
"browser-sync-client": "^2.27.11",
|
||||
"browser-sync-ui": "^2.27.11",
|
||||
"bs-recipes": "1.3.4",
|
||||
"bs-snippet-injector": "^2.0.1",
|
||||
"chokidar": "^3.5.1",
|
||||
@@ -10010,7 +10096,7 @@
|
||||
"micromatch": "^4.0.2",
|
||||
"opn": "5.3.0",
|
||||
"portscanner": "2.2.0",
|
||||
"qs": "6.2.3",
|
||||
"qs": "^6.11.0",
|
||||
"raw-body": "^2.3.2",
|
||||
"resp-modifier": "6.0.2",
|
||||
"rx": "4.1.0",
|
||||
@@ -10024,9 +10110,9 @@
|
||||
}
|
||||
},
|
||||
"browser-sync-client": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.10.tgz",
|
||||
"integrity": "sha512-KCFKA1YDj6cNul0VsA28apohtBsdk5Wv8T82ClOZPZMZWxPj4Ny5AUbrj9UlAb/k6pdxE5HABrWDhP9+cjt4HQ==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.11.tgz",
|
||||
"integrity": "sha512-okMNfD2NasL/XD1/BclP3onXjhahisk3e/kTQ5HPDT/lLqdBqNDd6QFcjI5I1ak7na2hxKQSLjryql+7fp5gKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"etag": "1.8.1",
|
||||
@@ -10037,9 +10123,9 @@
|
||||
}
|
||||
},
|
||||
"browser-sync-ui": {
|
||||
"version": "2.27.10",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.10.tgz",
|
||||
"integrity": "sha512-elbJILq4Uo6OQv6gsvS3Y9vRAJlWu+h8j0JDkF0X/ua+3S6SVbbiWnZc8sNOFlG7yvVGIwBED3eaYQ0iBo1Dtw==",
|
||||
"version": "2.27.11",
|
||||
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.11.tgz",
|
||||
"integrity": "sha512-1T/Y8Pp1R68aUL7zVSFq0nxtr258xWd/nTasCAHX2M6EsGaswVOFtXsw3bKqsr35z+J+LfVfOdz1HFLYKxdgrA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-each-series": "0.1.1",
|
||||
@@ -10919,9 +11005,9 @@
|
||||
}
|
||||
},
|
||||
"engine.io": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
|
||||
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
|
||||
"integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/cookie": "^0.4.1",
|
||||
@@ -10933,7 +11019,7 @@
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.0.3",
|
||||
"ws": "~8.2.3"
|
||||
"ws": "~8.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -10950,6 +11036,13 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -11574,6 +11667,11 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fullcalendar": {
|
||||
"version": "5.11.3",
|
||||
"resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-5.11.3.tgz",
|
||||
"integrity": "sha512-SgqiMEA+lWLyEd2jEwtIxdfx41j2CZr4KK00D2Gepj1MnGOjaEi13athnU6xvqMQXXjgJNj+vmlUP69QiuGncQ=="
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -12490,9 +12588,9 @@
|
||||
"integrity": "sha512-rmglSaNttGo4LY33PFW51mgeD1ItvHyfS9cRCD+Cj9Msj/xFaG/sZjLGVtPbtxYJmhY/c8jtw6G07yWhC2ifEw=="
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "2.0.0",
|
||||
@@ -13857,6 +13955,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
"integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
|
||||
"dev": true
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
@@ -14490,10 +14594,13 @@
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz",
|
||||
"integrity": "sha512-AY4g8t3LMboim0t6XWFdz6J5OuJ1ZNYu54SXihS/OMpgyCqYmcAJnWqkNSOjSjWmq3xxy+GF9uWQI2lI/7tKIA==",
|
||||
"dev": true
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"side-channel": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"quick-lru": {
|
||||
"version": "4.0.1",
|
||||
@@ -15057,6 +15164,17 @@
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
||||
},
|
||||
"side-channel": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"call-bind": "^1.0.0",
|
||||
"get-intrinsic": "^1.0.2",
|
||||
"object-inspect": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
@@ -15207,17 +15325,17 @@
|
||||
}
|
||||
},
|
||||
"socket.io": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz",
|
||||
"integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==",
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz",
|
||||
"integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.2.0",
|
||||
"socket.io-adapter": "~2.4.0",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
"engine.io": "~6.4.1",
|
||||
"socket.io-adapter": "~2.5.2",
|
||||
"socket.io-parser": "~4.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -15238,21 +15356,33 @@
|
||||
}
|
||||
},
|
||||
"socket.io-adapter": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz",
|
||||
"integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==",
|
||||
"dev": true
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz",
|
||||
"integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ws": "~8.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"socket.io-client": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz",
|
||||
"integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz",
|
||||
"integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.2.3",
|
||||
"socket.io-parser": "~4.2.0"
|
||||
"socket.io-parser": "~4.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -15879,9 +16009,9 @@
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
|
||||
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true
|
||||
},
|
||||
"typo-js": {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"clipboard": "^2.0.8",
|
||||
"cssnano": "^5.0.13",
|
||||
"easymde": "^2.16.1",
|
||||
"fullcalendar": "^5.10.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-flatten": "^0.4.0",
|
||||
@@ -33,7 +34,7 @@
|
||||
"uglify-js": "^3.14.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browser-sync": "^2.27.10"
|
||||
"browser-sync": "^2.27.11"
|
||||
},
|
||||
"scripts": {
|
||||
"gulp": "gulp",
|
||||
|
||||
@@ -73,6 +73,7 @@ function initPicker(obj) {
|
||||
return array;
|
||||
}
|
||||
};
|
||||
console.log(obj.data);
|
||||
if (!obj.data('noclear')) {
|
||||
obj.prepend($("<option></option>")
|
||||
.attr("value",'')
|
||||
|
||||
@@ -4,16 +4,16 @@ Date.prototype.getISOString = function () {
|
||||
var dd = this.getDate().toString();
|
||||
return yyyy + '-' + (mm[1] ? mm : "0" + mm[0]) + '-' + (dd[1] ? dd : "0" + dd[0]); // padding
|
||||
};
|
||||
$(document).ready(function () {
|
||||
$(document).on('click', '.modal-href', function (e) {
|
||||
$link = $(this);
|
||||
jQuery(document).ready(function () {
|
||||
jQuery(document).on('click', '.modal-href', function (e) {
|
||||
$link = jQuery(this);
|
||||
// Anti modal inception
|
||||
if ($link.parents('#modal').length == 0) {
|
||||
e.preventDefault();
|
||||
modaltarget = $link.data('target');
|
||||
modalobject = "";
|
||||
$('#modal').load($link.attr('href'), function (e) {
|
||||
$('#modal').modal();
|
||||
jQuery('#modal').load($link.attr('href'), function (e) {
|
||||
jQuery('#modal').modal();
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -23,6 +23,7 @@ $(document).ready(function () {
|
||||
s.type = 'text/javascript';
|
||||
document.body.appendChild(s);
|
||||
s.src = '{% static "js/asteroids.min.js"%}';
|
||||
ga('send', 'event', 'easter_egg', 'activated');
|
||||
}
|
||||
easter_egg.load();
|
||||
});
|
||||
|
||||
@@ -281,7 +281,3 @@ html.embedded {
|
||||
.bootstrap-select, button.btn.dropdown-toggle.bs-placeholder.btn-light {
|
||||
padding-right: 1rem !important;
|
||||
}
|
||||
|
||||
.badge-purple, .bg-purple {
|
||||
background-color: #800080 !important;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,15 @@ class Command(BaseCommand):
|
||||
"Bin Diving",
|
||||
"Wiki Editing"]
|
||||
|
||||
descriptions = [
|
||||
"Physical training concentrates on mechanistic goals: training programs in this area develop specific motor skills, agility, strength or physical fitness, often with an intention of peaking at a particular time.",
|
||||
"In military use, training means gaining the physical ability to perform and survive in combat, and learn the many skills needed in a time of war.",
|
||||
"These include how to use a variety of weapons, outdoor survival skills, and how to survive being captured by the enemy, among many others. See military education and training.",
|
||||
"While some studies have indicated relaxation training is useful for some medical conditions, autogenic training has limited results or has been the result of few studies.",
|
||||
"Some occupations are inherently hazardous, and require a minimum level of competence before the practitioners can perform the work at an acceptable level of safety to themselves or others in the vicinity.",
|
||||
"Occupational diving, rescue, firefighting and operation of certain types of machinery and vehicles may require assessment and certification of a minimum acceptable competence before the person is allowed to practice as a licensed instructor."
|
||||
]
|
||||
|
||||
for i, name in enumerate(names):
|
||||
category = random.choice(self.categories)
|
||||
previous_item = models.TrainingItem.objects.filter(category=category).last()
|
||||
@@ -150,7 +159,7 @@ class Command(BaseCommand):
|
||||
number = previous_item.reference_number + 1
|
||||
else:
|
||||
number = 0
|
||||
item = models.TrainingItem.objects.create(category=category, reference_number=number, description=name)
|
||||
item = models.TrainingItem.objects.create(category=category, reference_number=number, name=name, description=random.choice(descriptions) + random.choice(descriptions) + random.choice(descriptions))
|
||||
self.items.append(item)
|
||||
|
||||
def setup_levels(self):
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.18 on 2023-02-19 14:02
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('training', '0005_auto_20220223_1535'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='trainingitem',
|
||||
old_name='description',
|
||||
new_name='name',
|
||||
),
|
||||
]
|
||||
18
training/migrations/0007_trainingitem_description.py
Normal file
18
training/migrations/0007_trainingitem_description.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.18 on 2023-02-19 14:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('training', '0006_rename_description_trainingitem_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='trainingitem',
|
||||
name='description',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
]
|
||||
@@ -85,7 +85,7 @@ class TrainingItemManager(QueryablePropertiesManager):
|
||||
def search(self, query=None):
|
||||
qs = self.get_queryset()
|
||||
if query is not None:
|
||||
or_lookup = (Q(description__icontains=query) | Q(display_id=query))
|
||||
or_lookup = (Q(name__icontains=query) | Q(description__icontains=query) | Q(display_id=query))
|
||||
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups
|
||||
return qs
|
||||
|
||||
@@ -94,16 +94,13 @@ class TrainingItemManager(QueryablePropertiesManager):
|
||||
class TrainingItem(models.Model):
|
||||
reference_number = models.IntegerField()
|
||||
category = models.ForeignKey('TrainingCategory', related_name='items', on_delete=models.CASCADE)
|
||||
description = models.CharField(max_length=50)
|
||||
name = models.CharField(max_length=50)
|
||||
description = models.TextField(blank=True)
|
||||
active = models.BooleanField(default=True)
|
||||
prerequisites = models.ManyToManyField('self', symmetrical=False, blank=True)
|
||||
|
||||
objects = TrainingItemManager()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return str(self)
|
||||
|
||||
@queryable_property
|
||||
def display_id(self):
|
||||
return f"{self.category.reference_number}.{self.reference_number}"
|
||||
@@ -121,7 +118,7 @@ class TrainingItem(models.Model):
|
||||
return models.Q()
|
||||
|
||||
def __str__(self):
|
||||
name = f"{self.display_id} {self.description}"
|
||||
name = f"{self.display_id} {self.name}"
|
||||
if not self.active:
|
||||
name += " (inactive)"
|
||||
return name
|
||||
@@ -149,7 +146,7 @@ class TrainingItemQualificationManager(QueryablePropertiesManager):
|
||||
def search(self, query=None):
|
||||
qs = self.get_queryset().select_related('item', 'supervisor', 'item__category')
|
||||
if query is not None:
|
||||
or_lookup = (Q(item__description__icontains=query) | Q(supervisor__first_name__icontains=query) | Q(supervisor__last_name__icontains=query) | Q(item__category__name__icontains=query) | Q(item__display_id=query))
|
||||
or_lookup = (Q(item__name__icontains=query) | Q(supervisor__first_name__icontains=query) | Q(supervisor__last_name__icontains=query) | Q(item__category__name__icontains=query) | Q(item__display_id=query))
|
||||
|
||||
try:
|
||||
or_lookup = Q(item__category__reference_number=int(query)) | or_lookup
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
{% extends 'base_training.html' %}
|
||||
|
||||
{% load button from filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-12 text-right py-2 pr-0">
|
||||
{% button 'print' 'item_list_export' %}
|
||||
</div>
|
||||
<div id="accordion">
|
||||
{% for category in categories %}
|
||||
<div class="card">
|
||||
@@ -13,10 +18,11 @@
|
||||
<div class="card-body">
|
||||
<div class="list-group list-group-flush">
|
||||
{% for item in category.items.all %}
|
||||
<li class="list-group-item {% if not item.active%}text-warning{%endif%}">{{ item }}
|
||||
<li class="list-group-item {% if not item.active%}text-warning{%endif%}">{{ item }} <a href="{% url 'item_qualification' item.pk %}" class="btn btn-info float-right"><span class="fas fa-user"></span> Qualified Users</a>
|
||||
<br><small>{{ item.description }}</small>
|
||||
{% if item.prerequisites.exists %}
|
||||
<div class="ml-3 font-italic">
|
||||
<p class="text-info mb-0">Passed Out Prerequisites:</p>
|
||||
<p class="text-info mb-0">Competency Assessment Prerequisites:</p>
|
||||
<ul>
|
||||
{% for p in item.prerequisites.all %}
|
||||
<li>{{p}}</li>
|
||||
@@ -24,7 +30,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<a href="{% url 'item_qualification' item.pk %}" class="btn btn-info"><span class="fas fa-user"></span> Qualified Users</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
25
training/templates/item_list.xml
Normal file
25
training/templates/item_list.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
{% extends 'base_print.xml' %}
|
||||
|
||||
{% block content %}
|
||||
<h1 style="page-head">TEC Training Item List</h1>
|
||||
<spacer length="15" />
|
||||
{% for category in categories %}
|
||||
<h2 {% if not forloop.first %}style="breakbefore"{%else%}style="emheader"{%endif%}>{{category}}</h2>
|
||||
<spacer length="10" />
|
||||
{% for item in category.items.all %}
|
||||
<h3>{{ item }}</h3>
|
||||
<spacer length="4" />
|
||||
<para>{{ item.description }}</para>
|
||||
{% if item.prerequisites.exists %}
|
||||
<h4>Competency Assessment Prerequisites:</h4>
|
||||
<ul bulletFontSize="5">
|
||||
{% for p in item.prerequisites.all %}
|
||||
<li><para>{{p}}</para></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<spacer length="8" />
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<namedString id="lastPage"><pageNumber/></namedString>
|
||||
{% endblock %}
|
||||
@@ -8,6 +8,7 @@ from versioning.views import VersionHistory
|
||||
|
||||
urlpatterns = [
|
||||
path('items/', login_required(views.ItemList.as_view()), name='item_list'),
|
||||
path('items/export/', login_required(views.ItemListExport.as_view()), name='item_list_export'),
|
||||
path('item/<int:pk>/qualified_users/', login_required(views.ItemQualifications.as_view()), name='item_qualification'),
|
||||
|
||||
path('trainee/list/', login_required(views.TraineeList.as_view()), name='trainee_list'),
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.db import transaction
|
||||
from django.db.models import Q, Count
|
||||
from django.db.utils import IntegrityError
|
||||
|
||||
from PyRIGS.views import is_ajax, ModalURLMixin, get_related
|
||||
from PyRIGS.views import is_ajax, ModalURLMixin, get_related, PrintListView
|
||||
from training import models, forms
|
||||
from users import views
|
||||
from reversion.views import RevisionMixin
|
||||
@@ -24,6 +24,20 @@ class ItemList(generic.ListView):
|
||||
return context
|
||||
|
||||
|
||||
class ItemListExport(PrintListView):
|
||||
model = models.TrainingItem
|
||||
template_name = 'item_list.xml'
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(active=True)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['filename'] = "TrainingItemList.pdf"
|
||||
context["categories"] = models.TrainingCategory.objects.all()
|
||||
return context
|
||||
|
||||
|
||||
class TraineeDetail(views.ProfileDetail):
|
||||
template_name = "trainee_detail.html"
|
||||
model = models.Trainee
|
||||
|
||||
Reference in New Issue
Block a user