Merge remote-tracking branch 'paperwork/main'
This commit is contained in:
commit
52feb2d0b2
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
__pycache__
|
||||
/cmsmanage/settings/prod.py
|
||||
__pycache__/
|
||||
*.sqlite3
|
||||
/__pypackages__/
|
||||
|
5
.pdm.toml
Normal file
5
.pdm.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[python]
|
||||
path = "/usr/bin/python"
|
||||
|
||||
[strategy]
|
||||
save = "compatible"
|
25
Pipfile
25
Pipfile
@ -1,25 +0,0 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
django = "~=3.2"
|
||||
django-widget-tweaks = "~=1.4"
|
||||
django-auth-ldap = "~=4.0"
|
||||
django-markdownx = "~=3.0"
|
||||
django-markdownify = "~=0.9"
|
||||
uvicorn = "~=0.17"
|
||||
mysqlclient = "~=2.1"
|
||||
django-recurrence = "~=1.10"
|
||||
|
||||
[dev-packages]
|
||||
djlint = "~=0.7"
|
||||
black = "*"
|
||||
pre-commit = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
|
||||
[scripts]
|
||||
manage = "python3 ./manage.py"
|
554
Pipfile.lock
generated
554
Pipfile.lock
generated
@ -1,554 +0,0 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "05bf4a81c16ace1a283eed7cb9c0c3890141eed9840be4b037fe8cc003895619"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"asgiref": {
|
||||
"hashes": [
|
||||
"sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0",
|
||||
"sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"bleach": {
|
||||
"hashes": [
|
||||
"sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da",
|
||||
"sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.1.0"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
|
||||
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.0.3"
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:0a0a37f0b93aef30c4bf3a839c187e1175bcdeb7e177341da0cb7b8194416891",
|
||||
"sha256:69c94abe5d6b1b088bf475e09b7b74403f943e34da107e798465d2045da27e75"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2.11"
|
||||
},
|
||||
"django-auth-ldap": {
|
||||
"hashes": [
|
||||
"sha256:276f79e624ce083ce13f161387f65ff1c0efe83ef8a42f2b9830d43317b15239",
|
||||
"sha256:94119c94981809124d3dc4bed974f71c7a980666896df626f556a88a5fe0b59c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"django-markdownify": {
|
||||
"hashes": [
|
||||
"sha256:2d3e460a34fb4498c8f7a054e7c6d4d5f67cc0792f86331b2af2dc27f776b65c",
|
||||
"sha256:b060eb7869f493f7bff390ba2f7a81b981dd6c5f163dbb95423b6cf714ca4d23"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"django-markdownx": {
|
||||
"hashes": [
|
||||
"sha256:e18e395cad0ade96afbb250a81cad15618e417ac3c0d9c37d964be3d8fd57bcf",
|
||||
"sha256:f4d8998618c0548bf5349713d805e7440684d70116de0f10413932286c4e375f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"django-recurrence": {
|
||||
"hashes": [
|
||||
"sha256:715f681f6af029ff3a8d73c7b1460abd8cbc5d5a5001efcb127032e84d9cb963",
|
||||
"sha256:9053b44b78b7fbfe3530673edfdd6d2f562105f8a192bc6a4b906a3df4f95f59"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.10.3"
|
||||
},
|
||||
"django-widget-tweaks": {
|
||||
"hashes": [
|
||||
"sha256:9bfc5c705684754a83cc81da328b39ad1b80f32bd0f4340e2a810cbab4b0c00e",
|
||||
"sha256:fe6b17d5d595c63331f300917980db2afcf71f240ab9341b954aea8f45d25b9a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4.12"
|
||||
},
|
||||
"h11": {
|
||||
"hashes": [
|
||||
"sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06",
|
||||
"sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.13.0"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6",
|
||||
"sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"
|
||||
],
|
||||
"markers": "python_version < '3.10'",
|
||||
"version": "==4.10.1"
|
||||
},
|
||||
"markdown": {
|
||||
"hashes": [
|
||||
"sha256:76df8ae32294ec39dcf89340382882dfa12975f87f45c3ed1ecdb1e8cefc7006",
|
||||
"sha256:9923332318f843411e9932237530df53162e29dc7a4e2b91e35764583c46c9a3"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.3.6"
|
||||
},
|
||||
"mysqlclient": {
|
||||
"hashes": [
|
||||
"sha256:02c8826e6add9b20f4cb12dcf016485f7b1d6e30356a1204d05431867a1b3947",
|
||||
"sha256:2c8410f54492a3d2488a6a53e2d85b7e016751a1e7d116e7aea9c763f59f5e8c",
|
||||
"sha256:973235686f1b720536d417bf0a0d39b4ab3d5086b2b6ad5e6752393428c02b12",
|
||||
"sha256:b62d23c11c516cedb887377c8807628c1c65d57593b57853186a6ee18b0c6a5b",
|
||||
"sha256:e6279263d5a9feca3e0edbc2b2a52c057375bf301d47da2089c075ff76331d14"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.0"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6",
|
||||
"sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc",
|
||||
"sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52",
|
||||
"sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4",
|
||||
"sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af",
|
||||
"sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315",
|
||||
"sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4",
|
||||
"sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281",
|
||||
"sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb",
|
||||
"sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9",
|
||||
"sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128",
|
||||
"sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105",
|
||||
"sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553",
|
||||
"sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5",
|
||||
"sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d",
|
||||
"sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6",
|
||||
"sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100",
|
||||
"sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce",
|
||||
"sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd",
|
||||
"sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05",
|
||||
"sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f",
|
||||
"sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f",
|
||||
"sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7",
|
||||
"sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f",
|
||||
"sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762",
|
||||
"sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379",
|
||||
"sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee",
|
||||
"sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925",
|
||||
"sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f",
|
||||
"sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f",
|
||||
"sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e",
|
||||
"sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==9.0.0"
|
||||
},
|
||||
"pyasn1": {
|
||||
"hashes": [
|
||||
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
|
||||
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
|
||||
"sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
|
||||
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
|
||||
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
|
||||
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
|
||||
"sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
|
||||
"sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
|
||||
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
|
||||
"sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
|
||||
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
|
||||
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
|
||||
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
|
||||
],
|
||||
"version": "==0.4.8"
|
||||
},
|
||||
"pyasn1-modules": {
|
||||
"hashes": [
|
||||
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
|
||||
"sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199",
|
||||
"sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
|
||||
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
|
||||
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
|
||||
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
|
||||
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
|
||||
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
|
||||
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
|
||||
"sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
|
||||
"sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
|
||||
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
|
||||
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"
|
||||
],
|
||||
"version": "==0.2.8"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
|
||||
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.7"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
},
|
||||
"python-ldap": {
|
||||
"hashes": [
|
||||
"sha256:60464c8fc25e71e0fd40449a24eae482dcd0fb7fcf823e7de627a6525b3e0d12"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.4.0"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
|
||||
"sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
|
||||
],
|
||||
"version": "==2021.3"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"sqlparse": {
|
||||
"hashes": [
|
||||
"sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
|
||||
"sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.4.2"
|
||||
},
|
||||
"uvicorn": {
|
||||
"hashes": [
|
||||
"sha256:60a149248181920a73b2e97aec1dacec5501618867f041a228b2519d91a62a91",
|
||||
"sha256:fa166e6c3d58e23ff5a1a3543b079c7b28aa057ab1388201e4b34a49ec05da72"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.17.0.post1"
|
||||
},
|
||||
"webencodings": {
|
||||
"hashes": [
|
||||
"sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78",
|
||||
"sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
|
||||
],
|
||||
"version": "==0.5.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d",
|
||||
"sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.7.0"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
"black": {
|
||||
"hashes": [
|
||||
"sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3",
|
||||
"sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==21.12b0"
|
||||
},
|
||||
"cfgv": {
|
||||
"hashes": [
|
||||
"sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426",
|
||||
"sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"
|
||||
],
|
||||
"markers": "python_full_version >= '3.6.1'",
|
||||
"version": "==3.3.1"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
|
||||
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.0.3"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
|
||||
"sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==0.4.4"
|
||||
},
|
||||
"distlib": {
|
||||
"hashes": [
|
||||
"sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b",
|
||||
"sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"
|
||||
],
|
||||
"version": "==0.3.4"
|
||||
},
|
||||
"djlint": {
|
||||
"hashes": [
|
||||
"sha256:68aad9ddfef883cc9d9e0d177387b74840af5ca12dcce6e4629eb7075c97dc05",
|
||||
"sha256:714ed457e022047149c8bff57d5be00ce30f8846b60e866791c66d27e7d11e7f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.7.3"
|
||||
},
|
||||
"filelock": {
|
||||
"hashes": [
|
||||
"sha256:38b4f4c989f9d06d44524df1b24bd19e167d851f19b50bf3e3559952dddc5b80",
|
||||
"sha256:cf0fc6a2f8d26bd900f19bf33915ca70ba4dd8c56903eeb14e1e7a2fd7590146"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.4.2"
|
||||
},
|
||||
"identify": {
|
||||
"hashes": [
|
||||
"sha256:d11469ff952a4d7fd7f9be520d335dc450f585d474b39b5dfb86a500831ab6c7",
|
||||
"sha256:d27d10099844741c277b45d809bd452db0d70a9b41ea3cd93799ebbbcc6dcb29"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.4.5"
|
||||
},
|
||||
"mypy-extensions": {
|
||||
"hashes": [
|
||||
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
|
||||
"sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
|
||||
],
|
||||
"version": "==0.4.3"
|
||||
},
|
||||
"nodeenv": {
|
||||
"hashes": [
|
||||
"sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b",
|
||||
"sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"
|
||||
],
|
||||
"version": "==1.6.0"
|
||||
},
|
||||
"pathspec": {
|
||||
"hashes": [
|
||||
"sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a",
|
||||
"sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"
|
||||
],
|
||||
"version": "==0.9.0"
|
||||
},
|
||||
"platformdirs": {
|
||||
"hashes": [
|
||||
"sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca",
|
||||
"sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.4.1"
|
||||
},
|
||||
"pre-commit": {
|
||||
"hashes": [
|
||||
"sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616",
|
||||
"sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.17.0"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293",
|
||||
"sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b",
|
||||
"sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57",
|
||||
"sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b",
|
||||
"sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4",
|
||||
"sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07",
|
||||
"sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba",
|
||||
"sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9",
|
||||
"sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287",
|
||||
"sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513",
|
||||
"sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0",
|
||||
"sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0",
|
||||
"sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92",
|
||||
"sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f",
|
||||
"sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2",
|
||||
"sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc",
|
||||
"sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c",
|
||||
"sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86",
|
||||
"sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4",
|
||||
"sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c",
|
||||
"sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34",
|
||||
"sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b",
|
||||
"sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c",
|
||||
"sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb",
|
||||
"sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737",
|
||||
"sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3",
|
||||
"sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d",
|
||||
"sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53",
|
||||
"sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78",
|
||||
"sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803",
|
||||
"sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a",
|
||||
"sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174",
|
||||
"sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==6.0"
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:04611cc0f627fc4a50bc4a9a2e6178a974c6a6a4aa9c1cca921635d2c47b9c87",
|
||||
"sha256:0b5d6f9aed3153487252d00a18e53f19b7f52a1651bc1d0c4b5844bc286dfa52",
|
||||
"sha256:0d2f5c3f7057530afd7b739ed42eb04f1011203bc5e4663e1e1d01bb50f813e3",
|
||||
"sha256:11772be1eb1748e0e197a40ffb82fb8fd0d6914cd147d841d9703e2bef24d288",
|
||||
"sha256:1333b3ce73269f986b1fa4d5d395643810074dc2de5b9d262eb258daf37dc98f",
|
||||
"sha256:16f81025bb3556eccb0681d7946e2b35ff254f9f888cff7d2120e8826330315c",
|
||||
"sha256:1a171eaac36a08964d023eeff740b18a415f79aeb212169080c170ec42dd5184",
|
||||
"sha256:1d6301f5288e9bdca65fab3de6b7de17362c5016d6bf8ee4ba4cbe833b2eda0f",
|
||||
"sha256:1e031899cb2bc92c0cf4d45389eff5b078d1936860a1be3aa8c94fa25fb46ed8",
|
||||
"sha256:1f8c0ae0a0de4e19fddaaff036f508db175f6f03db318c80bbc239a1def62d02",
|
||||
"sha256:2245441445099411b528379dee83e56eadf449db924648e5feb9b747473f42e3",
|
||||
"sha256:22709d701e7037e64dae2a04855021b62efd64a66c3ceed99dfd684bfef09e38",
|
||||
"sha256:24c89346734a4e4d60ecf9b27cac4c1fee3431a413f7aa00be7c4d7bbacc2c4d",
|
||||
"sha256:25716aa70a0d153cd844fe861d4f3315a6ccafce22b39d8aadbf7fcadff2b633",
|
||||
"sha256:2dacb3dae6b8cc579637a7b72f008bff50a94cde5e36e432352f4ca57b9e54c4",
|
||||
"sha256:34316bf693b1d2d29c087ee7e4bb10cdfa39da5f9c50fa15b07489b4ab93a1b5",
|
||||
"sha256:36b2d700a27e168fa96272b42d28c7ac3ff72030c67b32f37c05616ebd22a202",
|
||||
"sha256:37978254d9d00cda01acc1997513f786b6b971e57b778fbe7c20e30ae81a97f3",
|
||||
"sha256:38289f1690a7e27aacd049e420769b996826f3728756859420eeee21cc857118",
|
||||
"sha256:385ccf6d011b97768a640e9d4de25412204fbe8d6b9ae39ff115d4ff03f6fe5d",
|
||||
"sha256:3c7ea86b9ca83e30fa4d4cd0eaf01db3ebcc7b2726a25990966627e39577d729",
|
||||
"sha256:49810f907dfe6de8da5da7d2b238d343e6add62f01a15d03e2195afc180059ed",
|
||||
"sha256:519c0b3a6fbb68afaa0febf0d28f6c4b0a1074aefc484802ecb9709faf181607",
|
||||
"sha256:51f02ca184518702975b56affde6c573ebad4e411599005ce4468b1014b4786c",
|
||||
"sha256:552a39987ac6655dad4bf6f17dd2b55c7b0c6e949d933b8846d2e312ee80005a",
|
||||
"sha256:596f5ae2eeddb79b595583c2e0285312b2783b0ec759930c272dbf02f851ff75",
|
||||
"sha256:6014038f52b4b2ac1fa41a58d439a8a00f015b5c0735a0cd4b09afe344c94899",
|
||||
"sha256:61ebbcd208d78658b09e19c78920f1ad38936a0aa0f9c459c46c197d11c580a0",
|
||||
"sha256:6213713ac743b190ecbf3f316d6e41d099e774812d470422b3a0f137ea635832",
|
||||
"sha256:637e27ea1ebe4a561db75a880ac659ff439dec7f55588212e71700bb1ddd5af9",
|
||||
"sha256:6aa427c55a0abec450bca10b64446331b5ca8f79b648531138f357569705bc4a",
|
||||
"sha256:6ca45359d7a21644793de0e29de497ef7f1ae7268e346c4faf87b421fea364e6",
|
||||
"sha256:6db1b52c6f2c04fafc8da17ea506608e6be7086715dab498570c3e55e4f8fbd1",
|
||||
"sha256:752e7ddfb743344d447367baa85bccd3629c2c3940f70506eb5f01abce98ee68",
|
||||
"sha256:760c54ad1b8a9b81951030a7e8e7c3ec0964c1cb9fee585a03ff53d9e531bb8e",
|
||||
"sha256:768632fd8172ae03852e3245f11c8a425d95f65ff444ce46b3e673ae5b057b74",
|
||||
"sha256:7a0b9f6a1a15d494b35f25ed07abda03209fa76c33564c09c9e81d34f4b919d7",
|
||||
"sha256:7e070d3aef50ac3856f2ef5ec7214798453da878bb5e5a16c16a61edf1817cc3",
|
||||
"sha256:7e12949e5071c20ec49ef00c75121ed2b076972132fc1913ddf5f76cae8d10b4",
|
||||
"sha256:7e26eac9e52e8ce86f915fd33380f1b6896a2b51994e40bb094841e5003429b4",
|
||||
"sha256:85ffd6b1cb0dfb037ede50ff3bef80d9bf7fa60515d192403af6745524524f3b",
|
||||
"sha256:8618d9213a863c468a865e9d2ec50221015f7abf52221bc927152ef26c484b4c",
|
||||
"sha256:8acef4d8a4353f6678fd1035422a937c2170de58a2b29f7da045d5249e934101",
|
||||
"sha256:8d2f355a951f60f0843f2368b39970e4667517e54e86b1508e76f92b44811a8a",
|
||||
"sha256:90b6840b6448203228a9d8464a7a0d99aa8fa9f027ef95fe230579abaf8a6ee1",
|
||||
"sha256:9187500d83fd0cef4669385cbb0961e227a41c0c9bc39219044e35810793edf7",
|
||||
"sha256:93c20777a72cae8620203ac11c4010365706062aa13aaedd1a21bb07adbb9d5d",
|
||||
"sha256:93cce7d422a0093cfb3606beae38a8e47a25232eea0f292c878af580a9dc7605",
|
||||
"sha256:94c623c331a48a5ccc7d25271399aff29729fa202c737ae3b4b28b89d2b0976d",
|
||||
"sha256:97f32dc03a8054a4c4a5ab5d761ed4861e828b2c200febd4e46857069a483916",
|
||||
"sha256:9a2bf98ac92f58777c0fafc772bf0493e67fcf677302e0c0a630ee517a43b949",
|
||||
"sha256:a602bdc8607c99eb5b391592d58c92618dcd1537fdd87df1813f03fed49957a6",
|
||||
"sha256:a9d24b03daf7415f78abc2d25a208f234e2c585e5e6f92f0204d2ab7b9ab48e3",
|
||||
"sha256:abfcb0ef78df0ee9df4ea81f03beea41849340ce33a4c4bd4dbb99e23ec781b6",
|
||||
"sha256:b013f759cd69cb0a62de954d6d2096d648bc210034b79b1881406b07ed0a83f9",
|
||||
"sha256:b02e3e72665cd02afafb933453b0c9f6c59ff6e3708bd28d0d8580450e7e88af",
|
||||
"sha256:b52cc45e71657bc4743a5606d9023459de929b2a198d545868e11898ba1c3f59",
|
||||
"sha256:ba37f11e1d020969e8a779c06b4af866ffb6b854d7229db63c5fdddfceaa917f",
|
||||
"sha256:bb804c7d0bfbd7e3f33924ff49757de9106c44e27979e2492819c16972ec0da2",
|
||||
"sha256:bf594cc7cc9d528338d66674c10a5b25e3cde7dd75c3e96784df8f371d77a298",
|
||||
"sha256:c38baee6bdb7fe1b110b6b3aaa555e6e872d322206b7245aa39572d3fc991ee4",
|
||||
"sha256:c73d2166e4b210b73d1429c4f1ca97cea9cc090e5302df2a7a0a96ce55373f1c",
|
||||
"sha256:c9099bf89078675c372339011ccfc9ec310310bf6c292b413c013eb90ffdcafc",
|
||||
"sha256:cf0db26a1f76aa6b3aa314a74b8facd586b7a5457d05b64f8082a62c9c49582a",
|
||||
"sha256:d19a34f8a3429bd536996ad53597b805c10352a8561d8382e05830df389d2b43",
|
||||
"sha256:da80047524eac2acf7c04c18ac7a7da05a9136241f642dd2ed94269ef0d0a45a",
|
||||
"sha256:de2923886b5d3214be951bc2ce3f6b8ac0d6dfd4a0d0e2a4d2e5523d8046fdfb",
|
||||
"sha256:defa0652696ff0ba48c8aff5a1fac1eef1ca6ac9c660b047fc8e7623c4eb5093",
|
||||
"sha256:e54a1eb9fd38f2779e973d2f8958fd575b532fe26013405d1afb9ee2374e7ab8",
|
||||
"sha256:e5c31d70a478b0ca22a9d2d76d520ae996214019d39ed7dd93af872c7f301e52",
|
||||
"sha256:ebaeb93f90c0903233b11ce913a7cb8f6ee069158406e056f884854c737d2442",
|
||||
"sha256:ecfe51abf7f045e0b9cdde71ca9e153d11238679ef7b5da6c82093874adf3338",
|
||||
"sha256:f99112aed4fb7cee00c7f77e8b964a9b10f69488cdff626ffd797d02e2e4484f",
|
||||
"sha256:fd914db437ec25bfa410f8aa0aa2f3ba87cdfc04d9919d608d02330947afaeab"
|
||||
],
|
||||
"version": "==2022.1.18"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==0.10.2"
|
||||
},
|
||||
"tomli": {
|
||||
"hashes": [
|
||||
"sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f",
|
||||
"sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.2.3"
|
||||
},
|
||||
"tomlkit": {
|
||||
"hashes": [
|
||||
"sha256:29e84a855712dfe0e88a48f6d05c21118dbafb283bb2eed614d46f80deb8e9a1",
|
||||
"sha256:b824e3466f1d475b2b5f1c392954c6cb7ea04d64354ff7300dc7c14257dc85db"
|
||||
],
|
||||
"markers": "python_version >= '3.6' and python_full_version < '4.0.0'",
|
||||
"version": "==0.8.0"
|
||||
},
|
||||
"tqdm": {
|
||||
"hashes": [
|
||||
"sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c",
|
||||
"sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==4.62.3"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e",
|
||||
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==4.0.1"
|
||||
},
|
||||
"virtualenv": {
|
||||
"hashes": [
|
||||
"sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09",
|
||||
"sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==20.13.0"
|
||||
}
|
||||
}
|
||||
}
|
2
cmsmanage/settings/.gitignore
vendored
Normal file
2
cmsmanage/settings/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
dev.py
|
||||
prod.py
|
@ -10,7 +10,6 @@ For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/3.1/ref/settings/
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
@ -22,18 +21,20 @@ ALLOWED_HOSTS = []
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
"tasks.apps.TasksConfig",
|
||||
"rentals.apps.RentalsConfig",
|
||||
"widget_tweaks",
|
||||
"markdownx",
|
||||
"markdownify",
|
||||
"recurrence",
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"django_admin_logs",
|
||||
"widget_tweaks",
|
||||
"markdownx",
|
||||
"recurrence",
|
||||
"tasks.apps.TasksConfig",
|
||||
"rentals.apps.RentalsConfig",
|
||||
"membershipworks.apps.MembershipworksConfig",
|
||||
"paperwork.apps.PaperworkConfig",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -51,7 +52,7 @@ ROOT_URLCONF = "cmsmanage.urls"
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [os.path.join(BASE_DIR, "templates")],
|
||||
"DIRS": [Path(BASE_DIR) / "templates"],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
@ -68,6 +69,10 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
WSGI_APPLICATION = "cmsmanage.wsgi.application"
|
||||
|
||||
DATABASE_ROUTERS = [
|
||||
"membershipworks.routers.MembershipWorksRouter",
|
||||
"paperwork.routers.PaperworkRouter",
|
||||
]
|
||||
|
||||
# Default URL to redirect to after authentication
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
|
@ -1,20 +0,0 @@
|
||||
from .base import *
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = "g&zqf68eks@z$ctb%3_5+retmt%_i0=)7-y$i^gvc6p#s1+*ng"
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
"default": {
|
||||
"ENGINE": "django.db.backends.sqlite3",
|
||||
"NAME": BASE_DIR / "db.sqlite3",
|
||||
}
|
||||
}
|
7
cmsmanage/settings/dev_base.py
Normal file
7
cmsmanage/settings/dev_base.py
Normal file
@ -0,0 +1,7 @@
|
||||
from .base import *
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
@ -1,5 +1,5 @@
|
||||
import ldap
|
||||
from django_auth_ldap.config import LDAPSearch, PosixGroupType
|
||||
from django_auth_ldap.config import LDAPSearch, PosixGroupType, LDAPGroupQuery
|
||||
|
||||
from .base import *
|
||||
|
||||
@ -27,6 +27,12 @@ AUTH_LDAP_USER_ATTR_MAP = {
|
||||
"email": "mail",
|
||||
}
|
||||
|
||||
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
|
||||
"is_staff": LDAPGroupQuery(
|
||||
"cn=MW_CMS Staff,cn=groups,dc=sawtooth,dc=claremontmakerspace,dc=org"
|
||||
),
|
||||
}
|
||||
|
||||
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
|
||||
"cn=groups,dc=sawtooth,dc=claremontmakerspace,dc=org",
|
||||
ldap.SCOPE_SUBTREE,
|
||||
|
0
membershipworks/__init__.py
Normal file
0
membershipworks/__init__.py
Normal file
29
membershipworks/admin.py
Normal file
29
membershipworks/admin.py
Normal file
@ -0,0 +1,29 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Member, Flag
|
||||
|
||||
|
||||
class ReadOnlyAdmin(admin.ModelAdmin):
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
class MemberFlagInline(admin.TabularInline):
|
||||
model = Member.flags.through
|
||||
|
||||
|
||||
@admin.register(Member)
|
||||
class MemberAdmin(ReadOnlyAdmin):
|
||||
search_fields = ["account_name"]
|
||||
inlines = [MemberFlagInline]
|
||||
|
||||
|
||||
@admin.register(Flag)
|
||||
class FlagAdmin(ReadOnlyAdmin):
|
||||
inlines = [MemberFlagInline]
|
6
membershipworks/apps.py
Normal file
6
membershipworks/apps.py
Normal file
@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MembershipworksConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "membershipworks"
|
346
membershipworks/migrations/0001_initial.py
Normal file
346
membershipworks/migrations/0001_initial.py
Normal file
@ -0,0 +1,346 @@
|
||||
# Generated by Django 4.0.2 on 2022-02-12 05:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Flag",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.CharField(max_length=24, primary_key=True, serialize=False),
|
||||
),
|
||||
("name", models.TextField(null=True)),
|
||||
("type", models.CharField(max_length=6)),
|
||||
],
|
||||
options={
|
||||
"db_table": "flag",
|
||||
"managed": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Member",
|
||||
fields=[
|
||||
(
|
||||
"uid",
|
||||
models.CharField(max_length=24, primary_key=True, serialize=False),
|
||||
),
|
||||
(
|
||||
"year_of_birth",
|
||||
models.TextField(db_column="Year of Birth", null=True),
|
||||
),
|
||||
("account_name", models.TextField(db_column="Account Name", null=True)),
|
||||
("first_name", models.TextField(db_column="First Name", null=True)),
|
||||
("last_name", models.TextField(db_column="Last Name", null=True)),
|
||||
("phone", models.TextField(db_column="Phone", null=True)),
|
||||
("email", models.TextField(db_column="Email", null=True)),
|
||||
(
|
||||
"address_street",
|
||||
models.TextField(db_column="Address (Street)", null=True),
|
||||
),
|
||||
(
|
||||
"address_city",
|
||||
models.TextField(db_column="Address (City)", null=True),
|
||||
),
|
||||
(
|
||||
"address_state_province",
|
||||
models.TextField(db_column="Address (State/Province)", null=True),
|
||||
),
|
||||
(
|
||||
"address_postal_code",
|
||||
models.TextField(db_column="Address (Postal Code)", null=True),
|
||||
),
|
||||
(
|
||||
"address_country",
|
||||
models.TextField(db_column="Address (Country)", null=True),
|
||||
),
|
||||
(
|
||||
"profile_description",
|
||||
models.TextField(db_column="Profile description", null=True),
|
||||
),
|
||||
("website", models.TextField(db_column="Website", null=True)),
|
||||
("fax", models.TextField(db_column="Fax", null=True)),
|
||||
(
|
||||
"contact_person",
|
||||
models.TextField(db_column="Contact Person", null=True),
|
||||
),
|
||||
("password", models.TextField(db_column="Password", null=True)),
|
||||
(
|
||||
"position_relation",
|
||||
models.TextField(db_column="Position/relation", null=True),
|
||||
),
|
||||
(
|
||||
"parent_account_id",
|
||||
models.TextField(db_column="Parent Account ID", null=True),
|
||||
),
|
||||
(
|
||||
"gift_membership_purchased_by",
|
||||
models.TextField(
|
||||
db_column="Gift Membership purchased by", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"purchased_gift_membership_for",
|
||||
models.TextField(
|
||||
db_column="Purchased Gift Membership for", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"closet_storage",
|
||||
models.TextField(db_column="Closet Storage #", null=True),
|
||||
),
|
||||
(
|
||||
"storage_shelf",
|
||||
models.TextField(db_column="Storage Shelf #", null=True),
|
||||
),
|
||||
(
|
||||
"personal_studio_space",
|
||||
models.TextField(db_column="Personal Studio Space #", null=True),
|
||||
),
|
||||
(
|
||||
"access_permitted_shops_during_extended_hours",
|
||||
models.BooleanField(
|
||||
db_column="Access Permitted Shops During Extended Hours?"
|
||||
),
|
||||
),
|
||||
(
|
||||
"normal_access_permitted_during_covid19_limited_operations",
|
||||
models.BooleanField(
|
||||
db_column="Normal Access Permitted During COVID-19 Limited Operations"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_permitted_during_covid19_staffed_period_only",
|
||||
models.BooleanField(
|
||||
db_column="Access Permitted During COVID-19 Staffed Period Only"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_front_door_and_studio_space_during_extended_hours",
|
||||
models.BooleanField(
|
||||
db_column="Access Front Door and Studio Space During Extended Hours?"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_wood_shop",
|
||||
models.BooleanField(db_column="Access Wood Shop?"),
|
||||
),
|
||||
(
|
||||
"access_metal_shop",
|
||||
models.BooleanField(db_column="Access Metal Shop?"),
|
||||
),
|
||||
(
|
||||
"access_storage_closet",
|
||||
models.BooleanField(db_column="Access Storage Closet?"),
|
||||
),
|
||||
(
|
||||
"access_studio_space",
|
||||
models.BooleanField(db_column="Access Studio Space?"),
|
||||
),
|
||||
(
|
||||
"access_front_door",
|
||||
models.BooleanField(db_column="Access Front Door?"),
|
||||
),
|
||||
(
|
||||
"access_card_number",
|
||||
models.TextField(db_column="Access Card Number", null=True),
|
||||
),
|
||||
(
|
||||
"access_card_facility_code",
|
||||
models.TextField(db_column="Access Card Facility Code", null=True),
|
||||
),
|
||||
(
|
||||
"auto_billing_id",
|
||||
models.TextField(db_column="Auto Billing ID", null=True),
|
||||
),
|
||||
(
|
||||
"billing_method",
|
||||
models.TextField(db_column="Billing Method", null=True),
|
||||
),
|
||||
("renewal_date", models.DateField(db_column="Renewal Date", null=True)),
|
||||
("join_date", models.DateField(db_column="Join Date", null=True)),
|
||||
("admin_note", models.TextField(db_column="Admin note", null=True)),
|
||||
(
|
||||
"profile_gallery_image_url",
|
||||
models.TextField(db_column="Profile gallery image URL", null=True),
|
||||
),
|
||||
(
|
||||
"business_card_image_url",
|
||||
models.TextField(db_column="Business card image URL", null=True),
|
||||
),
|
||||
("instagram", models.TextField(db_column="Instagram", null=True)),
|
||||
("pinterest", models.TextField(db_column="Pinterest", null=True)),
|
||||
("youtube", models.TextField(db_column="Youtube", null=True)),
|
||||
("yelp", models.TextField(db_column="Yelp", null=True)),
|
||||
("google", models.TextField(db_column="Google+", null=True)),
|
||||
("bbb", models.TextField(db_column="BBB", null=True)),
|
||||
("twitter", models.TextField(db_column="Twitter", null=True)),
|
||||
("facebook", models.TextField(db_column="Facebook", null=True)),
|
||||
("linked_in", models.TextField(db_column="LinkedIn", null=True)),
|
||||
(
|
||||
"do_not_show_street_address_in_profile",
|
||||
models.TextField(
|
||||
db_column="Do not show street address in profile", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"do_not_list_in_directory",
|
||||
models.TextField(db_column="Do not list in directory", null=True),
|
||||
),
|
||||
(
|
||||
"how_did_you_hear",
|
||||
models.TextField(db_column="HowDidYouHear", null=True),
|
||||
),
|
||||
(
|
||||
"authorize_charge",
|
||||
models.TextField(db_column="authorizeCharge", null=True),
|
||||
),
|
||||
(
|
||||
"policy_agreement",
|
||||
models.TextField(db_column="policyAgreement", null=True),
|
||||
),
|
||||
(
|
||||
"waiver_form_signed_and_on_file_date",
|
||||
models.DateField(
|
||||
db_column="Waiver form signed and on file date.", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_agreement_signed_and_on_file_date",
|
||||
models.DateField(
|
||||
db_column="Membership Agreement signed and on file date.",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
("ip_address", models.TextField(db_column="IP Address", null=True)),
|
||||
("audit_date", models.DateField(db_column="Audit Date", null=True)),
|
||||
(
|
||||
"agreement_version",
|
||||
models.TextField(db_column="Agreement Version", null=True),
|
||||
),
|
||||
(
|
||||
"paperwork_status",
|
||||
models.TextField(db_column="Paperwork status", null=True),
|
||||
),
|
||||
(
|
||||
"membership_agreement_dated",
|
||||
models.BooleanField(db_column="Membership agreement dated"),
|
||||
),
|
||||
(
|
||||
"membership_agreement_acknowledgement_page_filled_out",
|
||||
models.BooleanField(
|
||||
db_column="Membership Agreement Acknowledgement Page Filled Out"
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_agreement_signed",
|
||||
models.BooleanField(db_column="Membership Agreement Signed"),
|
||||
),
|
||||
(
|
||||
"liability_form_filled_out",
|
||||
models.BooleanField(db_column="Liability Form Filled Out"),
|
||||
),
|
||||
(
|
||||
"self_certify_essential_business",
|
||||
models.BooleanField(db_column="selfCertifyEssentialBusiness"),
|
||||
),
|
||||
(
|
||||
"accepted_covid19_policy",
|
||||
models.BooleanField(db_column="Accepted COVID-19 Policy"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "members",
|
||||
"ordering": ("first_name", "last_name"),
|
||||
"managed": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="MemberFlag",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "memberflag",
|
||||
"managed": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Transaction",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("sid", models.CharField(max_length=27, null=True)),
|
||||
("timestamp", models.DateTimeField()),
|
||||
("type", models.TextField(null=True)),
|
||||
(
|
||||
"sum",
|
||||
models.DecimalField(decimal_places=4, max_digits=13, null=True),
|
||||
),
|
||||
(
|
||||
"fee",
|
||||
models.DecimalField(decimal_places=4, max_digits=13, null=True),
|
||||
),
|
||||
("event_id", models.TextField(null=True)),
|
||||
("for_what", models.TextField(db_column="For", null=True)),
|
||||
("items", models.TextField(db_column="Items", null=True)),
|
||||
(
|
||||
"discount_code",
|
||||
models.TextField(db_column="Discount Code", null=True),
|
||||
),
|
||||
("note", models.TextField(db_column="Note", null=True)),
|
||||
("name", models.TextField(db_column="Name", null=True)),
|
||||
(
|
||||
"contact_person",
|
||||
models.TextField(db_column="Contact Person", null=True),
|
||||
),
|
||||
("full_address", models.TextField(db_column="Full Address", null=True)),
|
||||
("street", models.TextField(db_column="Street", null=True)),
|
||||
("city", models.TextField(db_column="City", null=True)),
|
||||
(
|
||||
"state_province",
|
||||
models.TextField(db_column="State/Province", null=True),
|
||||
),
|
||||
("postal_code", models.TextField(db_column="Postal Code", null=True)),
|
||||
("country", models.TextField(db_column="Country", null=True)),
|
||||
("phone", models.TextField(db_column="Phone", null=True)),
|
||||
("email", models.TextField(db_column="Email", null=True)),
|
||||
(
|
||||
"member",
|
||||
models.ForeignKey(
|
||||
db_column="uid",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="transactions",
|
||||
to="membershipworks.member",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "transactions",
|
||||
},
|
||||
),
|
||||
]
|
0
membershipworks/migrations/__init__.py
Normal file
0
membershipworks/migrations/__init__.py
Normal file
154
membershipworks/models.py
Normal file
154
membershipworks/models.py
Normal file
@ -0,0 +1,154 @@
|
||||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Flag(models.Model):
|
||||
id = models.CharField(max_length=24, primary_key=True)
|
||||
name = models.TextField(null=True)
|
||||
type = models.CharField(max_length=6)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.type})"
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = "flag"
|
||||
|
||||
|
||||
# TODO: is this still a temporal table?
|
||||
class Member(models.Model):
|
||||
uid = models.CharField(max_length=24, primary_key=True)
|
||||
year_of_birth = models.TextField(db_column="Year of Birth", null=True)
|
||||
account_name = models.TextField(db_column="Account Name", null=True)
|
||||
first_name = models.TextField(db_column="First Name", null=True)
|
||||
last_name = models.TextField(db_column="Last Name", null=True)
|
||||
phone = models.TextField(db_column="Phone", null=True)
|
||||
email = models.TextField(db_column="Email", null=True)
|
||||
address_street = models.TextField(db_column="Address (Street)", null=True)
|
||||
address_city = models.TextField(db_column="Address (City)", null=True)
|
||||
address_state_province = models.TextField(
|
||||
db_column="Address (State/Province)", null=True
|
||||
)
|
||||
address_postal_code = models.TextField(db_column="Address (Postal Code)", null=True)
|
||||
address_country = models.TextField(db_column="Address (Country)", null=True)
|
||||
profile_description = models.TextField(db_column="Profile description", null=True)
|
||||
website = models.TextField(db_column="Website", null=True)
|
||||
fax = models.TextField(db_column="Fax", null=True)
|
||||
contact_person = models.TextField(db_column="Contact Person", null=True)
|
||||
password = models.TextField(db_column="Password", null=True)
|
||||
position_relation = models.TextField(db_column="Position/relation", null=True)
|
||||
parent_account_id = models.TextField(db_column="Parent Account ID", null=True)
|
||||
gift_membership_purchased_by = models.TextField(
|
||||
db_column="Gift Membership purchased by", null=True
|
||||
)
|
||||
purchased_gift_membership_for = models.TextField(
|
||||
db_column="Purchased Gift Membership for", null=True
|
||||
)
|
||||
closet_storage = models.TextField(db_column="Closet Storage #", null=True)
|
||||
storage_shelf = models.TextField(db_column="Storage Shelf #", null=True)
|
||||
personal_studio_space = models.TextField(
|
||||
db_column="Personal Studio Space #", null=True
|
||||
)
|
||||
access_permitted_shops_during_extended_hours = models.BooleanField(
|
||||
db_column="Access Permitted Shops During Extended Hours?"
|
||||
)
|
||||
normal_access_permitted_during_covid19_limited_operations = models.BooleanField(
|
||||
db_column="Normal Access Permitted During COVID-19 Limited Operations"
|
||||
)
|
||||
access_permitted_during_covid19_staffed_period_only = models.BooleanField(
|
||||
db_column="Access Permitted During COVID-19 Staffed Period Only"
|
||||
)
|
||||
access_front_door_and_studio_space_during_extended_hours = models.BooleanField(
|
||||
db_column="Access Front Door and Studio Space During Extended Hours?"
|
||||
)
|
||||
access_wood_shop = models.BooleanField(db_column="Access Wood Shop?")
|
||||
access_metal_shop = models.BooleanField(db_column="Access Metal Shop?")
|
||||
access_storage_closet = models.BooleanField(db_column="Access Storage Closet?")
|
||||
access_studio_space = models.BooleanField(db_column="Access Studio Space?")
|
||||
access_front_door = models.BooleanField(db_column="Access Front Door?")
|
||||
access_card_number = models.TextField(db_column="Access Card Number", null=True)
|
||||
access_card_facility_code = models.TextField(
|
||||
db_column="Access Card Facility Code", null=True
|
||||
)
|
||||
auto_billing_id = models.TextField(db_column="Auto Billing ID", null=True)
|
||||
billing_method = models.TextField(db_column="Billing Method", null=True)
|
||||
renewal_date = models.DateField(db_column="Renewal Date", null=True)
|
||||
join_date = models.DateField(db_column="Join Date", null=True)
|
||||
admin_note = models.TextField(db_column="Admin note", null=True)
|
||||
profile_gallery_image_url = models.TextField(
|
||||
db_column="Profile gallery image URL", null=True
|
||||
)
|
||||
business_card_image_url = models.TextField(
|
||||
db_column="Business card image URL", null=True
|
||||
)
|
||||
instagram = models.TextField(db_column="Instagram", null=True)
|
||||
pinterest = models.TextField(db_column="Pinterest", null=True)
|
||||
youtube = models.TextField(db_column="Youtube", null=True)
|
||||
yelp = models.TextField(db_column="Yelp", null=True)
|
||||
google = models.TextField(db_column="Google+", null=True)
|
||||
bbb = models.TextField(db_column="BBB", null=True)
|
||||
twitter = models.TextField(db_column="Twitter", null=True)
|
||||
facebook = models.TextField(db_column="Facebook", null=True)
|
||||
linked_in = models.TextField(db_column="LinkedIn", null=True)
|
||||
do_not_show_street_address_in_profile = models.TextField(
|
||||
db_column="Do not show street address in profile", null=True
|
||||
)
|
||||
do_not_list_in_directory = models.TextField(
|
||||
db_column="Do not list in directory", null=True
|
||||
)
|
||||
how_did_you_hear = models.TextField(db_column="HowDidYouHear", null=True)
|
||||
authorize_charge = models.TextField(db_column="authorizeCharge", null=True)
|
||||
policy_agreement = models.TextField(db_column="policyAgreement", null=True)
|
||||
waiver_form_signed_and_on_file_date = models.DateField(
|
||||
db_column="Waiver form signed and on file date.", null=True
|
||||
)
|
||||
membership_agreement_signed_and_on_file_date = models.DateField(
|
||||
db_column="Membership Agreement signed and on file date.", null=True
|
||||
)
|
||||
ip_address = models.TextField(db_column="IP Address", null=True)
|
||||
audit_date = models.DateField(db_column="Audit Date", null=True)
|
||||
agreement_version = models.TextField(db_column="Agreement Version", null=True)
|
||||
paperwork_status = models.TextField(db_column="Paperwork status", null=True)
|
||||
membership_agreement_dated = models.BooleanField(
|
||||
db_column="Membership agreement dated"
|
||||
)
|
||||
membership_agreement_acknowledgement_page_filled_out = models.BooleanField(
|
||||
db_column="Membership Agreement Acknowledgement Page Filled Out"
|
||||
)
|
||||
membership_agreement_signed = models.BooleanField(
|
||||
db_column="Membership Agreement Signed"
|
||||
)
|
||||
liability_form_filled_out = models.BooleanField(
|
||||
db_column="Liability Form Filled Out"
|
||||
)
|
||||
self_certify_essential_business = models.BooleanField(
|
||||
db_column="selfCertifyEssentialBusiness"
|
||||
)
|
||||
accepted_covid19_policy = models.BooleanField(db_column="Accepted COVID-19 Policy")
|
||||
flags = models.ManyToManyField(Flag, through="MemberFlag", related_name="members")
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.account_name}"
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = "members"
|
||||
ordering = ("first_name", "last_name")
|
||||
|
||||
|
||||
class MemberFlag(models.Model):
|
||||
member = models.ForeignKey(Member, on_delete=models.PROTECT, db_column="uid")
|
||||
flag = models.ForeignKey(Flag, on_delete=models.PROTECT)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.member} - {self.flag}"
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
db_table = "memberflag"
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["member", "flag_id"], name="unique_member_flag"
|
||||
)
|
||||
]
|
18
membershipworks/routers.py
Normal file
18
membershipworks/routers.py
Normal file
@ -0,0 +1,18 @@
|
||||
class MembershipWorksRouter:
|
||||
app_label = "membershipworks"
|
||||
db = "membershipworks"
|
||||
|
||||
def db_for_read(self, model, **hints):
|
||||
if model._meta.app_label == self.app_label:
|
||||
return self.db
|
||||
return None
|
||||
|
||||
def db_for_write(self, model, **hints):
|
||||
if model._meta.app_label == self.app_label:
|
||||
return self.db
|
||||
return None
|
||||
|
||||
def allow_migrate(self, db, app_label, model_name=None, **hints):
|
||||
if db == self.db:
|
||||
return False
|
||||
return None
|
3
membershipworks/tests.py
Normal file
3
membershipworks/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
3
membershipworks/views.py
Normal file
3
membershipworks/views.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
0
paperwork/__init__.py
Normal file
0
paperwork/__init__.py
Normal file
130
paperwork/admin.py
Normal file
130
paperwork/admin.py
Normal file
@ -0,0 +1,130 @@
|
||||
from django.core import mail
|
||||
from django.contrib import admin, messages
|
||||
from django.db.models.functions import Now
|
||||
|
||||
from .models import (
|
||||
CmsRedRiverVeteransScholarship,
|
||||
CertificationDefinition,
|
||||
Certification,
|
||||
CertificationVersion,
|
||||
InstructorOrVendor,
|
||||
SpecialProgram,
|
||||
Waiver,
|
||||
)
|
||||
from .certification_emails import all_certification_emails
|
||||
|
||||
|
||||
class CertificationVersionInline(admin.TabularInline):
|
||||
model = CertificationVersion
|
||||
extra = 1
|
||||
|
||||
|
||||
@admin.register(CertificationVersion)
|
||||
class CertificationVersionAdmin(admin.ModelAdmin):
|
||||
search_fields = ["definition__certification_name", "version"]
|
||||
list_display = ["definition", "version"]
|
||||
list_filter = ["definition__department", "definition__certification_name"]
|
||||
|
||||
|
||||
@admin.register(CertificationDefinition)
|
||||
class CertificationDefinitionAdmin(admin.ModelAdmin):
|
||||
search_fields = ["certification_name"]
|
||||
list_display = ["certification_name", "department"]
|
||||
list_filter = ["department"]
|
||||
inlines = [CertificationVersionInline]
|
||||
|
||||
|
||||
@admin.register(Certification)
|
||||
class CertificationAdmin(admin.ModelAdmin):
|
||||
search_fields = [
|
||||
"name",
|
||||
"certification__certification_name",
|
||||
"certification__department",
|
||||
]
|
||||
autocomplete_fields = ["member"]
|
||||
exclude = ["shop_lead_notified"]
|
||||
|
||||
@admin.display(
|
||||
description="Certification Name",
|
||||
ordering="certification_version__definition__certification_name",
|
||||
)
|
||||
def certification_name(self, obj):
|
||||
return obj.certification_version.definition.certification_name
|
||||
|
||||
@admin.display(
|
||||
description="Certification Version", ordering="certification_version__version"
|
||||
)
|
||||
def certification_version_version(self, obj):
|
||||
return obj.certification_version.version
|
||||
|
||||
@admin.display(
|
||||
description="Department",
|
||||
ordering="certification_version__definition__department",
|
||||
)
|
||||
def certification_department(self, obj):
|
||||
return obj.certification_version.definition.department
|
||||
|
||||
list_display = [
|
||||
"certification_name",
|
||||
"name",
|
||||
"certification_version_version",
|
||||
"certification_department",
|
||||
"date",
|
||||
"shop_lead_notified",
|
||||
"certified_by",
|
||||
]
|
||||
list_display_links = [
|
||||
"certification_name",
|
||||
"name",
|
||||
]
|
||||
list_filter = [
|
||||
"certification_version__definition__department",
|
||||
("shop_lead_notified", admin.EmptyFieldListFilter),
|
||||
]
|
||||
|
||||
actions = ["send_notifications"]
|
||||
|
||||
@admin.action(
|
||||
description="Notify Shop Leads and Members of selected certifications"
|
||||
)
|
||||
def send_notifications(self, request, queryset):
|
||||
try:
|
||||
emails = list(all_certification_emails(queryset))
|
||||
print(emails)
|
||||
|
||||
with mail.get_connection() as conn:
|
||||
conn.send_messages(emails)
|
||||
|
||||
for cert in queryset:
|
||||
cert.update(shop_lead_notified=Now())
|
||||
|
||||
self.message_user(
|
||||
request,
|
||||
f"{len(emails)} notifications sent for {len(queryset)} certifications",
|
||||
messages.SUCCESS,
|
||||
)
|
||||
except Exception as e:
|
||||
self.message_user(
|
||||
request,
|
||||
f"Failed to send notifications! {e}",
|
||||
messages.ERROR,
|
||||
)
|
||||
raise
|
||||
|
||||
|
||||
@admin.register(InstructorOrVendor)
|
||||
class InstructorOrVendorAdmin(admin.ModelAdmin):
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
@admin.register(SpecialProgram)
|
||||
class SpecialProgramAdmin(admin.ModelAdmin):
|
||||
search_fields = ["program_name"]
|
||||
|
||||
|
||||
@admin.register(Waiver)
|
||||
class WaiverAdmin(admin.ModelAdmin):
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
admin.site.register(CmsRedRiverVeteransScholarship)
|
5
paperwork/apps.py
Normal file
5
paperwork/apps.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PaperworkConfig(AppConfig):
|
||||
name = "paperwork"
|
102
paperwork/certification_emails.py
Normal file
102
paperwork/certification_emails.py
Normal file
@ -0,0 +1,102 @@
|
||||
from itertools import groupby
|
||||
|
||||
from django.core import mail
|
||||
from django.core.mail.message import sanitize_address
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.template import loader
|
||||
|
||||
from markdownify import markdownify
|
||||
import mdformat
|
||||
|
||||
from membershipworks.models import Member
|
||||
|
||||
|
||||
def make_multipart_email(subject, html_body, to):
|
||||
plain_body = mdformat.text(markdownify(html_body), extensions={"tables"})
|
||||
|
||||
email = mail.EmailMultiAlternatives(
|
||||
subject,
|
||||
plain_body,
|
||||
"Claremont MakerSpace Member Certification System <Certifications@ClaremontMakerSpace.org>",
|
||||
to,
|
||||
reply_to=["Claremont MakerSpace <Info@ClaremontMakerSpace.org>"],
|
||||
)
|
||||
|
||||
email.attach_alternative(html_body, "text/html")
|
||||
return email
|
||||
|
||||
|
||||
def make_department_email(department, certifications):
|
||||
template = loader.get_template("paperwork/department_certifications_email.dj.html")
|
||||
shop_leads = Member.objects.filter(
|
||||
flags__type="label", flags__name="Shop Lead: " + department
|
||||
).values_list("first_name", "account_name", "email", named=True)
|
||||
|
||||
html_body = template.render(
|
||||
{
|
||||
"shop_lead_names": [shop_lead.first_name for shop_lead in shop_leads],
|
||||
"department": department,
|
||||
"certifications": certifications,
|
||||
}
|
||||
)
|
||||
|
||||
return make_multipart_email(
|
||||
f"{len(certifications)} new CMS Certifications issued for {department}",
|
||||
html_body,
|
||||
to=[
|
||||
sanitize_address((shop_lead.account_name, shop_lead.email), "ascii")
|
||||
for shop_lead in shop_leads
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def department_emails(ordered_queryset):
|
||||
certifications_by_department = groupby(
|
||||
ordered_queryset, lambda c: c.certification_version.definition.department
|
||||
)
|
||||
|
||||
for department, certifications in certifications_by_department:
|
||||
yield make_department_email(department, list(certifications))
|
||||
|
||||
|
||||
def make_member_email(member, certifications):
|
||||
template = loader.get_template("paperwork/member_certifications_email.dj.html")
|
||||
|
||||
html_body = template.render({"member": member, "certifications": certifications})
|
||||
|
||||
return make_multipart_email(
|
||||
f"You have been issued {len(certifications)} new CMS Certifications",
|
||||
html_body,
|
||||
to=[sanitize_address((member.account_name, member.email), "ascii")],
|
||||
)
|
||||
|
||||
|
||||
def member_emails(ordered_queryset):
|
||||
certifications_by_member = groupby(
|
||||
ordered_queryset.filter(member__isnull=False), lambda c: c.member
|
||||
)
|
||||
|
||||
for member, certifications in certifications_by_member:
|
||||
yield make_member_email(member, list(certifications))
|
||||
|
||||
|
||||
def admin_email(ordered_queryset):
|
||||
template = loader.get_template("paperwork/admin_certifications_email.dj.html")
|
||||
html_body = template.render({"certifications": ordered_queryset})
|
||||
|
||||
return make_multipart_email(
|
||||
f"{len(ordered_queryset)} new CMS Certifications issued",
|
||||
html_body,
|
||||
# TODO: Admin emails should probably be from a group, not all staff
|
||||
to=[get_user_model().filter(is_staff=True).values("email", flat=True)],
|
||||
)
|
||||
|
||||
|
||||
def all_certification_emails(queryset):
|
||||
ordered_queryset = queryset.select_related(
|
||||
"certification_version__definition"
|
||||
).order_by("certification_version__definition__department")
|
||||
|
||||
yield from department_emails(ordered_queryset)
|
||||
yield from member_emails(ordered_queryset)
|
||||
yield admin_email(ordered_queryset)
|
325
paperwork/migrations/0001_initial.py
Normal file
325
paperwork/migrations/0001_initial.py
Normal file
@ -0,0 +1,325 @@
|
||||
# Generated by Django 4.0.2 on 2022-02-03 21:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("membershipworks", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CertificationDefinition",
|
||||
fields=[
|
||||
(
|
||||
"certification_identifier",
|
||||
models.AutoField(
|
||||
db_column="Certification Identifier",
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"certification_name",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Certification Name",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"department",
|
||||
models.CharField(
|
||||
blank=True, db_column="Department", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "Certification Definitions",
|
||||
"ordering": ("certification_name", "department"),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="CmsRedRiverVeteransScholarship",
|
||||
fields=[
|
||||
("serial", models.AutoField(primary_key=True, serialize=False)),
|
||||
(
|
||||
"program_name",
|
||||
models.CharField(db_column="Program Name", max_length=255),
|
||||
),
|
||||
(
|
||||
"member_name",
|
||||
models.CharField(
|
||||
blank=True, db_column="Member Name", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"discount_percent",
|
||||
models.DecimalField(
|
||||
blank=True,
|
||||
db_column="Discount Percent",
|
||||
decimal_places=0,
|
||||
max_digits=16,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"discount_code",
|
||||
models.CharField(
|
||||
blank=True, db_column="Discount Code", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_code",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Membership Code",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"start_date",
|
||||
models.DateField(blank=True, db_column="Start Date", null=True),
|
||||
),
|
||||
(
|
||||
"end_date",
|
||||
models.DateField(blank=True, db_column="End Date", null=True),
|
||||
),
|
||||
(
|
||||
"program_amount",
|
||||
models.DecimalField(
|
||||
blank=True,
|
||||
db_column="Program Amount",
|
||||
decimal_places=0,
|
||||
max_digits=16,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"program_status",
|
||||
models.CharField(
|
||||
blank=True, db_column="Program Status", max_length=16, null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "CMS Red River Veterans Scholarship",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="InstructorOrVendor",
|
||||
fields=[
|
||||
("serial", models.AutoField(primary_key=True, serialize=False)),
|
||||
("name", models.CharField(db_column="Name", max_length=255)),
|
||||
(
|
||||
"instructor_agreement_date",
|
||||
models.DateField(
|
||||
blank=True, db_column="Instructor Agreement Date", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"w9_date",
|
||||
models.DateField(blank=True, db_column="W9 date", null=True),
|
||||
),
|
||||
("phone", models.CharField(blank=True, max_length=255, null=True)),
|
||||
(
|
||||
"email_address",
|
||||
models.CharField(
|
||||
blank=True, db_column="email address", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "Instructors and Vendors",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SpecialProgram",
|
||||
fields=[
|
||||
(
|
||||
"program_name",
|
||||
models.CharField(
|
||||
db_column="Program Name",
|
||||
max_length=255,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"discount_percent",
|
||||
models.DecimalField(
|
||||
blank=True,
|
||||
db_column="Discount Percent",
|
||||
decimal_places=0,
|
||||
max_digits=16,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"discount_code",
|
||||
models.CharField(
|
||||
blank=True, db_column="Discount Code", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_code",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Membership Code",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"start_date",
|
||||
models.DateField(blank=True, db_column="Start Date", null=True),
|
||||
),
|
||||
(
|
||||
"end_date",
|
||||
models.DateField(blank=True, db_column="End Date", null=True),
|
||||
),
|
||||
(
|
||||
"program_amount",
|
||||
models.DecimalField(
|
||||
blank=True,
|
||||
db_column="Program Amount",
|
||||
decimal_places=0,
|
||||
max_digits=16,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"program_status",
|
||||
models.CharField(
|
||||
blank=True, db_column="Program Status", max_length=16, null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "Special_Programs",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Waiver",
|
||||
fields=[
|
||||
(
|
||||
"number",
|
||||
models.AutoField(
|
||||
db_column="Number", primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("name", models.CharField(db_column="Name", max_length=255)),
|
||||
("date", models.DateField(db_column="Date")),
|
||||
(
|
||||
"emergency_contact_name",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Emergency Contact Name",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"emergency_contact_number",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Emergency Contact Number",
|
||||
max_length=25,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"waiver_version",
|
||||
models.CharField(db_column="Waiver version", max_length=64),
|
||||
),
|
||||
(
|
||||
"guardian_name",
|
||||
models.CharField(
|
||||
blank=True, db_column="Guardian Name", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"guardian_relation",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
db_column="Guardian Relation",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"guardian_date",
|
||||
models.DateField(blank=True, db_column="Guardian Date", null=True),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "Waivers",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Certification",
|
||||
fields=[
|
||||
(
|
||||
"number",
|
||||
models.AutoField(
|
||||
db_column="Number", primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("name", models.CharField(db_column="Name", max_length=255)),
|
||||
(
|
||||
"certified_by",
|
||||
models.CharField(
|
||||
blank=True, db_column="Certified_By", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
("date", models.DateField(blank=True, db_column="Date", null=True)),
|
||||
(
|
||||
"version",
|
||||
models.CharField(
|
||||
blank=True, db_column="Version", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"shop_lead_notified",
|
||||
models.DateTimeField(
|
||||
blank=True, db_column="Shop Lead Notified", null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"certification",
|
||||
models.ForeignKey(
|
||||
db_column="Certification",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="paperwork.certificationdefinition",
|
||||
),
|
||||
),
|
||||
(
|
||||
"member",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
db_column="uid",
|
||||
db_constraint=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="membershipworks.member",
|
||||
),
|
||||
),
|
||||
(
|
||||
"notes",
|
||||
models.CharField(
|
||||
blank=True, db_column="Notes", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"db_table": "Certifications",
|
||||
},
|
||||
),
|
||||
]
|
88
paperwork/migrations/0002_add_certification_version_model.py
Normal file
88
paperwork/migrations/0002_add_certification_version_model.py
Normal file
@ -0,0 +1,88 @@
|
||||
# (Partially) Generated by Django 4.0.2 on 2022-02-04 18:01
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def migrate_certification_version_forward(apps, schema_editor):
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
Certification = apps.get_model("paperwork", "Certification")
|
||||
CertificationVersion = apps.get_model("paperwork", "CertificationVersion")
|
||||
|
||||
for certification in Certification.objects.using(db_alias).all():
|
||||
(version, _) = CertificationVersion.objects.using(db_alias).get_or_create(
|
||||
definition=certification.certification, version=certification.version
|
||||
)
|
||||
certification.certification_version = version
|
||||
certification.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("paperwork", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CertificationVersion",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"version",
|
||||
models.CharField(
|
||||
blank=True, db_column="Version", max_length=255, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"definition",
|
||||
models.ForeignKey(
|
||||
db_column="Certification",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="paperwork.certificationdefinition",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="certificationversion",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("definition", "version"), name="unique_certification_version"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="certification",
|
||||
name="certification_version",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="paperwork.certificationversion",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.RunPython(migrate_certification_version_forward),
|
||||
migrations.AlterField(
|
||||
model_name="certification",
|
||||
name="certification_version",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="paperwork.certificationversion",
|
||||
),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="certification",
|
||||
name="certification",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="certification",
|
||||
name="version",
|
||||
),
|
||||
]
|
0
paperwork/migrations/__init__.py
Normal file
0
paperwork/migrations/__init__.py
Normal file
193
paperwork/models.py
Normal file
193
paperwork/models.py
Normal file
@ -0,0 +1,193 @@
|
||||
from django.db import models
|
||||
|
||||
from membershipworks.models import Member
|
||||
|
||||
|
||||
class CmsRedRiverVeteransScholarship(models.Model):
|
||||
serial = models.AutoField(primary_key=True)
|
||||
program_name = models.CharField(db_column="Program Name", max_length=255)
|
||||
member_name = models.CharField(
|
||||
db_column="Member Name", max_length=255, blank=True, null=True
|
||||
)
|
||||
discount_percent = models.DecimalField(
|
||||
db_column="Discount Percent",
|
||||
max_digits=16,
|
||||
decimal_places=0,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
discount_code = models.CharField(
|
||||
db_column="Discount Code", max_length=255, blank=True, null=True
|
||||
)
|
||||
membership_code = models.CharField(
|
||||
db_column="Membership Code", max_length=255, blank=True, null=True
|
||||
)
|
||||
start_date = models.DateField(db_column="Start Date", blank=True, null=True)
|
||||
end_date = models.DateField(db_column="End Date", blank=True, null=True)
|
||||
program_amount = models.DecimalField(
|
||||
db_column="Program Amount",
|
||||
max_digits=16,
|
||||
decimal_places=0,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
program_status = models.CharField(
|
||||
db_column="Program Status", max_length=16, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.program_name} {self.member_name}"
|
||||
|
||||
class Meta:
|
||||
db_table = "CMS Red River Veterans Scholarship"
|
||||
|
||||
|
||||
class CertificationDefinition(models.Model):
|
||||
certification_identifier = models.AutoField(
|
||||
db_column="Certification Identifier", primary_key=True
|
||||
)
|
||||
certification_name = models.CharField(
|
||||
db_column="Certification Name", max_length=255, blank=True, null=True
|
||||
)
|
||||
department = models.CharField(
|
||||
db_column="Department", max_length=255, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.certification_name} <{self.department}>"
|
||||
|
||||
class Meta:
|
||||
db_table = "Certification Definitions"
|
||||
ordering = ("certification_name", "department")
|
||||
|
||||
|
||||
class CertificationVersion(models.Model):
|
||||
definition = models.ForeignKey(
|
||||
CertificationDefinition, on_delete=models.PROTECT, db_column="Certification"
|
||||
)
|
||||
version = models.CharField(
|
||||
db_column="Version", max_length=255, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.definition} [{self.version}]"
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=["definition", "version"], name="unique_certification_version"
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class Certification(models.Model):
|
||||
number = models.AutoField(db_column="Number", primary_key=True)
|
||||
certification_version = models.ForeignKey(
|
||||
CertificationVersion, on_delete=models.PROTECT
|
||||
)
|
||||
name = models.CharField(db_column="Name", max_length=255)
|
||||
member = models.ForeignKey(
|
||||
Member,
|
||||
on_delete=models.PROTECT,
|
||||
to_field="uid",
|
||||
db_column="uid",
|
||||
blank=True,
|
||||
null=True,
|
||||
db_constraint=False,
|
||||
)
|
||||
certified_by = models.CharField(
|
||||
db_column="Certified_By", max_length=255, blank=True, null=True
|
||||
)
|
||||
date = models.DateField(db_column="Date", blank=True, null=True)
|
||||
shop_lead_notified = models.DateTimeField(
|
||||
db_column="Shop Lead Notified", blank=True, null=True
|
||||
)
|
||||
notes = models.CharField(db_column="Notes", max_length=255, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} - {self.certification_version}"
|
||||
|
||||
class Meta:
|
||||
db_table = "Certifications"
|
||||
|
||||
|
||||
class InstructorOrVendor(models.Model):
|
||||
serial = models.AutoField(primary_key=True)
|
||||
name = models.CharField(db_column="Name", max_length=255)
|
||||
instructor_agreement_date = models.DateField(
|
||||
db_column="Instructor Agreement Date", blank=True, null=True
|
||||
)
|
||||
w9_date = models.DateField(db_column="W9 date", blank=True, null=True)
|
||||
phone = models.CharField(max_length=255, blank=True, null=True)
|
||||
email_address = models.CharField(
|
||||
db_column="email address", max_length=255, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
class Meta:
|
||||
db_table = "Instructors and Vendors"
|
||||
|
||||
|
||||
class SpecialProgram(models.Model):
|
||||
program_name = models.CharField(
|
||||
db_column="Program Name", primary_key=True, max_length=255
|
||||
)
|
||||
discount_percent = models.DecimalField(
|
||||
db_column="Discount Percent",
|
||||
max_digits=16,
|
||||
decimal_places=0,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
discount_code = models.CharField(
|
||||
db_column="Discount Code", max_length=255, blank=True, null=True
|
||||
)
|
||||
membership_code = models.CharField(
|
||||
db_column="Membership Code", max_length=255, blank=True, null=True
|
||||
)
|
||||
start_date = models.DateField(db_column="Start Date", blank=True, null=True)
|
||||
end_date = models.DateField(db_column="End Date", blank=True, null=True)
|
||||
program_amount = models.DecimalField(
|
||||
db_column="Program Amount",
|
||||
max_digits=16,
|
||||
decimal_places=0,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
program_status = models.CharField(
|
||||
db_column="Program Status", max_length=16, blank=True, null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.program_name
|
||||
|
||||
class Meta:
|
||||
db_table = "Special_Programs"
|
||||
|
||||
|
||||
class Waiver(models.Model):
|
||||
number = models.AutoField(db_column="Number", primary_key=True)
|
||||
name = models.CharField(db_column="Name", max_length=255)
|
||||
date = models.DateField(db_column="Date")
|
||||
emergency_contact_name = models.CharField(
|
||||
db_column="Emergency Contact Name", max_length=255, blank=True, null=True
|
||||
)
|
||||
emergency_contact_number = models.CharField(
|
||||
db_column="Emergency Contact Number", max_length=25, blank=True, null=True
|
||||
)
|
||||
waiver_version = models.CharField(db_column="Waiver version", max_length=64)
|
||||
guardian_name = models.CharField(
|
||||
db_column="Guardian Name", max_length=255, blank=True, null=True
|
||||
)
|
||||
guardian_relation = models.CharField(
|
||||
db_column="Guardian Relation", max_length=255, blank=True, null=True
|
||||
)
|
||||
guardian_date = models.DateField(db_column="Guardian Date", blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} {self.date}"
|
||||
|
||||
class Meta:
|
||||
db_table = "Waivers"
|
22
paperwork/routers.py
Normal file
22
paperwork/routers.py
Normal file
@ -0,0 +1,22 @@
|
||||
class PaperworkRouter:
|
||||
app_label = "paperwork"
|
||||
related_app_labels = {"paperwork", "membershipworks"}
|
||||
db = "cms"
|
||||
|
||||
def db_for_read(self, model, **hints):
|
||||
if model._meta.app_label == self.app_label:
|
||||
return self.db
|
||||
return None
|
||||
|
||||
def db_for_write(self, model, **hints):
|
||||
if model._meta.app_label == self.app_label:
|
||||
return self.db
|
||||
return None
|
||||
|
||||
def allow_relation(self, obj1, obj2, **hints):
|
||||
if (
|
||||
obj1._meta.app_label in self.related_app_labels
|
||||
or obj2._meta.app_label in self.related_app_labels
|
||||
):
|
||||
return True
|
||||
return None
|
@ -0,0 +1,23 @@
|
||||
<p>
|
||||
The following Claremont MakerSpace Member Certifications have been issued:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Certification</th>
|
||||
<th>Version</th>
|
||||
<th>Member</th>
|
||||
<th>Department</th>
|
||||
<th>Certified By</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
{% for certification in certifications %}
|
||||
<tr>
|
||||
<td>{{ certification.certification_version.definition.certification_name }}</td>
|
||||
<td>{{ certification.certification_version.version }}</td>
|
||||
<td>{{ certification.member }}</td>
|
||||
<td>{{ certification.certification_version.definition.department }}</td>
|
||||
<td>{{ certification.certified_by }}</td>
|
||||
<td>{{ certification.date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
@ -0,0 +1,24 @@
|
||||
<p>
|
||||
Dear <b>{{ shop_lead_names|join:", " }}</b>:
|
||||
</p>
|
||||
<p>
|
||||
The following Claremont MakerSpace Member Certifications have been issued for the <b>{{ department }}</b>:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Certification</th>
|
||||
<th>Version</th>
|
||||
<th>Member</th>
|
||||
<th>Certified By</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
{% for certification in certifications %}
|
||||
<tr>
|
||||
<td>{{ certification.certification_version.definition.certification_name }}</td>
|
||||
<td>{{ certification.certification_version.version }}</td>
|
||||
<td>{{ certification.member }}</td>
|
||||
<td>{{ certification.certified_by }}</td>
|
||||
<td>{{ certification.date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
@ -0,0 +1,24 @@
|
||||
<p>
|
||||
Dear <b>{{ member.first_name }}</b>:
|
||||
</p>
|
||||
<p>
|
||||
You have been issued the following Claremont MakerSpace Member Certifications:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<th>Certification</th>
|
||||
<th>Version</th>
|
||||
<th>Department</th>
|
||||
<th>Certified By</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
{% for certification in certifications %}
|
||||
<tr>
|
||||
<td>{{ certification.certification_version.definition.certification_name }}</td>
|
||||
<td>{{ certification.certification_version.version }}</td>
|
||||
<td>{{ certification.certification_version.definition.department }}</td>
|
||||
<td>{{ certification.certified_by }}</td>
|
||||
<td>{{ certification.date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
3
paperwork/tests.py
Normal file
3
paperwork/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
3
paperwork/views.py
Normal file
3
paperwork/views.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
662
pdm.lock
generated
Normal file
662
pdm.lock
generated
Normal file
@ -0,0 +1,662 @@
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.5.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "ASGI specs, helper code, and adapters"
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "21.4.0"
|
||||
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
summary = "Classes Without Boilerplate"
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.10.0"
|
||||
requires_python = ">3.0.0"
|
||||
summary = "Screen-scraping library"
|
||||
dependencies = [
|
||||
"soupsieve>1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "22.1.0"
|
||||
requires_python = ">=3.6.2"
|
||||
summary = "The uncompromising code formatter."
|
||||
dependencies = [
|
||||
"click>=8.0.0",
|
||||
"mypy-extensions>=0.4.3",
|
||||
"pathspec>=0.9.0",
|
||||
"platformdirs>=2",
|
||||
"tomli>=1.1.0",
|
||||
"typing-extensions>=3.10.0.0; python_version < \"3.10\"",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.0.3"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Composable command line interface toolkit"
|
||||
dependencies = [
|
||||
"colorama; platform_system == \"Windows\"",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.4"
|
||||
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
summary = "Cross-platform colored terminal text."
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "4.0.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||
dependencies = [
|
||||
"asgiref<4,>=3.4.1",
|
||||
"sqlparse>=0.2.2",
|
||||
"tzdata; sys_platform == \"win32\"",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-admin-logs"
|
||||
version = "1.0.2"
|
||||
requires_python = ">=3.5"
|
||||
summary = "View, delete or disable Django admin log entries."
|
||||
dependencies = [
|
||||
"Django>=2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-auth-ldap"
|
||||
version = "4.0.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Django LDAP authentication backend."
|
||||
dependencies = [
|
||||
"Django>=2.2",
|
||||
"python-ldap>=3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-markdownx"
|
||||
version = "4.0.0b1"
|
||||
summary = "A comprehensive Markdown editor built for Django."
|
||||
dependencies = [
|
||||
"Django",
|
||||
"Markdown",
|
||||
"Pillow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-recurrence"
|
||||
version = "1.11.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Django utility wrapping dateutil.rrule"
|
||||
dependencies = [
|
||||
"django>=2.2",
|
||||
"python-dateutil",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "django-widget-tweaks"
|
||||
version = "1.4.12"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Tweak the form field rendering in templates, not in python-level form definitions."
|
||||
|
||||
[[package]]
|
||||
name = "djlint"
|
||||
version = "0.7.4"
|
||||
requires_python = ">=3.7,<4.0"
|
||||
summary = "HTML Template Linter and Formatter"
|
||||
dependencies = [
|
||||
"PyYAML<7.0,>=6.0",
|
||||
"click<9.0.0,>=8.0.1",
|
||||
"colorama<0.5.0,>=0.4.4",
|
||||
"importlib-metadata<5.0.0,>=4.10.1",
|
||||
"pathspec<0.10.0,>=0.9.0",
|
||||
"regex<2023.0.0,>=2022.1.18",
|
||||
"tomlkit<0.9.0,>=0.8.0",
|
||||
"tqdm<5.0.0,>=4.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.13.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "4.11.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Read metadata from Python packages"
|
||||
dependencies = [
|
||||
"zipp>=0.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "3.3.6"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Python implementation of Markdown."
|
||||
dependencies = [
|
||||
"importlib-metadata>=4.4; python_version < \"3.10\"",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "2.0.1"
|
||||
requires_python = "~=3.6"
|
||||
summary = "Python port of markdown-it. Markdown parsing, done right!"
|
||||
dependencies = [
|
||||
"attrs<22,>=19",
|
||||
"mdurl~=0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdownify"
|
||||
version = "0.10.3"
|
||||
summary = "Convert HTML to markdown."
|
||||
dependencies = [
|
||||
"beautifulsoup4<5,>=4.9",
|
||||
"six<2,>=1.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdformat"
|
||||
version = "0.7.13"
|
||||
requires_python = ">=3.7,<4.0"
|
||||
summary = "CommonMark compliant Markdown formatter"
|
||||
dependencies = [
|
||||
"importlib-metadata>=3.6.0; python_version < \"3.10\"",
|
||||
"markdown-it-py<3.0.0,>=1.0.0b2",
|
||||
"tomli>=1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdformat-tables"
|
||||
version = "0.4.1"
|
||||
requires_python = ">=3.6.1"
|
||||
summary = "An mdformat plugin for rendering tables."
|
||||
dependencies = [
|
||||
"mdformat<0.8.0,>=0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Markdown URL utilities"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
summary = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
|
||||
[[package]]
|
||||
name = "mysqlclient"
|
||||
version = "2.1.0"
|
||||
requires_python = ">=3.5"
|
||||
summary = "Python interface to MySQL"
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.9.0"
|
||||
summary = "Utility library for gitignore style pattern matching of file paths."
|
||||
|
||||
[[package]]
|
||||
name = "pillow"
|
||||
version = "9.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Python Imaging Library (Fork)"
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "2.5.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
|
||||
[[package]]
|
||||
name = "pyasn1"
|
||||
version = "0.4.8"
|
||||
summary = "ASN.1 types and codecs"
|
||||
|
||||
[[package]]
|
||||
name = "pyasn1-modules"
|
||||
version = "0.2.8"
|
||||
summary = "A collection of ASN.1-based protocols modules."
|
||||
dependencies = [
|
||||
"pyasn1<0.5.0,>=0.4.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.8.2"
|
||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||
summary = "Extensions to the standard Python datetime module"
|
||||
dependencies = [
|
||||
"six>=1.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-ldap"
|
||||
version = "3.4.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Python modules for implementing LDAP clients"
|
||||
dependencies = [
|
||||
"pyasn1-modules>=0.1.5",
|
||||
"pyasn1>=0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0"
|
||||
requires_python = ">=3.6"
|
||||
summary = "YAML parser and emitter for Python"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2022.1.18"
|
||||
summary = "Alternative regular expression module, to replace re."
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
summary = "Python 2 and 3 compatibility utilities"
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.3.1"
|
||||
requires_python = ">=3.6"
|
||||
summary = "A modern CSS selector implementation for Beautiful Soup."
|
||||
|
||||
[[package]]
|
||||
name = "sqlparse"
|
||||
version = "0.4.2"
|
||||
requires_python = ">=3.5"
|
||||
summary = "A non-validating SQL parser."
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A lil' TOML parser"
|
||||
|
||||
[[package]]
|
||||
name = "tomlkit"
|
||||
version = "0.8.0"
|
||||
requires_python = ">=3.6,<4.0"
|
||||
summary = "Style preserving TOML library"
|
||||
|
||||
[[package]]
|
||||
name = "tqdm"
|
||||
version = "4.62.3"
|
||||
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
||||
summary = "Fast, Extensible Progress Meter"
|
||||
dependencies = [
|
||||
"colorama; platform_system == \"Windows\"",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.1.1"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Backported and Experimental Type Hints for Python 3.6+"
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2021.5"
|
||||
requires_python = ">=2"
|
||||
summary = "Provider of IANA time zone data"
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.17.4"
|
||||
requires_python = ">=3.7"
|
||||
summary = "The lightning-fast ASGI server."
|
||||
dependencies = [
|
||||
"asgiref>=3.4.0",
|
||||
"click>=7.0",
|
||||
"h11>=0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.7.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
|
||||
[metadata]
|
||||
lock_version = "3.1"
|
||||
content_hash = "sha256:46cf64b2180e5ba20253e265677b5c645952556baa19c194c904fa3a8af42741"
|
||||
|
||||
[metadata.files]
|
||||
"asgiref 3.5.0" = [
|
||||
{file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"},
|
||||
{file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"},
|
||||
]
|
||||
"attrs 21.4.0" = [
|
||||
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
|
||||
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
|
||||
]
|
||||
"beautifulsoup4 4.10.0" = [
|
||||
{file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
|
||||
{file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
|
||||
]
|
||||
"black 22.1.0" = [
|
||||
{file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"},
|
||||
{file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"},
|
||||
{file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"},
|
||||
{file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"},
|
||||
{file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"},
|
||||
{file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"},
|
||||
{file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"},
|
||||
{file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"},
|
||||
{file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"},
|
||||
{file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"},
|
||||
{file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"},
|
||||
{file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"},
|
||||
{file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"},
|
||||
{file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"},
|
||||
{file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"},
|
||||
{file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"},
|
||||
{file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"},
|
||||
{file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"},
|
||||
{file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"},
|
||||
{file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"},
|
||||
{file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"},
|
||||
{file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"},
|
||||
{file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"},
|
||||
]
|
||||
"click 8.0.3" = [
|
||||
{file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
|
||||
{file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
|
||||
]
|
||||
"colorama 0.4.4" = [
|
||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||
]
|
||||
"django 4.0.2" = [
|
||||
{file = "Django-4.0.2-py3-none-any.whl", hash = "sha256:996495c58bff749232426c88726d8cd38d24c94d7c1d80835aafffa9bc52985a"},
|
||||
{file = "Django-4.0.2.tar.gz", hash = "sha256:110fb58fb12eca59e072ad59fc42d771cd642dd7a2f2416582aa9da7a8ef954a"},
|
||||
]
|
||||
"django-admin-logs 1.0.2" = [
|
||||
{file = "django_admin_logs-1.0.2-py3-none-any.whl", hash = "sha256:81753c20d372bc5562fe4a09090418bbb61b308388e851b19192873a472fa3d1"},
|
||||
{file = "django-admin-logs-1.0.2.tar.gz", hash = "sha256:aedb5df940d32c10423d65136343bc009727df8a5a49ed0196e65241d823a890"},
|
||||
]
|
||||
"django-auth-ldap 4.0.0" = [
|
||||
{file = "django_auth_ldap-4.0.0-py3-none-any.whl", hash = "sha256:94119c94981809124d3dc4bed974f71c7a980666896df626f556a88a5fe0b59c"},
|
||||
{file = "django-auth-ldap-4.0.0.tar.gz", hash = "sha256:276f79e624ce083ce13f161387f65ff1c0efe83ef8a42f2b9830d43317b15239"},
|
||||
]
|
||||
"django-markdownx 4.0.0b1" = [
|
||||
{file = "django_markdownx-4.0.0b1-py2.py3-none-any.whl", hash = "sha256:e862ddc3e0aa8a2d6bb297fcf115a35b36b874ea5f07463577f1b34aa5073c3e"},
|
||||
{file = "django-markdownx-4.0.0b1.tar.gz", hash = "sha256:4f0ee12c38a9aeab9f8da0588ca169ec32c4dad84fc90dc4e9f56481b5de3473"},
|
||||
]
|
||||
"django-recurrence 1.11.1" = [
|
||||
{file = "django_recurrence-1.11.1-py3-none-any.whl", hash = "sha256:0c65f30872599b5813a9bab6952dada23c55894f28674490a753ada559f14bc5"},
|
||||
{file = "django-recurrence-1.11.1.tar.gz", hash = "sha256:9c89444e651a78c587f352c5f63eda48ab2f53996347b9fcdff2d248f4fcff70"},
|
||||
]
|
||||
"django-widget-tweaks 1.4.12" = [
|
||||
{file = "django_widget_tweaks-1.4.12-py3-none-any.whl", hash = "sha256:fe6b17d5d595c63331f300917980db2afcf71f240ab9341b954aea8f45d25b9a"},
|
||||
{file = "django-widget-tweaks-1.4.12.tar.gz", hash = "sha256:9bfc5c705684754a83cc81da328b39ad1b80f32bd0f4340e2a810cbab4b0c00e"},
|
||||
]
|
||||
"djlint 0.7.4" = [
|
||||
{file = "djlint-0.7.4-py3-none-any.whl", hash = "sha256:1bced1cf7b0712b00d33a8df8418aff56ccea01d21b79a94ca6e876cf763e6b5"},
|
||||
{file = "djlint-0.7.4.tar.gz", hash = "sha256:aad18147db996cb93d63493126ad29d13251f60e6e45f98ab0e9b6252875ccf0"},
|
||||
]
|
||||
"h11 0.13.0" = [
|
||||
{file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"},
|
||||
{file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"},
|
||||
]
|
||||
"importlib-metadata 4.11.0" = [
|
||||
{file = "importlib_metadata-4.11.0-py3-none-any.whl", hash = "sha256:6affcdb3aec542dd98df8211e730bba6c5f2bec8288d47bacacde898f548c9ad"},
|
||||
{file = "importlib_metadata-4.11.0.tar.gz", hash = "sha256:9e5e553bbba1843cb4a00823014b907616be46ee503d2b9ba001d214a8da218f"},
|
||||
]
|
||||
"markdown 3.3.6" = [
|
||||
{file = "Markdown-3.3.6-py3-none-any.whl", hash = "sha256:9923332318f843411e9932237530df53162e29dc7a4e2b91e35764583c46c9a3"},
|
||||
{file = "Markdown-3.3.6.tar.gz", hash = "sha256:76df8ae32294ec39dcf89340382882dfa12975f87f45c3ed1ecdb1e8cefc7006"},
|
||||
]
|
||||
"markdown-it-py 2.0.1" = [
|
||||
{file = "markdown_it_py-2.0.1-py3-none-any.whl", hash = "sha256:31974138ca8cafbcb62213f4974b29571b940e78364584729233f59b8dfdb8bd"},
|
||||
{file = "markdown-it-py-2.0.1.tar.gz", hash = "sha256:7b5c153ae1ab2cde00a33938bce68f3ad5d68fbe363f946de7d28555bed4e08a"},
|
||||
]
|
||||
"markdownify 0.10.3" = [
|
||||
{file = "markdownify-0.10.3-py3-none-any.whl", hash = "sha256:edad0ad3896ec7460d05537ad804bbb3614877c6cd0df27b56dee218236d9ce2"},
|
||||
{file = "markdownify-0.10.3.tar.gz", hash = "sha256:782e310390cd5e4bde7543ceb644598c78b9824ee9f8d7ef9f9f4f8782e46974"},
|
||||
]
|
||||
"mdformat 0.7.13" = [
|
||||
{file = "mdformat-0.7.13-py3-none-any.whl", hash = "sha256:accca5fb17da270b63d27ce05c86eba1e8dd2a0342e9c7bb4cff4e50040b65bb"},
|
||||
{file = "mdformat-0.7.13.tar.gz", hash = "sha256:28ede5e435ba84154e332edced33ee24fa30453d8fcbfbf7e41cd126a0851112"},
|
||||
]
|
||||
"mdformat-tables 0.4.1" = [
|
||||
{file = "mdformat_tables-0.4.1-py3-none-any.whl", hash = "sha256:981f3dc7350027f78e3fd6a5fe8a16e123eec423af2d140e588d855751501019"},
|
||||
{file = "mdformat_tables-0.4.1.tar.gz", hash = "sha256:3024e88e9d29d7b8bb07fd6b59c9d5dcf14d2060122be29e30e72d27b65d7da9"},
|
||||
]
|
||||
"mdurl 0.1.0" = [
|
||||
{file = "mdurl-0.1.0-py3-none-any.whl", hash = "sha256:40654d6dcb8d21501ed13c21cc0bd6fc42ff07ceb8be30029e5ae63ebc2ecfda"},
|
||||
{file = "mdurl-0.1.0.tar.gz", hash = "sha256:94873a969008ee48880fb21bad7de0349fef529f3be178969af5817239e9b990"},
|
||||
]
|
||||
"mypy-extensions 0.4.3" = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
"mysqlclient 2.1.0" = [
|
||||
{file = "mysqlclient-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:02c8826e6add9b20f4cb12dcf016485f7b1d6e30356a1204d05431867a1b3947"},
|
||||
{file = "mysqlclient-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b62d23c11c516cedb887377c8807628c1c65d57593b57853186a6ee18b0c6a5b"},
|
||||
{file = "mysqlclient-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2c8410f54492a3d2488a6a53e2d85b7e016751a1e7d116e7aea9c763f59f5e8c"},
|
||||
{file = "mysqlclient-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:e6279263d5a9feca3e0edbc2b2a52c057375bf301d47da2089c075ff76331d14"},
|
||||
{file = "mysqlclient-2.1.0.tar.gz", hash = "sha256:973235686f1b720536d417bf0a0d39b4ab3d5086b2b6ad5e6752393428c02b12"},
|
||||
]
|
||||
"pathspec 0.9.0" = [
|
||||
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
|
||||
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
||||
]
|
||||
"pillow 9.0.1" = [
|
||||
{file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"},
|
||||
{file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"},
|
||||
{file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"},
|
||||
{file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"},
|
||||
{file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"},
|
||||
{file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"},
|
||||
{file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"},
|
||||
{file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"},
|
||||
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"},
|
||||
{file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"},
|
||||
{file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"},
|
||||
{file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"},
|
||||
]
|
||||
"platformdirs 2.5.0" = [
|
||||
{file = "platformdirs-2.5.0-py3-none-any.whl", hash = "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb"},
|
||||
{file = "platformdirs-2.5.0.tar.gz", hash = "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b"},
|
||||
]
|
||||
"pyasn1 0.4.8" = [
|
||||
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
|
||||
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
|
||||
]
|
||||
"pyasn1-modules 0.2.8" = [
|
||||
{file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"},
|
||||
{file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"},
|
||||
]
|
||||
"python-dateutil 2.8.2" = [
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
]
|
||||
"python-ldap 3.4.0" = [
|
||||
{file = "python-ldap-3.4.0.tar.gz", hash = "sha256:60464c8fc25e71e0fd40449a24eae482dcd0fb7fcf823e7de627a6525b3e0d12"},
|
||||
]
|
||||
"pyyaml 6.0" = [
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
|
||||
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
|
||||
]
|
||||
"regex 2022.1.18" = [
|
||||
{file = "regex-2022.1.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34316bf693b1d2d29c087ee7e4bb10cdfa39da5f9c50fa15b07489b4ab93a1b5"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a0b9f6a1a15d494b35f25ed07abda03209fa76c33564c09c9e81d34f4b919d7"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f99112aed4fb7cee00c7f77e8b964a9b10f69488cdff626ffd797d02e2e4484f"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a2bf98ac92f58777c0fafc772bf0493e67fcf677302e0c0a630ee517a43b949"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8618d9213a863c468a865e9d2ec50221015f7abf52221bc927152ef26c484b4c"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b52cc45e71657bc4743a5606d9023459de929b2a198d545868e11898ba1c3f59"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e12949e5071c20ec49ef00c75121ed2b076972132fc1913ddf5f76cae8d10b4"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b02e3e72665cd02afafb933453b0c9f6c59ff6e3708bd28d0d8580450e7e88af"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:abfcb0ef78df0ee9df4ea81f03beea41849340ce33a4c4bd4dbb99e23ec781b6"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6213713ac743b190ecbf3f316d6e41d099e774812d470422b3a0f137ea635832"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:61ebbcd208d78658b09e19c78920f1ad38936a0aa0f9c459c46c197d11c580a0"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b013f759cd69cb0a62de954d6d2096d648bc210034b79b1881406b07ed0a83f9"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9187500d83fd0cef4669385cbb0961e227a41c0c9bc39219044e35810793edf7"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-win32.whl", hash = "sha256:94c623c331a48a5ccc7d25271399aff29729fa202c737ae3b4b28b89d2b0976d"},
|
||||
{file = "regex-2022.1.18-cp310-cp310-win_amd64.whl", hash = "sha256:1a171eaac36a08964d023eeff740b18a415f79aeb212169080c170ec42dd5184"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:49810f907dfe6de8da5da7d2b238d343e6add62f01a15d03e2195afc180059ed"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d2f5c3f7057530afd7b739ed42eb04f1011203bc5e4663e1e1d01bb50f813e3"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85ffd6b1cb0dfb037ede50ff3bef80d9bf7fa60515d192403af6745524524f3b"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba37f11e1d020969e8a779c06b4af866ffb6b854d7229db63c5fdddfceaa917f"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e27ea1ebe4a561db75a880ac659ff439dec7f55588212e71700bb1ddd5af9"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:37978254d9d00cda01acc1997513f786b6b971e57b778fbe7c20e30ae81a97f3"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54a1eb9fd38f2779e973d2f8958fd575b532fe26013405d1afb9ee2374e7ab8"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:768632fd8172ae03852e3245f11c8a425d95f65ff444ce46b3e673ae5b057b74"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:de2923886b5d3214be951bc2ce3f6b8ac0d6dfd4a0d0e2a4d2e5523d8046fdfb"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:1333b3ce73269f986b1fa4d5d395643810074dc2de5b9d262eb258daf37dc98f"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:d19a34f8a3429bd536996ad53597b805c10352a8561d8382e05830df389d2b43"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8d2f355a951f60f0843f2368b39970e4667517e54e86b1508e76f92b44811a8a"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-win32.whl", hash = "sha256:2245441445099411b528379dee83e56eadf449db924648e5feb9b747473f42e3"},
|
||||
{file = "regex-2022.1.18-cp36-cp36m-win_amd64.whl", hash = "sha256:25716aa70a0d153cd844fe861d4f3315a6ccafce22b39d8aadbf7fcadff2b633"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7e070d3aef50ac3856f2ef5ec7214798453da878bb5e5a16c16a61edf1817cc3"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22709d701e7037e64dae2a04855021b62efd64a66c3ceed99dfd684bfef09e38"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9099bf89078675c372339011ccfc9ec310310bf6c292b413c013eb90ffdcafc"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04611cc0f627fc4a50bc4a9a2e6178a974c6a6a4aa9c1cca921635d2c47b9c87"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:552a39987ac6655dad4bf6f17dd2b55c7b0c6e949d933b8846d2e312ee80005a"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e031899cb2bc92c0cf4d45389eff5b078d1936860a1be3aa8c94fa25fb46ed8"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2dacb3dae6b8cc579637a7b72f008bff50a94cde5e36e432352f4ca57b9e54c4"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e5c31d70a478b0ca22a9d2d76d520ae996214019d39ed7dd93af872c7f301e52"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bb804c7d0bfbd7e3f33924ff49757de9106c44e27979e2492819c16972ec0da2"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:36b2d700a27e168fa96272b42d28c7ac3ff72030c67b32f37c05616ebd22a202"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:16f81025bb3556eccb0681d7946e2b35ff254f9f888cff7d2120e8826330315c"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:da80047524eac2acf7c04c18ac7a7da05a9136241f642dd2ed94269ef0d0a45a"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-win32.whl", hash = "sha256:6ca45359d7a21644793de0e29de497ef7f1ae7268e346c4faf87b421fea364e6"},
|
||||
{file = "regex-2022.1.18-cp37-cp37m-win_amd64.whl", hash = "sha256:38289f1690a7e27aacd049e420769b996826f3728756859420eeee21cc857118"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6014038f52b4b2ac1fa41a58d439a8a00f015b5c0735a0cd4b09afe344c94899"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b5d6f9aed3153487252d00a18e53f19b7f52a1651bc1d0c4b5844bc286dfa52"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d24b03daf7415f78abc2d25a208f234e2c585e5e6f92f0204d2ab7b9ab48e3"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf594cc7cc9d528338d66674c10a5b25e3cde7dd75c3e96784df8f371d77a298"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd914db437ec25bfa410f8aa0aa2f3ba87cdfc04d9919d608d02330947afaeab"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b6840b6448203228a9d8464a7a0d99aa8fa9f027ef95fe230579abaf8a6ee1"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11772be1eb1748e0e197a40ffb82fb8fd0d6914cd147d841d9703e2bef24d288"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a602bdc8607c99eb5b391592d58c92618dcd1537fdd87df1813f03fed49957a6"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7e26eac9e52e8ce86f915fd33380f1b6896a2b51994e40bb094841e5003429b4"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:519c0b3a6fbb68afaa0febf0d28f6c4b0a1074aefc484802ecb9709faf181607"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3c7ea86b9ca83e30fa4d4cd0eaf01db3ebcc7b2726a25990966627e39577d729"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:51f02ca184518702975b56affde6c573ebad4e411599005ce4468b1014b4786c"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:385ccf6d011b97768a640e9d4de25412204fbe8d6b9ae39ff115d4ff03f6fe5d"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-win32.whl", hash = "sha256:1f8c0ae0a0de4e19fddaaff036f508db175f6f03db318c80bbc239a1def62d02"},
|
||||
{file = "regex-2022.1.18-cp38-cp38-win_amd64.whl", hash = "sha256:760c54ad1b8a9b81951030a7e8e7c3ec0964c1cb9fee585a03ff53d9e531bb8e"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:93c20777a72cae8620203ac11c4010365706062aa13aaedd1a21bb07adbb9d5d"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6aa427c55a0abec450bca10b64446331b5ca8f79b648531138f357569705bc4a"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38baee6bdb7fe1b110b6b3aaa555e6e872d322206b7245aa39572d3fc991ee4"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:752e7ddfb743344d447367baa85bccd3629c2c3940f70506eb5f01abce98ee68"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8acef4d8a4353f6678fd1035422a937c2170de58a2b29f7da045d5249e934101"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c73d2166e4b210b73d1429c4f1ca97cea9cc090e5302df2a7a0a96ce55373f1c"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24c89346734a4e4d60ecf9b27cac4c1fee3431a413f7aa00be7c4d7bbacc2c4d"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:596f5ae2eeddb79b595583c2e0285312b2783b0ec759930c272dbf02f851ff75"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ecfe51abf7f045e0b9cdde71ca9e153d11238679ef7b5da6c82093874adf3338"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1d6301f5288e9bdca65fab3de6b7de17362c5016d6bf8ee4ba4cbe833b2eda0f"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:93cce7d422a0093cfb3606beae38a8e47a25232eea0f292c878af580a9dc7605"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cf0db26a1f76aa6b3aa314a74b8facd586b7a5457d05b64f8082a62c9c49582a"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:defa0652696ff0ba48c8aff5a1fac1eef1ca6ac9c660b047fc8e7623c4eb5093"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-win32.whl", hash = "sha256:6db1b52c6f2c04fafc8da17ea506608e6be7086715dab498570c3e55e4f8fbd1"},
|
||||
{file = "regex-2022.1.18-cp39-cp39-win_amd64.whl", hash = "sha256:ebaeb93f90c0903233b11ce913a7cb8f6ee069158406e056f884854c737d2442"},
|
||||
{file = "regex-2022.1.18.tar.gz", hash = "sha256:97f32dc03a8054a4c4a5ab5d761ed4861e828b2c200febd4e46857069a483916"},
|
||||
]
|
||||
"six 1.16.0" = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
"soupsieve 2.3.1" = [
|
||||
{file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"},
|
||||
{file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"},
|
||||
]
|
||||
"sqlparse 0.4.2" = [
|
||||
{file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"},
|
||||
{file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"},
|
||||
]
|
||||
"tomli 2.0.1" = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
"tomlkit 0.8.0" = [
|
||||
{file = "tomlkit-0.8.0-py3-none-any.whl", hash = "sha256:b824e3466f1d475b2b5f1c392954c6cb7ea04d64354ff7300dc7c14257dc85db"},
|
||||
{file = "tomlkit-0.8.0.tar.gz", hash = "sha256:29e84a855712dfe0e88a48f6d05c21118dbafb283bb2eed614d46f80deb8e9a1"},
|
||||
]
|
||||
"tqdm 4.62.3" = [
|
||||
{file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
|
||||
{file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
|
||||
]
|
||||
"typing-extensions 4.1.1" = [
|
||||
{file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
|
||||
{file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
|
||||
]
|
||||
"tzdata 2021.5" = [
|
||||
{file = "tzdata-2021.5-py2.py3-none-any.whl", hash = "sha256:3eee491e22ebfe1e5cfcc97a4137cd70f092ce59144d81f8924a844de05ba8f5"},
|
||||
{file = "tzdata-2021.5.tar.gz", hash = "sha256:68dbe41afd01b867894bbdfd54fa03f468cfa4f0086bfb4adcd8de8f24f3ee21"},
|
||||
]
|
||||
"uvicorn 0.17.4" = [
|
||||
{file = "uvicorn-0.17.4-py3-none-any.whl", hash = "sha256:e85872d84fb651cccc4c5d2a71cf7ead055b8fb4d8f1e78e36092282c0cf2aec"},
|
||||
{file = "uvicorn-0.17.4.tar.gz", hash = "sha256:25850bbc86195a71a6477b3e4b3b7b4c861fb687fb96912972ce5324472b1011"},
|
||||
]
|
||||
"zipp 3.7.0" = [
|
||||
{file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"},
|
||||
{file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"},
|
||||
]
|
@ -1,8 +1,49 @@
|
||||
[project]
|
||||
name = "CMS Management"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = [
|
||||
{name = "Adam Goldsmith", email = "contact@adamgoldsmith.name"},
|
||||
]
|
||||
dependencies = [
|
||||
"django~=4.0",
|
||||
"django-admin-logs~=1.0",
|
||||
"django-auth-ldap~=4.0",
|
||||
"django-markdownx<5,>=4.0.0b1",
|
||||
"django-recurrence~=1.11",
|
||||
"django-widget-tweaks~=1.4",
|
||||
"markdownify~=0.10",
|
||||
"mdformat~=0.7",
|
||||
"mdformat-tables~=0.4",
|
||||
"mysqlclient~=2.1",
|
||||
]
|
||||
requires-python = ">=3.9"
|
||||
|
||||
[project.optional-dependencies]
|
||||
server = ["uvicorn~=0.17"]
|
||||
|
||||
[tool.black]
|
||||
extend-exclude = "/migrations/.*.py"
|
||||
|
||||
[tool.djlint]
|
||||
extension = ".dj.html"
|
||||
indent = 2
|
||||
blank_line_after_tag = "load,extends"
|
||||
ignore = "T003,H017,H030,H031"
|
||||
|
||||
[[tool.pdm.source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
lint = [
|
||||
"black~=22.1",
|
||||
"djlint~=0.7",
|
||||
]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
start = "./manage.py runserver"
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-pep517"]
|
||||
build-backend = "pdm.pep517.api"
|
||||
|
@ -16,41 +16,95 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='LockerBank',
|
||||
name="LockerBank",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('location', models.CharField(max_length=200)),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=200)),
|
||||
("location", models.CharField(max_length=200)),
|
||||
("slug", models.SlugField(unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LockerUnit',
|
||||
name="LockerUnit",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('index', models.PositiveIntegerField()),
|
||||
('first_letter', models.CharField(max_length=1, unique=True, validators=[django.core.validators.RegexValidator('[A-Z]')])),
|
||||
('first_number', models.PositiveIntegerField()),
|
||||
('rows', models.PositiveIntegerField(default=5)),
|
||||
('columns', models.PositiveIntegerField(default=2)),
|
||||
('bank', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='units', to='rentals.lockerbank')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("index", models.PositiveIntegerField()),
|
||||
(
|
||||
"first_letter",
|
||||
models.CharField(
|
||||
max_length=1,
|
||||
unique=True,
|
||||
validators=[django.core.validators.RegexValidator("[A-Z]")],
|
||||
),
|
||||
),
|
||||
("first_number", models.PositiveIntegerField()),
|
||||
("rows", models.PositiveIntegerField(default=5)),
|
||||
("columns", models.PositiveIntegerField(default=2)),
|
||||
(
|
||||
"bank",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="units",
|
||||
to="rentals.lockerbank",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ['index'],
|
||||
"ordering": ["index"],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='LockerRental',
|
||||
name="LockerRental",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('column', models.PositiveIntegerField()),
|
||||
('row', models.PositiveIntegerField()),
|
||||
('locker_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rentals', to='rentals.lockerunit')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("column", models.PositiveIntegerField()),
|
||||
("row", models.PositiveIntegerField()),
|
||||
(
|
||||
"locker_unit",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="rentals",
|
||||
to="rentals.lockerunit",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='lockerunit',
|
||||
constraint=models.UniqueConstraint(fields=('bank', 'index'), name='unique_bank_index'),
|
||||
model_name="lockerunit",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("bank", "index"), name="unique_bank_index"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
27
tasks/clean_markdown.py
Normal file
27
tasks/clean_markdown.py
Normal file
@ -0,0 +1,27 @@
|
||||
import bleach
|
||||
from markdownx.utils import markdownify
|
||||
|
||||
# fmt: off
|
||||
MARKDOWN_TAGS = [
|
||||
"h1", "h2", "h3", "h4", "h5", "h6",
|
||||
"b", "i", "strong", "em", "tt", "sub", "sup",
|
||||
"p", "br", "span", "div",
|
||||
"blockquote", "code", "pre",
|
||||
"hr",
|
||||
"ul", "ol", "li",
|
||||
"dl", "dd", "dt",
|
||||
"img",
|
||||
"a",
|
||||
"table", "thead", "tbody", "tr", "th", "td",
|
||||
]
|
||||
|
||||
MARKDOWN_ATTRS = {
|
||||
"*": ["id"],
|
||||
"img": ["src", "alt", "title"],
|
||||
"a": ["href", "alt", "title"],
|
||||
}
|
||||
|
||||
|
||||
def markdown_to_clean_html(md: str) -> str:
|
||||
x = bleach.clean(markdownify(md), tags=MARKDOWN_TAGS, attributes=MARKDOWN_ATTRS)
|
||||
return x
|
@ -12,65 +12,141 @@ class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
("auth", "0012_alter_user_first_name_max_length"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Tool',
|
||||
name="Tool",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('asset_tag', models.CharField(blank=True, max_length=10, unique=True)),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=200)),
|
||||
("asset_tag", models.CharField(blank=True, max_length=10, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Task',
|
||||
name="Task",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('slug', models.SlugField()),
|
||||
('description', markdownx.models.MarkdownxField(blank=True)),
|
||||
('recurrence_interval', models.CharField(max_length=200)),
|
||||
('recurrence_base', models.DateField(blank=True, null=True)),
|
||||
('tool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tasks.tool')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=200)),
|
||||
("slug", models.SlugField()),
|
||||
("description", markdownx.models.MarkdownxField(blank=True)),
|
||||
("recurrence_interval", models.CharField(max_length=200)),
|
||||
("recurrence_base", models.DateField(blank=True, null=True)),
|
||||
(
|
||||
"tool",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="tasks.tool"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('tool', 'slug')},
|
||||
"unique_together": {("tool", "slug")},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
name="Event",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('date', models.DateField()),
|
||||
('notes', markdownx.models.MarkdownxField(blank=True)),
|
||||
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tasks.task')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("date", models.DateField()),
|
||||
("notes", markdownx.models.MarkdownxField(blank=True)),
|
||||
(
|
||||
"task",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="tasks.task"
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='GroupToolSubscription',
|
||||
name="GroupToolSubscription",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('days_before', models.PositiveIntegerField()),
|
||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||
('tool', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tasks.tool')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("days_before", models.PositiveIntegerField()),
|
||||
(
|
||||
"group",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="auth.group"
|
||||
),
|
||||
),
|
||||
(
|
||||
"tool",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="tasks.tool"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('group', 'tool')},
|
||||
"unique_together": {("group", "tool")},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='GroupTaskSubscription',
|
||||
name="GroupTaskSubscription",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('days_before', models.PositiveIntegerField()),
|
||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.group')),
|
||||
('task', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tasks.task')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("days_before", models.PositiveIntegerField()),
|
||||
(
|
||||
"group",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="auth.group"
|
||||
),
|
||||
),
|
||||
(
|
||||
"task",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="tasks.task"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('group', 'task')},
|
||||
"unique_together": {("group", "task")},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
@ -3,27 +3,28 @@ from django.utils.text import slugify
|
||||
|
||||
|
||||
def slugify_name(apps, schema_editor):
|
||||
Tool = apps.get_model('tasks', 'tool')
|
||||
Tool = apps.get_model("tasks", "tool")
|
||||
for tool in Tool.objects.all():
|
||||
tool.slug = slugify(tool.name)
|
||||
tool.save(update_fields=['slug'])
|
||||
tool.save(update_fields=["slug"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tasks', '0001_initial'),
|
||||
("tasks", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tool',
|
||||
name='slug',
|
||||
model_name="tool",
|
||||
name="slug",
|
||||
field=models.SlugField(blank=True, null=True, unique=True),
|
||||
),
|
||||
migrations.RunPython(slugify_name),
|
||||
migrations.AlterField(
|
||||
model_name='tool',
|
||||
name='slug',
|
||||
model_name="tool",
|
||||
name="slug",
|
||||
field=models.SlugField(unique=True),
|
||||
)
|
||||
),
|
||||
]
|
||||
|
@ -4,28 +4,29 @@ from django.db import migrations
|
||||
import recurrence
|
||||
import recurrence.fields
|
||||
|
||||
|
||||
def transfer_recurrence(apps, schema_editor):
|
||||
Task = apps.get_model('tasks', 'task')
|
||||
Task = apps.get_model("tasks", "task")
|
||||
for task in Task.objects.all():
|
||||
task.recurrence = recurrence.deserialize('RRULE:' + task.recurrence_interval)
|
||||
task.save(update_fields=['recurrence'])
|
||||
task.recurrence = recurrence.deserialize("RRULE:" + task.recurrence_interval)
|
||||
task.save(update_fields=["recurrence"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('tasks', '0002_tool_slug'),
|
||||
("tasks", "0002_tool_slug"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='task',
|
||||
name='recurrence',
|
||||
field=recurrence.fields.RecurrenceField(default=''),
|
||||
model_name="task",
|
||||
name="recurrence",
|
||||
field=recurrence.fields.RecurrenceField(default=""),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.RunPython(transfer_recurrence),
|
||||
migrations.RemoveField(
|
||||
model_name='task',
|
||||
name='recurrence_interval',
|
||||
model_name="task",
|
||||
name="recurrence_interval",
|
||||
),
|
||||
]
|
||||
|
@ -7,6 +7,8 @@ from django.urls import reverse
|
||||
from markdownx.models import MarkdownxField
|
||||
from recurrence.fields import RecurrenceField
|
||||
|
||||
from .clean_markdown import markdown_to_clean_html
|
||||
|
||||
|
||||
class Tool(models.Model):
|
||||
name = models.CharField(max_length=200)
|
||||
@ -37,6 +39,10 @@ class Task(models.Model):
|
||||
def get_absolute_url(self):
|
||||
return reverse("tasks:taskDetail", args=[self.tool.slug, self.slug])
|
||||
|
||||
@property
|
||||
def description_html(self):
|
||||
return markdown_to_clean_html(self.description)
|
||||
|
||||
@property
|
||||
def last_event(self):
|
||||
return self.event_set.latest("date")
|
||||
@ -121,5 +127,9 @@ class Event(models.Model):
|
||||
date = models.DateField()
|
||||
notes = MarkdownxField(blank=True)
|
||||
|
||||
@property
|
||||
def notes_html(self):
|
||||
return markdown_to_clean_html(self.notes)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.task}: {self.user} {self.date}"
|
||||
|
@ -1,6 +1,5 @@
|
||||
{% extends "base.dj.html" %}
|
||||
|
||||
{% load markdownify %}
|
||||
{% load widget_tweaks %}
|
||||
|
||||
{% block title %}{{ tool.name }} - {{ task.name }} | {{ block.super }}{% endblock %}
|
||||
@ -66,7 +65,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<h2>Description</h2>
|
||||
{{ task.description|markdownify }}
|
||||
{{ task.description_html|safe }}
|
||||
</section>
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-warning">
|
||||
@ -123,7 +122,7 @@
|
||||
<tr>
|
||||
<td class="text-nowrap">{{ event.date }}</td>
|
||||
<td>{{ event.user }}</td>
|
||||
<td>{{ event.notes|markdownify }}</td>
|
||||
<td>{{ event.notes_html|safe }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -1,7 +1,5 @@
|
||||
{% extends "base.dj.html" %}
|
||||
|
||||
{% load markdownify %}
|
||||
|
||||
{% block title %}{{ tool }} | {{ block.super }}{% endblock %}
|
||||
{% block admin_link %}
|
||||
{% url 'admin:tasks_tool_change' tool.id %}
|
||||
@ -43,7 +41,7 @@
|
||||
<td class="text-nowrap">{{ event.date }}</td>
|
||||
<td>{{ event.task.name }}</td>
|
||||
<td>{{ event.user }}</td>
|
||||
<td>{{ event.notes|markdownify }}</td>
|
||||
<td>{{ event.notes_html|safe }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -47,9 +47,13 @@
|
||||
<div class="messages m-3">
|
||||
{% for message in messages %}
|
||||
{# TODO: should use tags correctly for bootstrap alerts #}
|
||||
<div role="alert" class="alert alert-info alert-dismissible fade show {% if message.tags %} {{ message.tags }}{% endif %}">
|
||||
<div role="alert"
|
||||
class="alert alert-info alert-dismissible fade show {% if message.tags %} {{ message.tags }}{% endif %}">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
<button type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user