diff --git a/src/Pipfile b/src/Pipfile index 9208fada5..9366423f1 100644 --- a/src/Pipfile +++ b/src/Pipfile @@ -31,6 +31,7 @@ gevent = "*" fred-epplib = {git = "https://github.com/cisagov/epplib.git", ref = "master"} pyzipper="*" tblib = "*" +django-admin-multiple-choice-list-filter = "*" [dev-packages] django-debug-toolbar = "*" diff --git a/src/Pipfile.lock b/src/Pipfile.lock index 4eb2c0fb3..a1c27e1db 100644 --- a/src/Pipfile.lock +++ b/src/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "082a951f15bb26a28f2dca7e0840fdf61518b3d90c42d77a310f982344cbd1dc" + "sha256": "52143c73ccc59cd3dd6a1294a9352dbae009ebfc6e3ca5d018b8484275e2b6f8" }, "pipfile-spec": 6, "requires": {}, @@ -24,28 +24,28 @@ }, "asgiref": { "hashes": [ - "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", - "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" + "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", + "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" ], - "markers": "python_version >= '3.7'", - "version": "==3.7.2" + "markers": "python_version >= '3.8'", + "version": "==3.8.1" }, "boto3": { "hashes": [ - "sha256:300888f0c1b6f32f27f85a9aa876f50f46514ec619647af7e4d20db74d339714", - "sha256:b26928f9a21cf3649cea20a59061340f3294c6e7785ceb6e1a953eb8010dc3ba" + "sha256:7ce8c9a50af2f8a159a0dd86b40011d8dfdaba35005a118e51cd3ac72dc630f1", + "sha256:d786e7fbe3c4152866199786468a625dc77b9f27294cd7ad4f63cd2e0c927287" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.56" + "version": "==1.34.71" }, "botocore": { "hashes": [ - "sha256:bffeb71ab21d47d4ecf947d9bdb2fbd1b0bbd0c27742cea7cf0b77b701c41d9f", - "sha256:fff66e22a5589c2d58fba57d1d95c334ce771895e831f80365f6cff6453285ec" + "sha256:3bc9e23aee73fe6f097823d61f79a8877790436038101a83fa96c7593e8109f8", + "sha256:c58f9ed71af2ea53d24146187130541222d7de8c27eb87d23f15457e7b83d88b" ], "markers": "python_version >= '3.8'", - "version": "==1.34.56" + "version": "==1.34.71" }, "cachetools": { "hashes": [ @@ -295,6 +295,14 @@ "markers": "python_version >= '3.8'", "version": "==4.2.10" }, + "django-admin-multiple-choice-list-filter": { + "hashes": [ + "sha256:a5b82682ff752cf74bbc4fa3d562c99b9f9f80389961017e1ac63e08f22d8b9f", + "sha256:eab2ad5fad6df8ed8436cb6c1d0e67863453a9d30282b7fdcb7e45b2eb37ab6f" + ], + "index": "pypi", + "version": "==0.1.1" + }, "django-allow-cidr": { "hashes": [ "sha256:11126c5bb9df3a61ff9d97304856ba7e5b26d46c6d456709a6d9e28483bff47f", @@ -384,12 +392,12 @@ }, "faker": { "hashes": [ - "sha256:2456d674f40bd51eb3acbf85221277027822e529a90cc826453d9a25dff932b1", - "sha256:ea6f784c40730de0f77067e49e78cdd590efb00bec3d33f577492262206c17fc" + "sha256:998c29ee7d64429bd59204abffa9ba11f784fb26c7b9df4def78d1a70feb36a7", + "sha256:a5ddccbe97ab691fad6bd8036c31f5697cfaa550e62e000078d1935fa8a7ec2e" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==24.0.0" + "version": "==24.4.0" }, "fred-epplib": { "git": "https://github.com/cisagov/epplib.git", @@ -732,18 +740,18 @@ }, "packaging": { "hashes": [ - "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", - "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" ], "markers": "python_version >= '3.7'", - "version": "==23.2" + "version": "==24.0" }, "phonenumberslite": { "hashes": [ - "sha256:137d53d5d78dca30bc2becf81a3e2ac74deb8f0997e9bbe44de515ece4bd92bd", - "sha256:e1f4359bff90c86d1b52db0e726d3334df00cc7d9c9c2ef66561d5f7a774d4ba" + "sha256:4d92f4f9079bb83588dde45fd8a414bc13e4962886aa4d23576984196f4d83c2", + "sha256:7426bc46af3de5a800a4c8f33ab13e33225d2c8ed4fc52aa3c0380dadd8d7381" ], - "version": "==8.13.31" + "version": "==8.13.33" }, "psycopg2-binary": { "hashes": [ @@ -872,11 +880,11 @@ }, "pydantic": { "hashes": [ - "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a", - "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f" + "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6", + "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5" ], "markers": "python_version >= '3.8'", - "version": "==2.6.3" + "version": "==2.6.4" }, "pydantic-core": { "hashes": [ @@ -1014,19 +1022,19 @@ }, "s3transfer": { "hashes": [ - "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e", - "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b" + "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", + "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" ], "markers": "python_version >= '3.8'", - "version": "==0.10.0" + "version": "==0.10.1" }, "setuptools": { "hashes": [ - "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56", - "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8" + "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e", + "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c" ], "markers": "python_version >= '3.8'", - "version": "==69.1.1" + "version": "==69.2.0" }, "six": { "hashes": [ @@ -1064,11 +1072,11 @@ }, "urllib3": { "hashes": [ - "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", - "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" + "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", + "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.7" + "markers": "python_version >= '3.8'", + "version": "==2.2.1" }, "whitenoise": { "hashes": [ @@ -1133,20 +1141,20 @@ "develop": { "asgiref": { "hashes": [ - "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", - "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" + "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", + "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" ], - "markers": "python_version >= '3.7'", - "version": "==3.7.2" + "markers": "python_version >= '3.8'", + "version": "==3.8.1" }, "bandit": { "hashes": [ - "sha256:17e60786a7ea3c9ec84569fd5aee09936d116cb0cb43151023258340dbffb7ed", - "sha256:527906bec6088cb499aae31bc962864b4e77569e9d529ee51df3a93b4b8ab28a" + "sha256:36de50f720856ab24a24dbaa5fee2c66050ed97c1477e0a1159deab1775eab6b", + "sha256:509f7af645bc0cd8fd4587abc1a038fc795636671ee8204d502b933aee44f381" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.7.7" + "version": "==1.7.8" }, "beautifulsoup4": { "hashes": [ @@ -1158,32 +1166,32 @@ }, "black": { "hashes": [ - "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8", - "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8", - "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd", - "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9", - "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31", - "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92", - "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f", - "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29", - "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4", - "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693", - "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218", - "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a", - "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23", - "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0", - "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982", - "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894", - "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540", - "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430", - "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b", - "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2", - "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6", - "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d" + "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f", + "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93", + "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11", + "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0", + "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9", + "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5", + "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213", + "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d", + "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7", + "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837", + "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f", + "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395", + "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995", + "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f", + "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597", + "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959", + "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5", + "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb", + "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4", + "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7", + "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd", + "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==24.2.0" + "version": "==24.3.0" }, "blinker": { "hashes": [ @@ -1195,12 +1203,12 @@ }, "boto3": { "hashes": [ - "sha256:300888f0c1b6f32f27f85a9aa876f50f46514ec619647af7e4d20db74d339714", - "sha256:b26928f9a21cf3649cea20a59061340f3294c6e7785ceb6e1a953eb8010dc3ba" + "sha256:7ce8c9a50af2f8a159a0dd86b40011d8dfdaba35005a118e51cd3ac72dc630f1", + "sha256:d786e7fbe3c4152866199786468a625dc77b9f27294cd7ad4f63cd2e0c927287" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.56" + "version": "==1.34.71" }, "boto3-mocking": { "hashes": [ @@ -1213,28 +1221,28 @@ }, "boto3-stubs": { "hashes": [ - "sha256:627f8eca69d832581ee1676d39df099a2a2e3a86d6b3ebd21c81c5f11ed6a6fa", - "sha256:a87e7ecbab6235ec371b4363027e57483bca349a9cd5c891f40db81dadfa273e" + "sha256:1be579780a39a75394db0c413594aec380afde86dbc7eb5eb086a97a25d3c995", + "sha256:c9959c48ee1b53e9d19e424898caacf365aaee34cee4c70f40692e2b47bc8099" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.56" + "version": "==1.34.71" }, "botocore": { "hashes": [ - "sha256:bffeb71ab21d47d4ecf947d9bdb2fbd1b0bbd0c27742cea7cf0b77b701c41d9f", - "sha256:fff66e22a5589c2d58fba57d1d95c334ce771895e831f80365f6cff6453285ec" + "sha256:3bc9e23aee73fe6f097823d61f79a8877790436038101a83fa96c7593e8109f8", + "sha256:c58f9ed71af2ea53d24146187130541222d7de8c27eb87d23f15457e7b83d88b" ], "markers": "python_version >= '3.8'", - "version": "==1.34.56" + "version": "==1.34.71" }, "botocore-stubs": { "hashes": [ - "sha256:018e001e3add5eb1828ef444b45fb8c9faf695e08334031bf2d96853cd9af703", - "sha256:25468ba6983987b704b1856bb155f297f576e6d4a690b021ab0c7122889ba907" + "sha256:0c3835c775db1387246c1ba8063b197604462fba8603d9b36b5dc60297197b2f", + "sha256:463248fd1d6e7b68a0c57bdd758d04c6bd0c5c2c3bfa81afdf9d64f0930b59bc" ], "markers": "python_version >= '3.8' and python_version < '4.0'", - "version": "==1.34.56" + "version": "==1.34.69" }, "click": { "hashes": [ @@ -1337,37 +1345,37 @@ }, "mypy": { "hashes": [ - "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6", - "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d", - "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02", - "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d", - "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3", - "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3", - "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3", - "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66", - "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259", - "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835", - "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd", - "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d", - "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8", - "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07", - "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b", - "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e", - "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6", - "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae", - "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9", - "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d", - "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a", - "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592", - "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218", - "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817", - "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4", - "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410", - "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55" + "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6", + "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913", + "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129", + "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc", + "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974", + "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374", + "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150", + "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03", + "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9", + "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02", + "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89", + "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2", + "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d", + "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3", + "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612", + "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e", + "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3", + "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e", + "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd", + "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04", + "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed", + "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185", + "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf", + "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b", + "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4", + "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f", + "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.8.0" + "version": "==1.9.0" }, "mypy-extensions": { "hashes": [ @@ -1387,11 +1395,11 @@ }, "packaging": { "hashes": [ - "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", - "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" ], "markers": "python_version >= '3.7'", - "version": "==23.2" + "version": "==24.0" }, "pathspec": { "hashes": [ @@ -1516,11 +1524,11 @@ }, "s3transfer": { "hashes": [ - "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e", - "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b" + "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", + "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" ], "markers": "python_version >= '3.8'", - "version": "==0.10.0" + "version": "==0.10.1" }, "six": { "hashes": [ @@ -1589,19 +1597,20 @@ }, "types-pyyaml": { "hashes": [ - "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062", - "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24" + "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342", + "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6" ], - "version": "==6.0.12.12" + "markers": "python_version >= '3.8'", + "version": "==6.0.12.20240311" }, "types-requests": { "hashes": [ - "sha256:a82807ec6ddce8f00fe0e949da6d6bc1fbf1715420218a9640d695f70a9e5a9b", - "sha256:f1721dba8385958f504a5386240b92de4734e047a08a40751c1654d1ac3349c5" + "sha256:47872893d65a38e282ee9f277a4ee50d1b28bd592040df7d1fdaffdf3779937d", + "sha256:b1c1b66abfb7fa79aae09097a811c4aa97130eb8831c60e47aee4ca344731ca5" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.31.0.20240218" + "version": "==2.31.0.20240311" }, "types-s3transfer": { "hashes": [ @@ -1622,11 +1631,11 @@ }, "urllib3": { "hashes": [ - "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", - "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" + "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", + "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.7" + "markers": "python_version >= '3.8'", + "version": "==2.2.1" }, "waitress": { "hashes": [ diff --git a/src/registrar/admin.py b/src/registrar/admin.py index e4c71f8d5..8a2bc2141 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -27,6 +27,7 @@ from django_fsm import TransitionNotAllowed # type: ignore from django.utils.safestring import mark_safe from django.utils.html import escape from django.contrib.auth.forms import UserChangeForm, UsernameField +from django_admin_multiple_choice_list_filter.list_filters import MultipleChoiceListFilter from django.utils.translation import gettext_lazy as _ @@ -978,6 +979,18 @@ class DomainRequestAdmin(ListHeaderAdmin): """Custom domain requests admin class.""" form = DomainRequestAdminForm + change_form_template = "django/admin/domain_request_change_form.html" + + class StatusListFilter(MultipleChoiceListFilter): + """Custom status filter which is a multiple choice filter""" + + title = "Status" + parameter_name = "status__in" + + template = "django/admin/multiple_choice_list_filter.html" + + def lookups(self, request, model_admin): + return DomainRequest.DomainRequestStatus.choices class InvestigatorFilter(admin.SimpleListFilter): """Custom investigator filter that only displays users with the manager role""" @@ -1039,8 +1052,6 @@ class DomainRequestAdmin(ListHeaderAdmin): if self.value() == "0": return queryset.filter(Q(is_election_board=False) | Q(is_election_board=None)) - change_form_template = "django/admin/domain_request_change_form.html" - # Columns list_display = [ "requested_domain", @@ -1071,7 +1082,7 @@ class DomainRequestAdmin(ListHeaderAdmin): # Filters list_filter = ( - "status", + StatusListFilter, "generic_org_type", "federal_type", ElectionOfficeFilter, @@ -1353,6 +1364,23 @@ class DomainRequestAdmin(ListHeaderAdmin): "Cannot edit a domain request with a restricted creator.", ) + def changelist_view(self, request, extra_context=None): + """ + Override changelist_view to set the selected value of status filter. + """ + # use http_referer in order to distinguish between request as a link from another page + # and request as a removal of all filters + http_referer = request.META.get("HTTP_REFERER", "") + # if there are no query parameters in the request + # and the request is the initial request for this view + if not bool(request.GET) and request.path not in http_referer: + # modify the GET of the request to set the selected filter + modified_get = copy.deepcopy(request.GET) + modified_get["status__in"] = "submitted,in review,action needed" + request.GET = modified_get + response = super().changelist_view(request, extra_context=extra_context) + return response + def change_view(self, request, object_id, form_url="", extra_context=None): obj = self.get_object(request, object_id) self.display_restricted_warning(request, obj) @@ -1406,6 +1434,13 @@ class DomainInformationInline(admin.StackedInline): "submitter", ] + def has_change_permission(self, request, obj=None): + """Custom has_change_permission override so that we can specify that + analysts can edit this through this inline, but not through the model normally""" + if request.user.has_perm("registrar.analyst_access_permission"): + return True + return super().has_change_permission(request, obj) + def formfield_for_manytomany(self, db_field, request, **kwargs): """customize the behavior of formfields with manytomany relationships. the customized behavior includes sorting of objects in lists as well as customizing helper text""" diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js index 8c60c534f..9a92542b1 100644 --- a/src/registrar/assets/js/get-gov-admin.js +++ b/src/registrar/assets/js/get-gov-admin.js @@ -410,3 +410,60 @@ function enableRelatedWidgetButtons(changeLink, deleteLink, viewLink, elementPk, }); observer.observe({ type: "navigation" }); })(); + +/** An IIFE for toggling the submit bar on domain request forms +*/ +(function (){ + // Get a reference to the button element + const toggleButton = document.getElementById('submitRowToggle'); + const submitRowWrapper = document.querySelector('.submit-row-wrapper'); + + if (toggleButton) { + // Add event listener to toggle the class and update content on click + toggleButton.addEventListener('click', function() { + // Toggle the 'collapsed' class on the bar + submitRowWrapper.classList.toggle('submit-row-wrapper--collapsed'); + + // Get a reference to the span element inside the button + const spanElement = this.querySelector('span'); + + // Get a reference to the use element inside the button + const useElement = this.querySelector('use'); + + // Check if the span element text is 'Hide' + if (spanElement.textContent.trim() === 'Hide') { + // Update the span element text to 'Show' + spanElement.textContent = 'Show'; + + // Update the xlink:href attribute to expand_more + useElement.setAttribute('xlink:href', '/public/img/sprite.svg#expand_less'); + } else { + // Update the span element text to 'Hide' + spanElement.textContent = 'Hide'; + + // Update the xlink:href attribute to expand_less + useElement.setAttribute('xlink:href', '/public/img/sprite.svg#expand_more'); + } + }); + + // We have a scroll indicator at the end of the page. + // Observe it. Once it gets on screen, test to see if the row is collapsed. + // If it is, expand it. + const targetElement = document.querySelector(".scroll-indicator"); + const options = { + threshold: 1 + }; + // Create a new Intersection Observer + const observer = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + // Refresh reference to submit row wrapper and check if it's collapsed + if (document.querySelector('.submit-row-wrapper').classList.contains('submit-row-wrapper--collapsed')) { + toggleButton.click(); + } + } + }); + }, options); + observer.observe(targetElement); + } +})(); diff --git a/src/registrar/assets/sass/_theme/_admin.scss b/src/registrar/assets/sass/_theme/_admin.scss index 658ae5ca8..d86c0e07b 100644 --- a/src/registrar/assets/sass/_theme/_admin.scss +++ b/src/registrar/assets/sass/_theme/_admin.scss @@ -42,6 +42,7 @@ html[data-theme="light"] { --error-fg: #{$theme-color-error}; --message-success-bg: #{$theme-color-success-lighter}; + --checkbox-green: #{$theme-color-success-light}; // $theme-color-warning-lighter - yellow-5 --message-warning-bg: #faf3d1; --message-error-bg: #{$theme-color-error-lighter}; @@ -93,6 +94,7 @@ html[data-theme="light"] { --error-fg: #e35f5f; --message-success-bg: #006b1b; + --checkbox-green: #006b1b; --message-warning-bg: #583305; --message-error-bg: #570808; @@ -422,6 +424,102 @@ address.dja-address-contact-list { border: 1px solid var(--error-fg) !important; } +.choice-filter { + position: relative; + padding-left: 20px; + svg { + top: 4px; + } +} + +.choice-filter--checked { + svg:nth-child(1) { + background: var(--checkbox-green); + fill: var(--checkbox-green); + } + svg:nth-child(2) { + color: var(--body-loud-color); + } +} + +// Let's define this block of code once and use it for analysts over a certain screen size, +// superusers over another screen size. +@mixin submit-row-wrapper--collapsed-one-line(){ + &.submit-row-wrapper--collapsed { + transform: translate3d(0, 42px, 0); + } + .submit-row { + clear: none; + } + } + +// Sticky submit bar for domain requests on desktop +@media screen and (min-width:768px) { + .submit-row-wrapper { + position: fixed; + bottom: 0; + right: 0; + left: 338px; + background: var(--darkened-bg); + border-top-left-radius: 6px; + transition: transform .2s ease-out; + .submit-row { + margin-bottom: 0; + } + } + .submit-row-wrapper--collapsed { + // translate3d is more performant than translateY + // https://stackoverflow.com/questions/22111256/translate3d-vs-translate-performance + transform: translate3d(0, 88px, 0); + } + .submit-row-wrapper--collapsed-one-line { + @include submit-row-wrapper--collapsed-one-line(); + } + .submit-row { + clear: both; + } + .submit-row-toggle{ + display: inline-block; + position: absolute; + top: -30px; + right: 0; + background: var(--darkened-bg); + } + #submitRowToggle { + color: var(--body-fg); + } + .requested-domain-sticky { + max-width: 325px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +} + +.visible-768 { + display: none; +} + +@media screen and (min-width:768px) { + .visible-768 { + display: block; + } +} + +@media screen and (min-width:935px) { + // Analyst only class + .submit-row-wrapper--analyst-view { + @include submit-row-wrapper--collapsed-one-line(); + } +} + +@media screen and (min-width:1256px) { + .submit-row-wrapper { + @include submit-row-wrapper--collapsed-one-line(); + } +} + +// Collapse button styles for fieldsets .module.collapse { margin-top: -35px; padding-top: 0; diff --git a/src/registrar/assets/sass/_theme/_base.scss b/src/registrar/assets/sass/_theme/_base.scss index 127db5589..212df992f 100644 --- a/src/registrar/assets/sass/_theme/_base.scss +++ b/src/registrar/assets/sass/_theme/_base.scss @@ -117,6 +117,10 @@ abbr[title] { } } +.visible-desktop { + display: none; +} + @include at-media(desktop) { .float-right-desktop { float: right; @@ -124,33 +128,15 @@ abbr[title] { .float-left-desktop { float: left; } + .visible-desktop { + display: block; + } } .flex-end { align-items: flex-end; } -// Only apply this custom wrapping to desktop -@include at-media(desktop) { - .usa-tooltip__body { - width: 350px; - white-space: normal; - text-align: center; - } -} - -@include at-media(tablet) { - .usa-tooltip__body { - width: 250px !important; - white-space: normal !important; - text-align: center !important; - } -} - -@include at-media(mobile) { - .usa-tooltip__body { - width: 250px !important; - white-space: normal !important; - text-align: center !important; - } +.cursor-pointer { + cursor: pointer; } diff --git a/src/registrar/assets/sass/_theme/_buttons.scss b/src/registrar/assets/sass/_theme/_buttons.scss index ef8635b95..1f5047503 100644 --- a/src/registrar/assets/sass/_theme/_buttons.scss +++ b/src/registrar/assets/sass/_theme/_buttons.scss @@ -138,6 +138,13 @@ a.usa-button--unstyled:visited { } } +.usa-button--unstyled--white, +.usa-button--unstyled--white:hover, +.usa-button--unstyled--white:focus, +.usa-button--unstyled--white:active { + color: color('white'); +} + // Cancel button used on the // DNSSEC main page // We want to center this button on mobile diff --git a/src/registrar/assets/sass/_theme/_tooltips.scss b/src/registrar/assets/sass/_theme/_tooltips.scss new file mode 100644 index 000000000..01348e1b1 --- /dev/null +++ b/src/registrar/assets/sass/_theme/_tooltips.scss @@ -0,0 +1,26 @@ +@use "uswds-core" as *; + +// Only apply this custom wrapping to desktop +@include at-media(desktop) { + .usa-tooltip__body { + width: 350px; + white-space: normal; + text-align: center; + } +} + +@include at-media(tablet) { + .usa-tooltip__body { + width: 250px !important; + white-space: normal !important; + text-align: center !important; + } +} + +@include at-media(mobile) { + .usa-tooltip__body { + width: 250px !important; + white-space: normal !important; + text-align: center !important; + } +} diff --git a/src/registrar/assets/sass/_theme/styles.scss b/src/registrar/assets/sass/_theme/styles.scss index 0239199e7..942501110 100644 --- a/src/registrar/assets/sass/_theme/styles.scss +++ b/src/registrar/assets/sass/_theme/styles.scss @@ -13,6 +13,7 @@ @forward "lists"; @forward "buttons"; @forward "forms"; +@forward "tooltips"; @forward "fieldsets"; @forward "alerts"; @forward "tables"; diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 646b7298f..54b65e83e 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -146,6 +146,8 @@ INSTALLED_APPS = [ # "puml_generator", # supports necessary headers for Django cross origin "corsheaders", + # library for multiple choice filters in django admin + "django_admin_multiple_choice_list_filter", ] # Middleware are routines for processing web requests. diff --git a/src/registrar/migrations/0081_create_groups_v10.py b/src/registrar/migrations/0081_create_groups_v10.py new file mode 100644 index 000000000..d65b6dbd2 --- /dev/null +++ b/src/registrar/migrations/0081_create_groups_v10.py @@ -0,0 +1,37 @@ +# This migration creates the create_full_access_group and create_cisa_analyst_group groups +# It is dependent on 0079 (which populates federal agencies) +# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS +# in the user_group model then: +# [NOT RECOMMENDED] +# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions +# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups +# step 3: fake run the latest migration in the migrations list +# [RECOMMENDED] +# Alternatively: +# step 1: duplicate the migration that loads data +# step 2: docker-compose exec app ./manage.py migrate + +from django.db import migrations +from registrar.models import UserGroup +from typing import Any + + +# For linting: RunPython expects a function reference, +# so let's give it one +def create_groups(apps, schema_editor) -> Any: + UserGroup.create_cisa_analyst_group(apps, schema_editor) + UserGroup.create_full_access_group(apps, schema_editor) + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0080_create_groups_v09"), + ] + + operations = [ + migrations.RunPython( + create_groups, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), + ] diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py index 2aa2f642e..e8636a462 100644 --- a/src/registrar/models/user_group.py +++ b/src/registrar/models/user_group.py @@ -26,11 +26,6 @@ class UserGroup(Group): "model": "contact", "permissions": ["change_contact"], }, - { - "app_label": "registrar", - "model": "domaininformation", - "permissions": ["change_domaininformation"], - }, { "app_label": "registrar", "model": "domainrequest", diff --git a/src/registrar/templates/admin/change_list.html b/src/registrar/templates/admin/change_list.html index 479b7b1ff..05c2d4e64 100644 --- a/src/registrar/templates/admin/change_list.html +++ b/src/registrar/templates/admin/change_list.html @@ -21,6 +21,8 @@ {% else %} election office = Yes {% endif %} + {% elif filter_param.parameter_name == 'status__in' %} + status in [{{ filter_param.parameter_value }}] {% else %} {{ filter_param.parameter_name }} = {{ filter_param.parameter_value }} {% endif %} diff --git a/src/registrar/templates/django/admin/domain_request_change_form.html b/src/registrar/templates/django/admin/domain_request_change_form.html index b0ee6e044..3b4fa7283 100644 --- a/src/registrar/templates/django/admin/domain_request_change_form.html +++ b/src/registrar/templates/django/admin/domain_request_change_form.html @@ -1,4 +1,5 @@ {% extends 'admin/change_form.html' %} +{% load custom_filters %} {% load i18n static %} {% block field_sets %} @@ -102,5 +103,25 @@ -{{ block.super }} + +{# submit-row-wrapper--analyst-view is a class that manages layout on certain screens for analysts only #} +
+ + + {% endblock %} diff --git a/src/registrar/templates/django/admin/multiple_choice_list_filter.html b/src/registrar/templates/django/admin/multiple_choice_list_filter.html new file mode 100644 index 000000000..66643f4ec --- /dev/null +++ b/src/registrar/templates/django/admin/multiple_choice_list_filter.html @@ -0,0 +1,37 @@ +{% load i18n %} +{% load static field_helpers url_helpers %} + + + Last updated: {{DomainRequest.updated_at|date:"F j, Y"}}
Last updated: {{DomainRequest.updated_at|date:"F j, Y"}}
{% include "includes/domain_request.html" %}
Withdraw request diff --git a/src/registrar/templates/domain_users.html b/src/registrar/templates/domain_users.html index 7de159871..65da4ef6b 100644 --- a/src/registrar/templates/domain_users.html +++ b/src/registrar/templates/domain_users.html @@ -135,7 +135,7 @@