diff --git a/Pipfile.lock b/Pipfile.lock index 7b036e19a..bad0dbe79 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -190,22 +190,22 @@ }, "cryptography": { "hashes": [ - "sha256:066bc53f052dfeda2f2d7c195cf16fb3e5ff13e1b6b7415b468514b40b381a5b", - "sha256:0923ba600d00718d63a3976f23cab19aef10c1765038945628cd9be047ad0336", - "sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87", - "sha256:4169a27b818de4a1860720108b55a2801f32b6ae79e7f99c00d79f2a2822eeb7", - "sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799", - "sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b", - "sha256:600cf9bfe75e96d965509a4c0b2b183f74a4fa6f5331dcb40fb7b77b7c2484df", - "sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0", - "sha256:926ae3dfd160050158b9ca25d419fb7ee658974564b01aa10c059a75dffab7e8", - "sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3", - "sha256:9e98b452132963678e3ac6c73f7010fe53adf72209a32854d55690acac3f6724", - "sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2", - "sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964" + "sha256:0f1212a66329c80d68aeeb39b8a16d54ef57071bf22ff4e521657b27372e327d", + "sha256:1e056c28420c072c5e3cb36e2b23ee55e260cb04eee08f702e0edfec3fb51959", + "sha256:240f5c21aef0b73f40bb9f78d2caff73186700bf1bc6b94285699aff98cc16c6", + "sha256:26965837447f9c82f1855e0bc8bc4fb910240b6e0d16a664bb722df3b5b06873", + "sha256:37340614f8a5d2fb9aeea67fd159bfe4f5f4ed535b1090ce8ec428b2f15a11f2", + "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713", + "sha256:3d8427734c781ea5f1b41d6589c293089704d4759e34597dce91014ac125aad1", + "sha256:7ec5d3b029f5fa2b179325908b9cd93db28ab7b85bb6c1db56b10e0b54235177", + "sha256:8e56e16617872b0957d1c9742a3f94b43533447fd78321514abbe7db216aa250", + "sha256:a79fef41233d4c535d28133627ce6c7ac73d5cc0eb7316331a5905bf01411f08", + "sha256:de4e5f7f68220d92b7637fc99847475b59154b7a1b3868fb7385337af54ac9ca", + "sha256:eb8cc2afe8b05acbd84a43905832ec78e7b3873fb124ca190f574dca7389a87d", + "sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9" ], "index": "pypi", - "version": "==3.4.6" + "version": "==3.4.7" }, "daphne": { "hashes": [ @@ -273,11 +273,11 @@ }, "djangorestframework": { "hashes": [ - "sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7", - "sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33" + "sha256:6d1d59f623a5ad0509fe0d6bfe93cbdfe17b8116ebc8eda86d45f6e16e819aaf", + "sha256:f747949a8ddac876e879190df194b925c177cdeb725a099db1460872f7c0a7f2" ], "index": "pypi", - "version": "==3.12.2" + "version": "==3.12.4" }, "filelock": { "hashes": [ @@ -300,11 +300,11 @@ }, "gunicorn": { "hashes": [ - "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626", - "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c" + "sha256:8d737657cdd62f483d482ee65cf9cc6a64d5b2199674f8b174803be9065e5d60", + "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8" ], "index": "pypi", - "version": "==20.0.4" + "version": "==20.1.0" }, "h11": { "hashes": [ @@ -316,57 +316,51 @@ }, "hiredis": { "hashes": [ - "sha256:06a039208f83744a702279b894c8cf24c14fd63c59cd917dcde168b79eef0680", - "sha256:0a909bf501459062aa1552be1461456518f367379fdc9fdb1f2ca5e4a1fdd7c0", - "sha256:18402d9e54fb278cb9a8c638df6f1550aca36a009d47ecf5aa263a38600f35b0", - "sha256:1e4cbbc3858ec7e680006e5ca590d89a5e083235988f26a004acf7244389ac01", - "sha256:23344e3c2177baf6975fbfa361ed92eb7d36d08f454636e5054b3faa7c2aff8a", - "sha256:289b31885b4996ce04cadfd5fc03d034dce8e2a8234479f7c9e23b9e245db06b", - "sha256:2c1c570ae7bf1bab304f29427e2475fe1856814312c4a1cf1cd0ee133f07a3c6", - "sha256:2c227c0ed371771ffda256034427320870e8ea2e4fd0c0a618c766e7c49aad73", - "sha256:3bb9b63d319402cead8bbd9dd55dca3b667d2997e9a0d8a1f9b6cc274db4baee", - "sha256:3ef2183de67b59930d2db8b8e8d4d58e00a50fcc5e92f4f678f6eed7a1c72d55", - "sha256:43b8ed3dbfd9171e44c554cb4acf4ee4505caa84c5e341858b50ea27dd2b6e12", - "sha256:47bcf3c5e6c1e87ceb86cdda2ee983fa0fe56a999e6185099b3c93a223f2fa9b", - "sha256:5263db1e2e1e8ae30500cdd75a979ff99dcc184201e6b4b820d0de74834d2323", - "sha256:5b1451727f02e7acbdf6aae4e06d75f66ee82966ff9114550381c3271a90f56c", - "sha256:6996883a8a6ff9117cbb3d6f5b0dcbbae6fb9e31e1a3e4e2f95e0214d9a1c655", - "sha256:6c96f64a54f030366657a54bb90b3093afc9c16c8e0dfa29fc0d6dbe169103a5", - "sha256:7332d5c3e35154cd234fd79573736ddcf7a0ade7a986db35b6196b9171493e75", - "sha256:7885b6f32c4a898e825bb7f56f36a02781ac4a951c63e4169f0afcf9c8c30dfb", - "sha256:7b0f63f10a166583ab744a58baad04e0f52cfea1ac27bfa1b0c21a48d1003c23", - "sha256:819f95d4eba3f9e484dd115ab7ab72845cf766b84286a00d4ecf76d33f1edca1", - "sha256:8968eeaa4d37a38f8ca1f9dbe53526b69628edc9c42229a5b2f56d98bb828c1f", - "sha256:89ebf69cb19a33d625db72d2ac589d26e936b8f7628531269accf4a3196e7872", - "sha256:8daecd778c1da45b8bd54fd41ffcd471a86beed3d8e57a43acf7a8d63bba4058", - "sha256:955ba8ea73cf3ed8bd2f963b4cb9f8f0dcb27becd2f4b3dd536fd24c45533454", - "sha256:964f18a59f5a64c0170f684c417f4fe3e695a536612e13074c4dd5d1c6d7c882", - "sha256:969843fbdfbf56cdb71da6f0bdf50f9985b8b8aeb630102945306cf10a9c6af2", - "sha256:996021ef33e0f50b97ff2d6b5f422a0fe5577de21a8873b58a779a5ddd1c3132", - "sha256:9e9c9078a7ce07e6fce366bd818be89365a35d2e4b163268f0ca9ba7e13bb2f6", - "sha256:9f4e67f87e072de981570eaf7cb41444bbac7e92b05c8651dbab6eb1fb8d5a14", - "sha256:a04901757cb0fb0f5602ac11dda48f5510f94372144d06c2563ba56c480b467c", - "sha256:a7bf1492429f18d205f3a818da3ff1f242f60aa59006e53dee00b4ef592a3363", - "sha256:aa0af2deb166a5e26e0d554b824605e660039b161e37ed4f01b8d04beec184f3", - "sha256:abfb15a6a7822f0fae681785cb38860e7a2cb1616a708d53df557b3d76c5bfd4", - "sha256:b253fe4df2afea4dfa6b1fa8c5fef212aff8bcaaeb4207e81eed05cb5e4a7919", - "sha256:b27f082f47d23cffc4cf1388b84fdc45c4ef6015f906cd7e0d988d9e35d36349", - "sha256:b33aea449e7f46738811fbc6f0b3177c6777a572207412bbbf6f525ffed001ae", - "sha256:b39989b49e8aca9d224324d2650029eda410a4faf43f6afb0eb4f9acb7be6097", - "sha256:b44f9421c4505c548435244d74037618f452844c5d3c67719d8a55e2613549da", - "sha256:bcc371151d1512201d0214c36c0c150b1dc64f19c2b1a8c9cb1d7c7c15ebd93f", - "sha256:c2851deeabd96d3f6283e9c6b26e0bfed4de2dc6fb15edf913e78b79fc5909ed", - "sha256:cdfd501c7ac5b198c15df800a3a34c38345f5182e5f80770caf362bccca65628", - "sha256:d2c0caffa47606d6d7c8af94ba42547bd2a441f06c74fd90a1ffe328524a6c64", - "sha256:dcb2db95e629962db5a355047fb8aefb012df6c8ae608930d391619dbd96fd86", - "sha256:e0eeb9c112fec2031927a1745788a181d0eecbacbed941fc5c4f7bc3f7b273bf", - "sha256:e154891263306200260d7f3051982774d7b9ef35af3509d5adbbe539afd2610c", - "sha256:e2e023a42dcbab8ed31f97c2bcdb980b7fbe0ada34037d87ba9d799664b58ded", - "sha256:e64be68255234bb489a574c4f2f8df7029c98c81ec4d160d6cd836e7f0679390", - "sha256:e82d6b930e02e80e5109b678c663a9ed210680ded81c1abaf54635d88d1da298" + "sha256:04026461eae67fdefa1949b7332e488224eac9e8f2b5c58c98b54d29af22093e", + "sha256:04927a4c651a0e9ec11c68e4427d917e44ff101f761cd3b5bc76f86aaa431d27", + "sha256:07bbf9bdcb82239f319b1f09e8ef4bdfaec50ed7d7ea51a56438f39193271163", + "sha256:09004096e953d7ebd508cded79f6b21e05dff5d7361771f59269425108e703bc", + "sha256:0adea425b764a08270820531ec2218d0508f8ae15a448568109ffcae050fee26", + "sha256:0b39ec237459922c6544d071cdcf92cbb5bc6685a30e7c6d985d8a3e3a75326e", + "sha256:0d5109337e1db373a892fdcf78eb145ffb6bbd66bb51989ec36117b9f7f9b579", + "sha256:0f41827028901814c709e744060843c77e78a3aca1e0d6875d2562372fcb405a", + "sha256:11d119507bb54e81f375e638225a2c057dda748f2b1deef05c2b1a5d42686048", + "sha256:1233e303645f468e399ec906b6b48ab7cd8391aae2d08daadbb5cad6ace4bd87", + "sha256:139705ce59d94eef2ceae9fd2ad58710b02aee91e7fa0ccb485665ca0ecbec63", + "sha256:1f03d4dadd595f7a69a75709bc81902673fa31964c75f93af74feac2f134cc54", + "sha256:240ce6dc19835971f38caf94b5738092cb1e641f8150a9ef9251b7825506cb05", + "sha256:294a6697dfa41a8cba4c365dd3715abc54d29a86a40ec6405d677ca853307cfb", + "sha256:3d55e36715ff06cdc0ab62f9591607c4324297b6b6ce5b58cb9928b3defe30ea", + "sha256:3dddf681284fe16d047d3ad37415b2e9ccdc6c8986c8062dbe51ab9a358b50a5", + "sha256:3f5f7e3a4ab824e3de1e1700f05ad76ee465f5f11f5db61c4b297ec29e692b2e", + "sha256:508999bec4422e646b05c95c598b64bdbef1edf0d2b715450a078ba21b385bcc", + "sha256:5d2a48c80cf5a338d58aae3c16872f4d452345e18350143b3bf7216d33ba7b99", + "sha256:5dc7a94bb11096bc4bffd41a3c4f2b958257085c01522aa81140c68b8bf1630a", + "sha256:65d653df249a2f95673976e4e9dd7ce10de61cfc6e64fa7eeaa6891a9559c581", + "sha256:7492af15f71f75ee93d2a618ca53fea8be85e7b625e323315169977fae752426", + "sha256:7f0055f1809b911ab347a25d786deff5e10e9cf083c3c3fd2dd04e8612e8d9db", + "sha256:807b3096205c7cec861c8803a6738e33ed86c9aae76cac0e19454245a6bbbc0a", + "sha256:81d6d8e39695f2c37954d1011c0480ef7cf444d4e3ae24bc5e89ee5de360139a", + "sha256:87c7c10d186f1743a8fd6a971ab6525d60abd5d5d200f31e073cd5e94d7e7a9d", + "sha256:8b42c0dc927b8d7c0eb59f97e6e34408e53bc489f9f90e66e568f329bff3e443", + "sha256:a00514362df15af041cc06e97aebabf2895e0a7c42c83c21894be12b84402d79", + "sha256:a39efc3ade8c1fb27c097fd112baf09d7fd70b8cb10ef1de4da6efbe066d381d", + "sha256:a4ee8000454ad4486fb9f28b0cab7fa1cd796fc36d639882d0b34109b5b3aec9", + "sha256:a7928283143a401e72a4fad43ecc85b35c27ae699cf5d54d39e1e72d97460e1d", + "sha256:adf4dd19d8875ac147bf926c727215a0faf21490b22c053db464e0bf0deb0485", + "sha256:ae8427a5e9062ba66fc2c62fb19a72276cf12c780e8db2b0956ea909c48acff5", + "sha256:b4c8b0bc5841e578d5fb32a16e0c305359b987b850a06964bd5a62739d688048", + "sha256:b84f29971f0ad4adaee391c6364e6f780d5aae7e9226d41964b26b49376071d0", + "sha256:c39c46d9e44447181cd502a35aad2bb178dbf1b1f86cf4db639d7b9614f837c6", + "sha256:cb2126603091902767d96bcb74093bd8b14982f41809f85c9b96e519c7e1dc41", + "sha256:dcef843f8de4e2ff5e35e96ec2a4abbdf403bd0f732ead127bd27e51f38ac298", + "sha256:de22905c5920f6a2af2fccc54a7897cf52f1d0a4b9de87f546c6fb70d13e4e0b", + "sha256:e3447d9e074abf0e3cd85aef8131e01ab93f9f0e86654db7ac8a3f73c63706ce", + "sha256:f52010e0a44e3d8530437e7da38d11fb822acfb0d5b12e9cd5ba655509937ca0", + "sha256:f8196f739092a78e4f6b1b2172679ed3343c39c61a3e9d722ce6fcf1dac2824a" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.1.0" + "markers": "python_version >= '3.6'", + "version": "==2.0.0" }, "httptools": { "hashes": [ @@ -468,48 +462,47 @@ }, "lxml": { "hashes": [ - "sha256:0448576c148c129594d890265b1a83b9cd76fd1f0a6a04620753d9a6bcfd0a4d", - "sha256:127f76864468d6630e1b453d3ffbbd04b024c674f55cf0a30dc2595137892d37", - "sha256:1471cee35eba321827d7d53d104e7b8c593ea3ad376aa2df89533ce8e1b24a01", - "sha256:2363c35637d2d9d6f26f60a208819e7eafc4305ce39dc1d5005eccc4593331c2", - "sha256:2e5cc908fe43fe1aa299e58046ad66981131a66aea3129aac7770c37f590a644", - "sha256:2e6fd1b8acd005bd71e6c94f30c055594bbd0aa02ef51a22bbfa961ab63b2d75", - "sha256:366cb750140f221523fa062d641393092813b81e15d0e25d9f7c6025f910ee80", - "sha256:42ebca24ba2a21065fb546f3e6bd0c58c3fe9ac298f3a320147029a4850f51a2", - "sha256:4e751e77006da34643ab782e4a5cc21ea7b755551db202bc4d3a423b307db780", - "sha256:4fb85c447e288df535b17ebdebf0ec1cf3a3f1a8eba7e79169f4f37af43c6b98", - "sha256:50c348995b47b5a4e330362cf39fc503b4a43b14a91c34c83b955e1805c8e308", - "sha256:535332fe9d00c3cd455bd3dd7d4bacab86e2d564bdf7606079160fa6251caacf", - "sha256:535f067002b0fd1a4e5296a8f1bf88193080ff992a195e66964ef2a6cfec5388", - "sha256:5be4a2e212bb6aa045e37f7d48e3e1e4b6fd259882ed5a00786f82e8c37ce77d", - "sha256:60a20bfc3bd234d54d49c388950195d23a5583d4108e1a1d47c9eef8d8c042b3", - "sha256:648914abafe67f11be7d93c1a546068f8eff3c5fa938e1f94509e4a5d682b2d8", - "sha256:681d75e1a38a69f1e64ab82fe4b1ed3fd758717bed735fb9aeaa124143f051af", - "sha256:68a5d77e440df94011214b7db907ec8f19e439507a70c958f750c18d88f995d2", - "sha256:69a63f83e88138ab7642d8f61418cf3180a4d8cd13995df87725cb8b893e950e", - "sha256:6e4183800f16f3679076dfa8abf2db3083919d7e30764a069fb66b2b9eff9939", - "sha256:6fd8d5903c2e53f49e99359b063df27fdf7acb89a52b6a12494208bf61345a03", - "sha256:791394449e98243839fa822a637177dd42a95f4883ad3dec2a0ce6ac99fb0a9d", - "sha256:7a7669ff50f41225ca5d6ee0a1ec8413f3a0d8aa2b109f86d540887b7ec0d72a", - "sha256:7e9eac1e526386df7c70ef253b792a0a12dd86d833b1d329e038c7a235dfceb5", - "sha256:7ee8af0b9f7de635c61cdd5b8534b76c52cd03536f29f51151b377f76e214a1a", - "sha256:8246f30ca34dc712ab07e51dc34fea883c00b7ccb0e614651e49da2c49a30711", - "sha256:8c88b599e226994ad4db29d93bc149aa1aff3dc3a4355dd5757569ba78632bdf", - "sha256:91d6dace31b07ab47eeadd3f4384ded2f77b94b30446410cb2c3e660e047f7a7", - "sha256:923963e989ffbceaa210ac37afc9b906acebe945d2723e9679b643513837b089", - "sha256:94d55bd03d8671686e3f012577d9caa5421a07286dd351dfef64791cf7c6c505", - "sha256:97db258793d193c7b62d4e2586c6ed98d51086e93f9a3af2b2034af01450a74b", - "sha256:a9d6bc8642e2c67db33f1247a77c53476f3a166e09067c0474facb045756087f", - "sha256:cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc", - "sha256:d8d3d4713f0c28bdc6c806a278d998546e8efc3498949e3ace6e117462ac0a5e", - "sha256:e0bfe9bb028974a481410432dbe1b182e8191d5d40382e5b8ff39cdd2e5c5931", - "sha256:e1dbb88a937126ab14d219a000728224702e0ec0fc7ceb7131c53606b7a76772", - "sha256:f4822c0660c3754f1a41a655e37cb4dbbc9be3d35b125a37fab6f82d47674ebc", - "sha256:f83d281bb2a6217cd806f4cf0ddded436790e66f393e124dfe9731f6b3fb9afe", - "sha256:fc37870d6716b137e80d19241d0e2cff7a7643b925dfa49b4c8ebd1295eb506e" + "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d", + "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3", + "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2", + "sha256:1822d16e5ac9061749955d099ff50c6cbc068f8cbfde28dfbeea845f7fbe6e09", + "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f", + "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927", + "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3", + "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7", + "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f", + "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade", + "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468", + "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b", + "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4", + "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83", + "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04", + "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791", + "sha256:74f69060f98a70e3654de3021cd8162859e0f30b9e69aed76ef2b7a2e3b84212", + "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51", + "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1", + "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a", + "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f", + "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee", + "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec", + "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969", + "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28", + "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a", + "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa", + "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106", + "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d", + "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4", + "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0", + "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4", + "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2", + "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0", + "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654", + "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2", + "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23", + "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.6.2" + "version": "==4.6.3" }, "msgpack": { "hashes": [ @@ -589,19 +582,19 @@ }, "ocrmypdf": { "hashes": [ - "sha256:2eda9aeef0c6326af8af9605a8b5903ed6ae4a4537d4046d16ad8bb7ff021ec2", - "sha256:4befdf50b6ed3fe3bb9d0ab1801b213e56138e21ba5b4b3f3cada51c72b7a314" + "sha256:329b070959731c277f0df91cfe011dd4da0d6534f23a739a3aa77bdab00fbc2f", + "sha256:b63df1b6bf37f29b41cb07f0328240a235d84c3dffc3a32299c71fa94c92d419" ], "index": "pypi", - "version": "==11.7.2" + "version": "==11.7.3" }, "pathvalidate": { "hashes": [ - "sha256:378c8b319838a255c00ab37f664686b75f0aabea4444d6c5a34effbec6738285", - "sha256:cae8ad5cd9223c5c1f4bc4e2ef0cd4c5e89acd2d698fdb7610ee108b9be654d2" + "sha256:5263a75d6335b2e9ac2010f38fbd85225b8dff274ded63e5ac21d94ce6b130c8", + "sha256:d0dab13e121628829f5aeb01220ca7af00c3b3b2fe5d83dc81fa0612ad58ade9" ], "index": "pypi", - "version": "==2.3.2" + "version": "==2.4.0" }, "pdfminer.six": { "hashes": [ @@ -613,72 +606,72 @@ }, "pikepdf": { "hashes": [ - "sha256:00372f75f630b1eedd22022cad622c7313b7a42c76b6aa9a91cabaa93915cbf0", - "sha256:0168b05e020f8ac3f027c61841bb222bb0876fdc21e1b0e44cfca8c7f188b17a", - "sha256:07a3b156766a45ef04b6919116468456c7d1fa05ac1a5a5999f08fd6213a7ada", - "sha256:087edf03ef41f76c84d7f65cfd325fbea6e684a134463f0d43f57c3e787c57f1", - "sha256:0f2f2dcf3ceab6572cb6f3dc893b49e5db65232a13de03ae87a66aa220e47d96", - "sha256:27ef5649d4a0d511bdffa5752b9a014441d8c09bf955479db53c41ffb94ee1ca", - "sha256:3096d128df599d48a69bbe6a32ecd3c4b8b2219dfb94c91509c781e94c20abb9", - "sha256:45a5988f7db8c428beae7dd648df30431e1d7892f3901f4c20bb618ed3e29244", - "sha256:5e9d5789ace2ac4007916848a5cc59bc4a1aa020a794cb384538ca0f0b9b9fe6", - "sha256:63b0a1b4c43deb618f3ebaed0e5861bff658916ea02ac2f6adacf8912b702628", - "sha256:68523f606575aef92a1f6d6de030d5e82f7e3e8712f53e36c9fa5c635e15794e", - "sha256:6bea9cf387709dd478a85f737f972a910bb0dbfa055ee636a41f0c425a769057", - "sha256:71fe23a61607ac85cf357baef42be55d525f5d5c9f560482862beaf59e5dc2bc", - "sha256:780082b54e502fb76af082dc6a1cbed635205a319aa54a9e0f0570bed20c9edf", - "sha256:7a816f4bb461366dad0165a1c81294d5e9a60009cbb5c803e2519eb0d250e757", - "sha256:88373178c1020b9f391f929e5f86056a9d920301f82e5489146af629fa4654d0", - "sha256:96c8bf46ac27482a9ca00565f41ddde546fff35c50db61eefaeb88849bcb9895", - "sha256:99c19cf0dd0fc89fc9e6a0de61e974e34d4111dd69802aeaee3e61fb1a74a3d8", - "sha256:bad118d9104fffc06664d51c8716a905e5d712b85ed65edc56a708486803f70f", - "sha256:bae06503ed36167b2ea5ea25003692d3edbf95bea2e67a1d595984c91d783eb4", - "sha256:cd73a1e82cfa5d378adccf9c44b0060c2d3c5e36958f0b5ecedb3f8e81742582", - "sha256:dd65214e23e2cc883af8c2341e6fe7ae71225fa644517ac25110d6ad2b31f026", - "sha256:fd1e339322c94b0c398aaa37d517c24a3db7bbda4fdc6bf57af3894293b8e1a6" + "sha256:018ee534527debd2cfcde0dd856a454a218ddb57e5ba1240810489e50be70a6e", + "sha256:19e4fdafb66b2093b42cd81230122f4789d0ef90d85d451bcb0249739295303d", + "sha256:232789113d6044816e5eeff0061e9014febfc889cf24be9fb17d172c504c1b53", + "sha256:6637f1895e5e93b2032077ded757846c9a90147fb9195bb73dd4b8a2f333e888", + "sha256:7a804515942049f846d548d3b817317f8136e06938737ff64b79c82d61908e27", + "sha256:7c90ae70684efad9477c4ada293187a4542afd685029f82b478f011d4f8cdcc0", + "sha256:7dea84178ebfb35195eedca47a38d99ca8264e1c6e8ff6f37ccb5d7b2ca903d3", + "sha256:95f36bd3920159320547c61c7aa753b9a423e43fedb350617c7eb9925bf48618", + "sha256:a5b57f1b5d5df49b0269e8039b1ba08abb42fdd6f5b6c4b49635be754a77472a", + "sha256:ae8ead8f975864aaf97b24cd916d1bf2e536eb64e7afb65ca679ed29b1ca5b89", + "sha256:b11e1bbc38eb90bfbf2eb0f2f50b300c4142732c148802d6e5f4caa5727fc81e", + "sha256:b192cb3f087509075febb28652d48800da1f3fc1842f94cea25a49fba7350a06", + "sha256:c024de7e57329353f82d287ca13e118e1438b6fd94b33475a474cd7fd16fbb8d", + "sha256:d05a5d22f1bec0979678388c453644f83f74348ab821815b9f1ccb947d4a21e4", + "sha256:d124e11eaacf5fe1bf77ca4c1b6b1a8d5285d00d3593c5cb6eba53058cdf9dae", + "sha256:dde6fde7a32c31aa515782ea967e32dbea97a19ef3fbbde45a93c5f65cabb36f", + "sha256:e03dd2131eba5c966fbb46b675006753945a251e9e9ad44ef141257db37b9c1a", + "sha256:e345206fe51b862022ece4e4e7468bbb955eacda9a9684387ff2f1c91c1def03", + "sha256:e7295619ea4b0fa714bfff24aaf865f7e6c298e82e77ce127b6a76f47377f7f3", + "sha256:f0cdb331b585074a50e9c8a967f68b905aa8674cc3d6577f004a93414f70f211", + "sha256:f3bd63e6db4a105074f6b5951a71313bc0ca8530b0050e3a03680639d05b5500", + "sha256:f6aaf410174ba10df545ccb6fe9b42fa5fd34b1bb4df366722af640275f3406a", + "sha256:ff48af76f461f40f36917baad52918f9afcb45762a7f4c07b6a7ec7e976d558d" ], "index": "pypi", - "version": "==2.9.1" + "version": "==2.10.0" }, "pillow": { "hashes": [ - "sha256:15306d71a1e96d7e271fd2a0737038b5a92ca2978d2e38b6ced7966583e3d5af", - "sha256:1940fc4d361f9cc7e558d6f56ff38d7351b53052fd7911f4b60cd7bc091ea3b1", - "sha256:1f93f2fe211f1ef75e6f589327f4d4f8545d5c8e826231b042b483d8383e8a7c", - "sha256:30d33a1a6400132e6f521640dd3f64578ac9bfb79a619416d7e8802b4ce1dd55", - "sha256:328240f7dddf77783e72d5ed79899a6b48bc6681f8d1f6001f55933cb4905060", - "sha256:46c2bcf8e1e75d154e78417b3e3c64e96def738c2a25435e74909e127a8cba5e", - "sha256:5762ebb4436f46b566fc6351d67a9b5386b5e5de4e58fdaa18a1c83e0e20f1a8", - "sha256:5a2d957eb4aba9d48170b8fe6538ec1fbc2119ffe6373782c03d8acad3323f2e", - "sha256:5cf03b9534aca63b192856aa601c68d0764810857786ea5da652581f3a44c2b0", - "sha256:5daba2b40782c1c5157a788ec4454067c6616f5a0c1b70e26ac326a880c2d328", - "sha256:63cd413ac52ee3f67057223d363f4f82ce966e64906aea046daf46695e3c8238", - "sha256:6efac40344d8f668b6c4533ae02a48d52fd852ef0654cc6f19f6ac146399c733", - "sha256:71b01ee69e7df527439d7752a2ce8fb89e19a32df484a308eca3e81f673d3a03", - "sha256:71f31ee4df3d5e0b366dd362007740106d3210fb6a56ec4b581a5324ba254f06", - "sha256:72027ebf682abc9bafd93b43edc44279f641e8996fb2945104471419113cfc71", - "sha256:74cd9aa648ed6dd25e572453eb09b08817a1e3d9f8d1bd4d8403d99e42ea790b", - "sha256:81b3716cc9744ffdf76b39afb6247eae754186838cedad0b0ac63b2571253fe6", - "sha256:8565355a29655b28fdc2c666fd9a3890fe5edc6639d128814fafecfae2d70910", - "sha256:87f42c976f91ca2fc21a3293e25bd3cd895918597db1b95b93cbd949f7d019ce", - "sha256:89e4c757a91b8c55d97c91fa09c69b3677c227b942fa749e9a66eef602f59c28", - "sha256:8c4e32218c764bc27fe49b7328195579581aa419920edcc321c4cb877c65258d", - "sha256:903293320efe2466c1ab3509a33d6b866dc850cfd0c5d9cc92632014cec185fb", - "sha256:90882c6f084ef68b71bba190209a734bf90abb82ab5e8f64444c71d5974008c6", - "sha256:98afcac3205d31ab6a10c5006b0cf040d0026a68ec051edd3517b776c1d78b09", - "sha256:a01da2c266d9868c4f91a9c6faf47a251f23b9a862dce81d2ff583135206f5be", - "sha256:aeab4cd016e11e7aa5cfc49dcff8e51561fa64818a0be86efa82c7038e9369d0", - "sha256:b07c660e014852d98a00a91adfbe25033898a9d90a8f39beb2437d22a203fc44", - "sha256:bd08a7e01d388c5e0b5b46b52081e01dc96ef226aeed13fa1d7af94b81d4e93b", - "sha256:bead24c0ae3f1f6afcb915a057943ccf65fc755d11a1410a909c1fefb6c06ad1", - "sha256:d1d6bca39bb6dd94fba23cdb3eeaea5e30c7717c5343004d900e2a63b132c341", - "sha256:e2cd8ac157c1e5ae88b6dd790648ee5d2777e76f1e5c7d184eaddb2938594f34", - "sha256:e5739ae63636a52b706a0facec77b2b58e485637e1638202556156e424a02dc2", - "sha256:f36c3ff63d6fc509ce599a2f5b0d0732189eed653420e7294c039d342c6e204a", - "sha256:f91b50ad88048d795c0ad004abbe1390aa1882073b1dca10bfd55d0b8cf18ec5" + "sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5", + "sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4", + "sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9", + "sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a", + "sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9", + "sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727", + "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120", + "sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c", + "sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2", + "sha256:3da86987a323708512d4d35939b29854286ad88940ee10f2eac48bfec9dba678", + "sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797", + "sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b", + "sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f", + "sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef", + "sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232", + "sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb", + "sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9", + "sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812", + "sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178", + "sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b", + "sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5", + "sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b", + "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1", + "sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713", + "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4", + "sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484", + "sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c", + "sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9", + "sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388", + "sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d", + "sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602", + "sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9", + "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e", + "sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2" ], "index": "pypi", - "version": "==8.1.2" + "version": "==8.2.0" }, "pluggy": { "hashes": [ @@ -690,11 +683,11 @@ }, "portalocker": { "hashes": [ - "sha256:afa66c85041d7bac1532acb74ff26cc2406472dcf7145c90c31ff8ca4f1cc146", - "sha256:e5f6ffb2f360e9aef615a7c284143d2a93bb640c62e8e45a703e6083fc5aa114" + "sha256:1d43fd8223e1743f5725e8910f69e7a45858ffd298e19252633ac903eafd83bc", + "sha256:4e913d807aa6598c320e8a50c50e2ee0602bc45240b485e3f8bc06f13060084c" ], "markers": "python_version >= '3'", - "version": "==2.2.1" + "version": "==2.3.0" }, "psycopg2-binary": { "hashes": [ @@ -801,11 +794,11 @@ }, "python-dotenv": { "hashes": [ - "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e", - "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0" + "sha256:31d752f5b748f4e292448c9a0cac6a08ed5e6f4cefab85044462dcad56905cec", + "sha256:9fa413c37d4652d3fa02fea0ff465c384f5db75eab259c4fc5d0c5b8bf20edd4" ], "index": "pypi", - "version": "==0.15.0" + "version": "==0.16.0" }, "python-gnupg": { "hashes": [ @@ -1245,6 +1238,7 @@ "sha256:12588a46ae0a99f172c4524cbbc3bb870f32e0f8405e9fa11a5ef3fa3a808ad7", "sha256:16caa44a06f6b0b2f7626ced4b193c1ae5d09c1b49c9b4962c93ae8aa2134f55", "sha256:18c478b89b6505756f007dcf76a67224a23dcf0f365427742ed0c0473099caa4", + "sha256:1bbb0bca8a3556a21f7b66c0a18876d8c617ddeda00982204b6218170b39526a", "sha256:221b41442cf4428fcda7fc958c9721c916709e2a3a9f584edd70f1493a09a762", "sha256:26109c50ccbcc10f651f76277cfc05fba8418a907daccc300c9247f24b3158a2", "sha256:28d8157f8c77662a1e0796a7d3cfa8910289131d4b4dd4e10b2686ab1309b67b", @@ -1284,6 +1278,7 @@ "sha256:d12895cd083e35e9e032eb4b57645b91116f8979527381a8d864d1f6b8cb4a2e", "sha256:d3cd9bad547a8e5fbe712a1dc1413aff1b917e8d39a2cd1389a6f933b7a21460", "sha256:e8809b01f27f679e3023b9e2013051e0a3f17abff4228cb5197663afd8a0f2c7", + "sha256:e8d49011baa7ce7765db46e53cfc8d125463a58e3eb478111b2c0c00ca098a33", "sha256:f3c37b0dc1898e305aad4f7a1d75f6da83036588c28a9ce0afc681ff5245a601", "sha256:f966765f54b536e791541458de84a737a6adba8467190f17a8fe7f85354ba908", "sha256:fa939c2e2468142c9773443d4038e7c915b0cc1b670d3c9192bdc503f7ea73e9", @@ -1453,11 +1448,11 @@ }, "faker": { "hashes": [ - "sha256:60a7263104ef7a14ecfe2af1142d53924aa534ccec85cea82bb67b2b32f84421", - "sha256:f43ac743c34affb1c7fccca8b06450371cd482b6ddcb4110e420acb24356e70b" + "sha256:08c4cfbfd498c0e90aff6741771c01803d894013df858db6a573182c6a47951f", + "sha256:20c6e4253b73ef2a783d38e085e7c8d8916295fff31c7403116d2af8f908f7ca" ], "markers": "python_version >= '3.6'", - "version": "==6.6.2" + "version": "==7.0.1" }, "filelock": { "hashes": [ diff --git a/README.md b/README.md index 45c71ab67..5cac22e55 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,12 @@ Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. These key points should help you decide whether Paperless-ng is something you would prefer over Paperless: -* Interface: The new front end is the main interface for paperless-ng, the old interface still exists but most customizations (such as thumbnails for the document list) have been removed. +* Interface: The new front end is the main interface for Paperless-ng, the old interface still exists but most customizations (such as thumbnails for the document list) have been removed.0 * Encryption: Paperless-ng does not support GnuPG anymore, since storing your data on encrypted file systems (that you optionally mount on demand) achieves about the same result. -* Resource usage: Paperless-ng does use a bit more resources than Paperless. Running the web server requires about 300MB of RAM or more, depending on the configuration. While adding documents, it requires about 300MB additional RAM, depending on the document. It still runs on Pi (many users do that), but it has been generally geared to better use the resources of more powerful systems. +* Resource usage: Paperless-ng does use a bit more resources than Paperless. Running the web server requires about 300MB of RAM or more, depending on the configuration. While adding documents, it requires about 300MB additional RAM, depending on the document. It still runs on Raspberry Pi (many users do that), but it has been generally geared to better use the resources of more powerful systems. * API changes: If you rely on the REST API of paperless, some of its functionality has been changed. -For a detailed list of changes, have a look at the [change log](https://paperless-ng.readthedocs.io/en/latest/changelog.html) in the documentation. +For a detailed list of changes, have a look at the [change log](https://paperless-ng.readthedocs.io/en/latest/changelog.html) in the documentation, especially the section about the [0.9.0 release](https://paperless-ng.readthedocs.io/en/latest/changelog.html#paperless-ng-0-9-0). # How it Works @@ -25,7 +25,7 @@ Paperless does not control your scanner, it only helps you deal with what your s 1. Buy a document scanner that can write to a place on your network. If you need some inspiration, have a look at the [scanner recommendations](https://paperless-ng.readthedocs.io/en/latest/scanners.html) page. Set it up to "scan to FTP" or something similar. It should be able to push scanned images to a server without you having to do anything. Of course if your scanner doesn't know how to automatically upload the file somewhere, you can always do that manually. Paperless doesn't care how the documents get into its local consumption directory. - - Alternatively, you can use any of the mobile scanning apps out there. We have an app that allows you to share documents with paperless, if you're on Android. See the section on affiliated projects. + - Alternatively, you can use any of the mobile scanning apps out there. We have an app that allows you to share documents with paperless, if you're on Android. See the section on affiliated projects below. 2. Wait for paperless to process your files. OCR is expensive, and depending on the power of your machine, this might take a bit of time. 3. Use the web frontend to sift through the database and find what you want. @@ -35,6 +35,8 @@ Here's what you get: ![Dashboard](https://github.com/jonaswinkler/paperless-ng/raw/master/docs/_static/screenshots/dashboard.png) +If you want to see paperless-ng in action, [more screenshots are available in the documentation](https://paperless-ng.readthedocs.io/en/latest/screenshots.html). + # Features * Performs OCR on your documents, adds selectable text to image only documents and adds tags, correspondents and document types to your documents. @@ -58,19 +60,17 @@ Here's what you get: * Optimized for multi core systems: Paperless-ng consumes multiple documents in parallel. * The integrated sanity checker makes sure that your document archive is in good health. -If you want to see some screenshots of paperless-ng in action, [some are available in the documentation](https://paperless-ng.readthedocs.io/en/latest/screenshots.html). - # Getting started The recommended way to deploy paperless is docker-compose. The files in the /docker/hub directory are configured to pull the image from Docker Hub. Read the [documentation](https://paperless-ng.readthedocs.io/en/latest/setup.html#installation) on how to get started. -Alternatively, you can install the dependencies and setup apache and a database server yourself. The documenation has a step by step guide on how to do it. +Alternatively, you can install the dependencies and setup apache and a database server yourself. The documenation has a step by step guide on how to do it. Consider giving the Ansible role a shot, this essentially automates the entire bare metal installation process. -# Migrating to paperless-ng +# Migrating from Paperless to Paperless-ng -Read the section about [migration](https://paperless-ng.readthedocs.io/en/latest/setup.html#migration-to-paperless-ng) in the documentation. Its also entirely possible to go back to paperless by reverting the database migrations. +Read the section about [migration](https://paperless-ng.readthedocs.io/en/latest/setup.html#migration-to-paperless-ng) in the documentation. Its also entirely possible to go back to Paperless by reverting the database migrations. # Documentation @@ -78,9 +78,7 @@ The documentation for Paperless-ng is available on [ReadTheDocs](https://paperle # Translation -Paperless is currently available in English, German, Dutch, French, Portuguese, Italian, and Romanian. - -There's an active translation project at crowdin! If you want to help out by translating paperless into your language, please head over to https://github.com/jonaswinkler/paperless-ng/issues/212 for details. +Paperless is available in many different languages. Translation is coordinated at crowdin. If you want to help out by translating paperless into your language, please head over to https://github.com/jonaswinkler/paperless-ng/issues/212 for details! # Feature Requests @@ -94,7 +92,7 @@ For bugs please [open an issue](https://github.com/jonaswinkler/paperless-ng/iss There's still lots of things to be done, just have a look at open issues & discussions. If you feel like contributing to the project, please do! Bug fixes and improvements to the front end (I just can't seem to get some of these CSS things right) are always welcome. The documentation has some basic information on how to get started. -If you want to implement something big: Please start a discussion about that in the issues! Maybe I've already had something similar in mind and we can make it happen together. However, keep in mind that the general roadmap is to make the existing features stable and get them tested. See the roadmap above. +If you want to implement something big: Please start a discussion about that! Maybe I've already had something similar in mind and we can make it happen together. However, keep in mind that the general roadmap is to make the existing features stable and get them tested. # Affiliated Projects diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 5919b14aa..cf6129438 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -68,6 +68,17 @@ migrations() { } +search_index() { + index_version=1 + index_version_file=/usr/src/paperless/data/.index_version + + if [[ (! -f "$index_version_file") || $(< $index_version_file) != "$index_version" ]]; then + echo "Search index out of date. Updating..." + sudo -HEu paperless python3 manage.py document_index reindex + echo $index_version | sudo -HEu paperless tee $index_version_file >/dev/null + fi +} + initialize() { map_uidgid @@ -87,6 +98,7 @@ initialize() { migrations + search_index } install_languages() { diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst index c64df4317..b7d46e063 100644 --- a/docs/advanced_usage.rst +++ b/docs/advanced_usage.rst @@ -10,14 +10,13 @@ easier. Matching tags, correspondents and document types ################################################ -After the consumer has tried to figure out what it could from the file name, -it starts looking at the content of the document itself. It will compare the -matching algorithms defined by every tag and correspondent already set in your -database to see if they apply to the text in that document. In other words, -if you defined a tag called ``Home Utility`` that had a ``match`` property of -``bc hydro`` and a ``matching_algorithm`` of ``literal``, Paperless will -automatically tag your newly-consumed document with your ``Home Utility`` tag -so long as the text ``bc hydro`` appears in the body of the document somewhere. +Paperless will compare the matching algorithms defined by every tag and +correspondent already set in your database to see if they apply to the text in +a document. In other words, if you defined a tag called ``Home Utility`` +that had a ``match`` property of ``bc hydro`` and a ``matching_algorithm`` of +``literal``, Paperless will automatically tag your newly-consumed document with +your ``Home Utility`` tag so long as the text ``bc hydro`` appears in the body +of the document somewhere. The matching logic is quite powerful, and supports searching the text of your document with different algorithms, and as such, some experimentation may be diff --git a/docs/api.rst b/docs/api.rst index c2120b20f..3a9d244c5 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -147,93 +147,57 @@ The REST api provides three different forms of authentication. Searching for documents ####################### -Paperless-ng offers API endpoints for full text search. These are as follows: +Full text searching is available on the ``/api/documents/`` endpoint. Two specific +query parameters cause the API to return full text search results: -``/api/search/`` -================ +* ``/api/documents/?query=your%20search%20query``: Search for a document using a full text query. + For details on the syntax, see :ref:`basic-usage_searching`. -Get search results based on a query. +* ``/api/documents/?more_like=1234``: Search for documents similar to the document with id 1234. -Query parameters: +Pagination works exactly the same as it does for normal requests on this endpoint. -* ``query``: The query string. See - `here `_ - for details on the syntax. -* ``page``: Specify the page you want to retrieve. Each page - contains 10 search results and the first page is ``page=1``, which - is the default if this is omitted. +Certain limitations apply to full text queries: -Result list object returned by the endpoint: +* Results are always sorted by search score. The results matching the query best will show up first. -.. code:: json +* Only a small subset of filtering parameters are supported. + +Furthermore, each returned document has an additional ``__search_hit__`` attribute with various information +about the search results: + +.. code:: { - "count": 1, - "page": 1, - "page_count": 1, - "corrected_query": "", + "count": 31, + "next": "http://localhost:8000/api/documents/?page=2&query=test", + "previous": null, "results": [ + ... + + { + "id": 123, + "title": "title", + "content": "content", + + ... + + "__search_hit__": { + "score": 0.343, + "highlights": "text Test text", + "rank": 23 + } + }, + + ... + ] } -* ``count``: The approximate total number of results. -* ``page``: The page returned to you. This might be different from - the page you requested, if you requested a page that is behind - the last page. In that case, the last page is returned. -* ``page_count``: The total number of pages. -* ``corrected_query``: Corrected version of the query string. Can be null. - If not null, can be used verbatim to start a new query. -* ``results``: A list of result objects on the current page. - -Result object: - -.. code:: json - - { - "id": 1, - "highlights": [ - - ], - "score": 6.34234, - "rank": 23, - "document": { - - } - } - -* ``id``: the primary key of the found document -* ``highlights``: an object containing parsable highlights for the result. - See below. -* ``score``: The score assigned to the document. A higher score indicates a - better match with the query. Search results are sorted descending by score. -* ``rank``: the position of the document within the entire search results list. -* ``document``: The full json of the document, as returned by - ``/api/documents//``. - -Highlights object: - -Highlights are provided as a list of fragments. A fragment is a longer section of -text from the original document. -Each fragment contains a list of strings, and some of them are marked as a highlight. - -.. code:: json - - [ - [ - {"text": "This is a sample text with a ", "highlight": false}, - {"text": "highlighted", "highlight": true}, - {"text": " word.", "highlight": false} - ], - [ - {"text": "Another", "highlight": true}, - {"text": " fragment with a highlight.", "highlight": false} - ] - ] - -A client may use this example to produce the following output: - -... This is a sample text with a **highlighted** word. ... **Another** fragment with a highlight. ... +* ``score`` is an indication how well this document matches the query relative to the other search results. +* ``highlights`` is an excerpt from the document content and highlights the search terms with ```` tags as shown above. +* ``rank`` is the index of the search results. The first result will have rank 0. ``/api/search/autocomplete/`` ============================= diff --git a/docs/changelog.rst b/docs/changelog.rst index 7010350a8..454f912f5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,48 @@ Changelog ********* +paperless-ng 1.4.0 +################## + +* Docker images now use tesseract 4.1.1, which should fix a series of issues with OCR. + +* The full text search now displays results using the default document list. This enables + selection, filtering and bulk edit on search results. + +* Changes + + * New URL pattern for accessing documents by ASN directly (http:///asn/123) + + * Added logging when executing pre- and post-consume scripts. + + * Better error logging during document consumption. + + * Updated python dependencies. + + * Automatically inserts typed text when opening "Create new" dialogs on the document details page. + +* Fixes + + * Fixed an issue with null characters in the document content. + +.. note:: + + The changed to the full text searching require you to reindex your documents. + *The docker image does this automatically, you don't need to do anything.* + To do this, execute the ``document_index reindex`` management command + (see :ref:`administration-index`). + +.. note:: + + Some packages that paperless depends on are slowly dropping Python 3.6 + support one after another, including the web server. Supporting Python + 3.6 means that I cannot update these packages anymore. + + At some point, paperless will drop Python 3.6 support. If using a bare + metal installation and you're still on Python 3.6, upgrade to 3.7 or newer. + + If using docker, this does not affect you. + paperless-ng 1.3.2 ################## @@ -108,17 +150,6 @@ paperless-ng 1.2.0 * Paperless no longer depends on ``libpoppler-cpp-dev``. -.. note:: - - Some packages that paperless depends on are slowly dropping Python 3.6 - support one after another, including the web server. Supporting Python - 3.6 means that I cannot update these packages anymore. - - At some point, paperless will drop Python 3.6 support. If using a bare - metal installation and you're still on Python 3.6, upgrade to 3.7 or newer. - - If using docker, this does not affect you. - paperless-ng 1.1.4 ################## diff --git a/docs/scanners.rst b/docs/scanners.rst index ad7566c71..752063bb4 100644 --- a/docs/scanners.rst +++ b/docs/scanners.rst @@ -13,26 +13,35 @@ that works right for you based on recommendations from other Paperless users. Physical scanners ================= -+---------+----------------+-----+-----+-----+----------------+ -| Brand | Model | Supports | Recommended By | -+---------+----------------+-----+-----+-----+----------------+ -| | | FTP | NFS | SMB | | -+=========+================+=====+=====+=====+================+ -| Brother | `ADS-1500W`_ | yes | no | yes | `danielquinn`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Brother | `MFC-J6930DW`_ | yes | | | `ayounggun`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Brother | `MFC-J5910DW`_ | yes | | | `bmsleight`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Brother | `MFC-9142CDN`_ | yes | | yes | `REOLDEV`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Fujitsu | `ix500`_ | yes | | yes | `eonist`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Epson | `WF-7710DWF`_ | yes | | yes | `Skylinar`_ | -+---------+----------------+-----+-----+-----+----------------+ -| Fujitsu | `S1300i`_ | yes | | yes | `jonaswinkler`_| -+---------+----------------+-----+-----+-----+----------------+ ++---------+----------------+-----+-----+-----+------+----------------+ +| Brand | Model | Supports | Recommended By | ++---------+----------------+-----+-----+-----+------+----------------+ +| | | FTP | NFS | SMB | SMTP | | ++=========+================+=====+=====+=====+======+================+ +| Brother | `ADS-1700W`_ | yes | no | yes | yes |`holzhannes`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `ADS-1600W`_ | yes | no | yes | yes |`holzhannes`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `ADS-1500W`_ | yes | no | yes | yes |`danielquinn`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `MFC-J6930DW`_ | yes | | | |`ayounggun`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `MFC-L5850DW`_ | yes | | | yes |`holzhannes`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `MFC-J5910DW`_ | yes | | | |`bmsleight`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Brother | `MFC-9142CDN`_ | yes | | yes | |`REOLDEV`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Fujitsu | `ix500`_ | yes | | yes | |`eonist`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Epson | `WF-7710DWF`_ | yes | | yes | |`Skylinar`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +| Fujitsu | `S1300i`_ | yes | | yes | |`jonaswinkler`_ | ++---------+----------------+-----+-----+-----+------+----------------+ +.. _MFC-L5850DW: https://www.brother-usa.com/products/mfcl5850dw +.. _ADS-1700W: https://www.brother-usa.com/products/ads1700w +.. _ADS-1600W: https://www.brother-usa.com/products/ads1600w .. _ADS-1500W: https://www.brother.ca/en/p/ads1500w .. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW .. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw @@ -41,6 +50,7 @@ Physical scanners .. _WF-7710DWF: https://www.epson.de/en/products/printers/inkjet-printers/for-home/workforce-wf-7710dwf .. _S1300i: https://www.fujitsu.com/global/products/computing/peripheral/scanners/soho/s1300i/ + .. _danielquinn: https://github.com/danielquinn .. _ayounggun: https://github.com/ayounggun .. _bmsleight: https://github.com/bmsleight @@ -48,25 +58,33 @@ Physical scanners .. _REOLDEV: https://github.com/REOLDEV .. _Skylinar: https://github.com/Skylinar .. _jonaswinkler: https://github.com/jonaswinkler +.. _holzhannes: https://github.com/holzhannes Mobile phone software ===================== You can use your phone to "scan" documents. The regular camera app will work, but may have too low contrast for OCR to work well. Apps specifically for scanning are recommended. -+-------------------+----------------+-----+-----+-----+-------+--------+----------------+ -| Name | OS | Supports | Recommended By | -+-------------------+----------------+-----+-----+-----+-------+--------+----------------+ -| | | FTP | NFS | SMB | Email | WebDav | | -+===================+================+=====+=====+=====+=======+========+================+ -| `Office Lens`_ | Android | ? | ? | ? | ? | ? | `jonaswinkler`_| -+-------------------+----------------+-----+-----+-----+-------+--------+----------------+ -| `Genius Scan`_ | Android | yes | no | yes | yes | yes | `hannahswain`_ | -+-------------------+----------------+-----+-----+-----+-------+--------+----------------+ ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ +| Name | OS | Supports | Recommended By | ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ +| | | FTP | NFS | SMB | Email | WebDav | | ++===================+================+=====+=====+=====+=======+========+==================+ +| `Office Lens`_ | Android | ? | ? | ? | ? | ? | `jonaswinkler`_ | ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ +| `Genius Scan`_ | Android | yes | no | yes | yes | yes | `hannahswain`_ | ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ +| `OpenScan`_ | Android | no | no | no | no | no | `benjaminfrank`_ | ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ +| `Quick Scan`_ | iOS | no | no | no | no | no | `holzhannes`_ | ++-------------------+----------------+-----+-----+-----+-------+--------+------------------+ -On Android, you can use these applications in combination with one of the :ref:`Paperless-ng compatible apps ` to "Share" the documents produced by these scanner apps with paperless. +On Android, you can use these applications in combination with one of the :ref:`Paperless-ng compatible apps ` to "Share" the documents produced by these scanner apps with paperless. On iOS, you can share the scanned documents via iOS-Sharing to other mail, WebDav or FTP apps. .. _Office Lens: https://play.google.com/store/apps/details?id=com.microsoft.office.officelens .. _Genius Scan: https://play.google.com/store/apps/details?id=com.thegrizzlylabs.geniusscan.free +.. _Quick Scan: https://apps.apple.com/us/app/quickscan-scanner-text-ocr/id1513790291 +.. _OpenScan: https://github.com/Ethereal-Developers-Inc/OpenScan .. _hannahswain: https://github.com/hannahswain +.. _benjaminfrank: https://github.com/benjaminfrank diff --git a/docs/usage_overview.rst b/docs/usage_overview.rst index 2c7093b99..7283db02f 100644 --- a/docs/usage_overview.rst +++ b/docs/usage_overview.rst @@ -255,6 +255,8 @@ Here are a couple examples of tags and types that you could use in your collecti * A tag ``missing_metadata`` when you still need to add some metadata to a document, but can't or don't want to do this right now. +.. _basic-usage_searching: + Searching ######### diff --git a/requirements.txt b/requirements.txt index 33d44f136..853cd6f77 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ click==7.1.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, coloredlogs==15.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' concurrent-log-handler==0.9.19 constantly==15.1.0 -cryptography==3.4.6 +cryptography==3.4.7 daphne==3.0.1; python_version >= '3.6' dateparser==1.0.0 django-cors-headers==3.7.0 @@ -33,12 +33,12 @@ django-filter==2.4.0 django-picklefield==3.0.1; python_version >= '3' django-q==1.3.4 django==3.1.7 -djangorestframework==3.12.2 +djangorestframework==3.12.4 filelock==3.0.12 fuzzywuzzy[speedup]==0.18.0 -gunicorn==20.0.4 +gunicorn==20.1.0 h11==0.12.0; python_version >= '3.6' -hiredis==1.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +hiredis==2.0.0; python_version >= '3.6' httptools==0.1.1 humanfriendly==9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' hyperlink==21.0.0 @@ -50,23 +50,23 @@ inotify-simple==1.3.5; python_version >= '2.7' and python_version not in '3.0, 3 inotifyrecursive==0.3.5 joblib==1.0.1; python_version >= '3.6' langdetect==1.0.8 -lxml==4.6.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +lxml==4.6.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' msgpack==1.0.2 numpy==1.19.5 -ocrmypdf==11.7.2 -pathvalidate==2.3.2 +ocrmypdf==11.7.3 +pathvalidate==2.4.0 pdfminer.six==20201018 -pikepdf==2.9.1 -pillow==8.1.2 +pikepdf==2.10.0 +pillow==8.2.0 pluggy==0.13.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -portalocker==2.2.1; python_version >= '3' +portalocker==2.3.0; python_version >= '3' psycopg2-binary==2.8.6 pyasn1-modules==0.2.8 pyasn1==0.4.8 pycparser==2.20; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' pyopenssl==20.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' python-dateutil==2.8.1 -python-dotenv==0.15.0 +python-dotenv==0.16.0 python-gnupg==0.4.7 python-levenshtein==0.12.2 python-magic==0.4.22 diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 959d90a1b..6a956512f 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -48,21 +48,21 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 @@ -146,77 +146,77 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Title src/app/components/document-list/document-list.component.html - 117 + 123 Document type src/app/components/document-list/document-list.component.html - 123 + 129 Created src/app/components/document-list/document-list.component.html - 129 + 135 Added src/app/components/document-list/document-list.component.html - 135 + 141 Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 @@ -912,48 +912,6 @@ 25 - - Search results - - src/app/components/search/search.component.html - 1 - - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - - - Search query: - - src/app/components/search/search.component.html - 9 - - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - Paperless-ng @@ -1039,81 +997,95 @@ 106 - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 + + + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 @@ -1233,7 +1205,28 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 + + + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 @@ -1626,6 +1619,13 @@ 14 + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Yes diff --git a/src-ui/src/app/app-routing.module.ts b/src-ui/src/app/app-routing.module.ts index 27f0629b4..db409d1c0 100644 --- a/src-ui/src/app/app-routing.module.ts +++ b/src-ui/src/app/app-routing.module.ts @@ -10,7 +10,7 @@ import { LogsComponent } from './components/manage/logs/logs.component'; import { SettingsComponent } from './components/manage/settings/settings.component'; import { TagListComponent } from './components/manage/tag-list/tag-list.component'; import { NotFoundComponent } from './components/not-found/not-found.component'; -import { SearchComponent } from './components/search/search.component'; +import {DocumentAsnComponent} from "./components/document-asn/document-asn.component"; const routes: Routes = [ {path: '', redirectTo: 'dashboard', pathMatch: 'full'}, @@ -18,15 +18,15 @@ const routes: Routes = [ {path: 'dashboard', component: DashboardComponent }, {path: 'documents', component: DocumentListComponent }, {path: 'view/:id', component: DocumentListComponent }, - {path: 'search', component: SearchComponent }, {path: 'documents/:id', component: DocumentDetailComponent }, - + {path: 'asn/:id', component: DocumentAsnComponent }, + {path: 'tags', component: TagListComponent }, {path: 'documenttypes', component: DocumentTypeListComponent }, {path: 'correspondents', component: CorrespondentListComponent }, {path: 'logs', component: LogsComponent }, {path: 'settings', component: SettingsComponent }, - ]}, + ]}, {path: '404', component: NotFoundComponent}, {path: '**', redirectTo: '/404', pathMatch: 'full'} diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index ca87d1a07..e6209a9e3 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -21,8 +21,6 @@ import { CorrespondentEditDialogComponent } from './components/manage/correspond import { TagEditDialogComponent } from './components/manage/tag-list/tag-edit-dialog/tag-edit-dialog.component'; import { DocumentTypeEditDialogComponent } from './components/manage/document-type-list/document-type-edit-dialog/document-type-edit-dialog.component'; import { TagComponent } from './components/common/tag/tag.component'; -import { SearchComponent } from './components/search/search.component'; -import { ResultHighlightComponent } from './components/search/result-highlight/result-highlight.component'; import { PageHeaderComponent } from './components/common/page-header/page-header.component'; import { AppFrameComponent } from './components/app-frame/app-frame.component'; import { ToastsComponent } from './components/common/toasts/toasts.component'; @@ -75,6 +73,7 @@ import localeEnGb from '@angular/common/locales/en-GB'; import localeRo from '@angular/common/locales/ro'; import localeRu from '@angular/common/locales/ru'; import localeEs from '@angular/common/locales/es'; +import { DocumentAsnComponent } from './components/document-asn/document-asn.component'; registerLocaleData(localeFr) @@ -105,8 +104,6 @@ registerLocaleData(localeEs) TagEditDialogComponent, DocumentTypeEditDialogComponent, TagComponent, - SearchComponent, - ResultHighlightComponent, PageHeaderComponent, AppFrameComponent, ToastsComponent, @@ -138,7 +135,8 @@ registerLocaleData(localeEs) SafePipe, CustomDatePipe, DateComponent, - ColorComponent + ColorComponent, + DocumentAsnComponent ], imports: [ BrowserModule, diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 96ca1382c..25d4a9dc7 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -5,7 +5,7 @@ - + Paperless-ng @@ -175,7 +175,7 @@  GitHub - + Suggest an idea diff --git a/src-ui/src/app/components/app-frame/app-frame.component.ts b/src-ui/src/app/components/app-frame/app-frame.component.ts index e360e7567..f8e76f0ae 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.ts +++ b/src-ui/src/app/components/app-frame/app-frame.component.ts @@ -10,6 +10,8 @@ import { SearchService } from 'src/app/services/rest/search.service'; import { environment } from 'src/environments/environment'; import { DocumentDetailComponent } from '../document-detail/document-detail.component'; import { Meta } from '@angular/platform-browser'; +import { DocumentListViewService } from 'src/app/services/document-list-view.service'; +import { FILTER_FULLTEXT_QUERY } from 'src/app/data/filter-rule-type'; @Component({ selector: 'app-app-frame', @@ -24,6 +26,7 @@ export class AppFrameComponent implements OnInit { private openDocumentsService: OpenDocumentsService, private searchService: SearchService, public savedViewService: SavedViewService, + private list: DocumentListViewService, private meta: Meta ) { @@ -74,7 +77,7 @@ export class AppFrameComponent implements OnInit { search() { this.closeMenu() - this.router.navigate(['search'], {queryParams: {query: this.searchField.value}}) + this.list.quickFilter([{rule_type: FILTER_FULLTEXT_QUERY, value: this.searchField.value}]) } closeDocument(d: PaperlessDocument) { diff --git a/src-ui/src/app/components/common/input/select/select.component.html b/src-ui/src/app/components/common/input/select/select.component.html index 540429e89..0ae3009ea 100644 --- a/src-ui/src/app/components/common/input/select/select.component.html +++ b/src-ui/src/app/components/common/input/select/select.component.html @@ -1,33 +1,36 @@
- diff --git a/src-ui/src/app/components/common/input/select/select.component.ts b/src-ui/src/app/components/common/input/select/select.component.ts index e02aaab72..921e3606c 100644 --- a/src-ui/src/app/components/common/input/select/select.component.ts +++ b/src-ui/src/app/components/common/input/select/select.component.ts @@ -16,6 +16,7 @@ export class SelectComponent extends AbstractInputComponent { constructor() { super() + this.addItemRef = this.addItem.bind(this) } @Input() @@ -34,9 +35,13 @@ export class SelectComponent extends AbstractInputComponent { suggestions: number[] @Output() - createNew = new EventEmitter() + createNew = new EventEmitter() - showPlusButton(): boolean { + public addItemRef: (name) => void + + private _lastSearchTerm: string + + get allowCreateNew(): boolean { return this.createNew.observers.length > 0 } @@ -48,4 +53,29 @@ export class SelectComponent extends AbstractInputComponent { } } + addItem(name: string) { + if (name) this.createNew.next(name) + else this.createNew.next(this._lastSearchTerm) + this.clearLastSearchTerm() + } + + clickNew() { + this.createNew.next(this._lastSearchTerm) + this.clearLastSearchTerm() + } + + clearLastSearchTerm() { + this._lastSearchTerm = null + } + + onSearch($event) { + this._lastSearchTerm = $event.term + } + + onBlur() { + setTimeout(() => { + this.clearLastSearchTerm() + }, 3000); + } + } diff --git a/src-ui/src/app/components/common/input/tags/tags.component.html b/src-ui/src/app/components/common/input/tags/tags.component.html index 677b9f4d1..72c2cf1a5 100644 --- a/src-ui/src/app/components/common/input/tags/tags.component.html +++ b/src-ui/src/app/components/common/input/tags/tags.component.html @@ -7,8 +7,13 @@ [closeOnSelect]="false" [clearSearchOnAdd]="true" [hideSelected]="true" + [addTag]="createTagRef" + addTagText="Add tag" (change)="onChange(value)" - (blur)="onTouched()"> + (search)="onSearch($event)" + (focus)="clearLastSearchTerm()" + (clear)="clearLastSearchTerm()" + (blur)="onBlur()"> @@ -39,8 +44,8 @@ {{tag.name}}  - - + +
diff --git a/src-ui/src/app/components/common/input/tags/tags.component.ts b/src-ui/src/app/components/common/input/tags/tags.component.ts index f77d0570d..8db444ba3 100644 --- a/src-ui/src/app/components/common/input/tags/tags.component.ts +++ b/src-ui/src/app/components/common/input/tags/tags.component.ts @@ -17,8 +17,9 @@ import { TagService } from 'src/app/services/rest/tag.service'; }) export class TagsComponent implements OnInit, ControlValueAccessor { - constructor(private tagService: TagService, private modalService: NgbModal) { } - + constructor(private tagService: TagService, private modalService: NgbModal) { + this.createTagRef = this.createTag.bind(this) + } onChange = (newValue: number[]) => {}; @@ -56,6 +57,10 @@ export class TagsComponent implements OnInit, ControlValueAccessor { tags: PaperlessTag[] + public createTagRef: (name) => void + + private _lastSearchTerm: string + getTag(id) { if (this.tags) { return this.tags.find(tag => tag.id == id) @@ -74,9 +79,11 @@ export class TagsComponent implements OnInit, ControlValueAccessor { } } - createTag() { + createTag(name: string = null) { var modal = this.modalService.open(TagEditDialogComponent, {backdrop: 'static'}) modal.componentInstance.dialogMode = 'create' + if (name) modal.componentInstance.object = { name: name } + else if (this._lastSearchTerm) modal.componentInstance.object = { name: this._lastSearchTerm } modal.componentInstance.success.subscribe(newTag => { this.tagService.listAll().subscribe(tags => { this.tags = tags.results @@ -99,4 +106,18 @@ export class TagsComponent implements OnInit, ControlValueAccessor { this.onChange(this.value) } + clearLastSearchTerm() { + this._lastSearchTerm = null + } + + onSearch($event) { + this._lastSearchTerm = $event.term + } + + onBlur() { + setTimeout(() => { + this.clearLastSearchTerm() + }, 3000); + } + } diff --git a/src-ui/src/app/components/dashboard/dashboard.component.html b/src-ui/src/app/components/dashboard/dashboard.component.html index ec2bbd85c..6b9ea950b 100644 --- a/src-ui/src/app/components/dashboard/dashboard.component.html +++ b/src-ui/src/app/components/dashboard/dashboard.component.html @@ -1,5 +1,5 @@ -

Searching document with asn {{asn}}

diff --git a/src-ui/src/app/components/document-asn/document-asn.component.scss b/src-ui/src/app/components/document-asn/document-asn.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/search/search.component.spec.ts b/src-ui/src/app/components/document-asn/document-asn.component.spec.ts similarity index 53% rename from src-ui/src/app/components/search/search.component.spec.ts rename to src-ui/src/app/components/document-asn/document-asn.component.spec.ts index 918ce7071..5a9826f8d 100644 --- a/src-ui/src/app/components/search/search.component.spec.ts +++ b/src-ui/src/app/components/document-asn/document-asn.component.spec.ts @@ -1,20 +1,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { SearchComponent } from './search.component'; +import { DocumentAsnComponent } from './document-asn.component'; -describe('SearchComponent', () => { - let component: SearchComponent; - let fixture: ComponentFixture; +describe('DocumentASNComponentComponent', () => { + let component: DocumentAsnComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ SearchComponent ] + declarations: [ DocumentAsnComponent ] }) .compileComponents(); }); beforeEach(() => { - fixture = TestBed.createComponent(SearchComponent); + fixture = TestBed.createComponent(DocumentAsnComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src-ui/src/app/components/document-asn/document-asn.component.ts b/src-ui/src/app/components/document-asn/document-asn.component.ts new file mode 100644 index 000000000..550c331b9 --- /dev/null +++ b/src-ui/src/app/components/document-asn/document-asn.component.ts @@ -0,0 +1,34 @@ +import { Component, OnInit } from '@angular/core'; +import {DocumentService} from "../../services/rest/document.service"; +import {ActivatedRoute, Router} from "@angular/router"; +import {FILTER_ASN} from "../../data/filter-rule-type"; + +@Component({ + selector: 'app-document-asncomponent', + templateUrl: './document-asn.component.html', + styleUrls: ['./document-asn.component.scss'] +}) +export class DocumentAsnComponent implements OnInit { + + asn: string + constructor( + private documentsService: DocumentService, + private route: ActivatedRoute, + private router: Router) { } + + + ngOnInit(): void { + + this.route.paramMap.subscribe(paramMap => { + this.asn = paramMap.get('id'); + this.documentsService.listAllFilteredIds([{rule_type: FILTER_ASN, value: this.asn}]).subscribe(documentId => { + if (documentId.length == 1) { + this.router.navigate(['documents', documentId[0]]) + } else { + this.router.navigate(['404']) + } + }) + }) + + } +} diff --git a/src-ui/src/app/components/document-detail/document-detail.component.html b/src-ui/src/app/components/document-detail/document-detail.component.html index f9b87aee3..1286225fb 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.html +++ b/src-ui/src/app/components/document-detail/document-detail.component.html @@ -60,9 +60,9 @@ + (createNew)="createCorrespondent($event)" [suggestions]="suggestions?.correspondents"> + (createNew)="createDocumentType($event)" [suggestions]="suggestions?.document_types"> diff --git a/src-ui/src/app/components/document-detail/document-detail.component.ts b/src-ui/src/app/components/document-detail/document-detail.component.ts index af98a6f7f..493e61d35 100644 --- a/src-ui/src/app/components/document-detail/document-detail.component.ts +++ b/src-ui/src/app/components/document-detail/document-detail.component.ts @@ -20,6 +20,7 @@ import { ToastService } from 'src/app/services/toast.service'; import { TextComponent } from '../common/input/text/text.component'; import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; import { PaperlessDocumentSuggestions } from 'src/app/data/paperless-document-suggestions'; +import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'; @Component({ selector: 'app-document-detail', @@ -127,9 +128,10 @@ export class DocumentDetailComponent implements OnInit { this.documentForm.patchValue(doc) } - createDocumentType() { + createDocumentType(newName: string) { var modal = this.modalService.open(DocumentTypeEditDialogComponent, {backdrop: 'static'}) modal.componentInstance.dialogMode = 'create' + if (newName) modal.componentInstance.object = { name: newName } modal.componentInstance.success.subscribe(newDocumentType => { this.documentTypeService.listAll().subscribe(documentTypes => { this.documentTypes = documentTypes.results @@ -138,9 +140,10 @@ export class DocumentDetailComponent implements OnInit { }) } - createCorrespondent() { + createCorrespondent(newName: string) { var modal = this.modalService.open(CorrespondentEditDialogComponent, {backdrop: 'static'}) modal.componentInstance.dialogMode = 'create' + if (newName) modal.componentInstance.object = { name: newName } modal.componentInstance.success.subscribe(newCorrespondent => { this.correspondentService.listAll().subscribe(correspondents => { this.correspondents = correspondents.results @@ -219,7 +222,7 @@ export class DocumentDetailComponent implements OnInit { } moreLike() { - this.router.navigate(["search"], {queryParams: {more_like:this.document.id}}) + this.documentListViewService.quickFilter([{rule_type: FILTER_FULLTEXT_MORELIKE, value: this.documentId.toString()}]) } hasNext() { diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html index 119960386..3a552eb4e 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.html @@ -25,14 +25,14 @@

- - {{getDetailsAsString()}} + + {{contentTrimmed}}

diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.scss b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.scss index 9507ab42a..1074283e9 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.scss +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.scss @@ -60,3 +60,8 @@ padding-top: 0.35rem !important; } } + +span ::ng-deep .match { + color: black; + background-color: rgb(255, 211, 66); +} \ No newline at end of file diff --git a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts index da147c07b..d8f29ef5a 100644 --- a/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts +++ b/src-ui/src/app/components/document-list/document-card-large/document-card-large.component.ts @@ -4,6 +4,8 @@ import { PaperlessDocument } from 'src/app/data/paperless-document'; import { DocumentService } from 'src/app/services/rest/document.service'; import { SettingsService, SETTINGS_KEYS } from 'src/app/services/settings.service'; import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { DocumentListViewService } from 'src/app/services/document-list-view.service'; +import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'; @Component({ selector: 'app-document-card-large', @@ -24,15 +26,9 @@ export class DocumentCardLargeComponent implements OnInit { return this.toggleSelected.observers.length > 0 } - @Input() - moreLikeThis: boolean = false - @Input() document: PaperlessDocument - @Input() - details: any - @Output() clickTag = new EventEmitter() @@ -42,8 +38,8 @@ export class DocumentCardLargeComponent implements OnInit { @Output() clickDocumentType = new EventEmitter() - @Input() - searchScore: number + @Output() + clickMoreLike= new EventEmitter() @ViewChild('popover') popover: NgbPopover @@ -51,12 +47,14 @@ export class DocumentCardLargeComponent implements OnInit { popoverHidden = true get searchScoreClass() { - if (this.searchScore > 0.7) { - return "success" - } else if (this.searchScore > 0.3) { - return "warning" - } else { - return "danger" + if (this.document.__search_hit__) { + if (this.document.__search_hit__.score > 0.7) { + return "success" + } else if (this.document.__search_hit__.score > 0.3) { + return "warning" + } else { + return "danger" + } } } @@ -67,19 +65,6 @@ export class DocumentCardLargeComponent implements OnInit { return this.settingsService.get(SETTINGS_KEYS.DARK_MODE_THUMB_INVERTED) } - getDetailsAsString() { - if (typeof this.details === 'string') { - return this.details.substring(0, 500) - } - } - - getDetailsAsHighlight() { - //TODO: this is not an exact typecheck, can we do better - if (this.details instanceof Array) { - return this.details - } - } - getThumbUrl() { return this.documentService.getThumbUrl(this.document.id) } @@ -116,4 +101,8 @@ export class DocumentCardLargeComponent implements OnInit { mouseLeaveCard() { this.popover.close() } + + get contentTrimmed() { + return this.document.content.substr(0, 500) + } } diff --git a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html index 0c66419e8..abe9f5299 100644 --- a/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html +++ b/src-ui/src/app/components/document-list/document-card-small/document-card-small.component.html @@ -38,7 +38,15 @@ {{(document.document_type$ | async)?.name}}
-
+ +
+ Created: {{ document.created | customDate}} + Added: {{ document.added | customDate}} + Modified: {{ document.modified | customDate}} +
+
+ +
- +
@@ -89,86 +89,95 @@ [rotate]="true" aria-label="Default pagination">
-
- - -
+ + + - - - - - - - - - - - - - - - - - - - - - -
ASNCorrespondentTitleDocument typeCreatedAdded
-
- - -
-
- {{d.archive_serial_number}} - - - {{(d.correspondent$ | async)?.name}} - - - {{d.title | documentTitle}} - - - - {{(d.document_type$ | async)?.name}} - - - {{d.created | customDate}} - - {{d.added | customDate}} -
+ -
- -
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
ASNCorrespondentTitleDocument typeCreatedAdded
+
+ + +
+
+ {{d.archive_serial_number}} + + + {{(d.correspondent$ | async)?.name}} + + + {{d.title | documentTitle}} + + + + {{(d.document_type$ | async)?.name}} + + + {{d.created | customDate}} + + {{d.added | customDate}} +
+ +
+ +
+ + +
diff --git a/src-ui/src/app/components/document-list/document-list.component.ts b/src-ui/src/app/components/document-list/document-list.component.ts index cf7afb845..13a827e97 100644 --- a/src-ui/src/app/components/document-list/document-list.component.ts +++ b/src-ui/src/app/components/document-list/document-list.component.ts @@ -2,6 +2,8 @@ import { Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren } from import { ActivatedRoute, Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Subscription } from 'rxjs'; +import { FilterRule } from 'src/app/data/filter-rule'; +import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'; import { PaperlessDocument } from 'src/app/data/paperless-document'; import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'; import { SortableDirective, SortEvent } from 'src/app/directives/sortable.directive'; @@ -37,7 +39,7 @@ export class DocumentListComponent implements OnInit, OnDestroy { displayMode = 'smallCards' // largeCards, smallCards, details - filterRulesModified: boolean = false + unmodifiedFilterRules: FilterRule[] = [] private consumptionFinishedSubscription: Subscription @@ -81,12 +83,12 @@ export class DocumentListComponent implements OnInit, OnDestroy { } this.list.activateSavedView(view) this.list.reload() - this.rulesChanged() + this.unmodifiedFilterRules = view.filter_rules }) } else { this.list.activateSavedView(null) this.list.reload() - this.rulesChanged() + this.unmodifiedFilterRules = [] } }) } @@ -100,7 +102,6 @@ export class DocumentListComponent implements OnInit, OnDestroy { loadViewConfig(view: PaperlessSavedView) { this.list.loadSavedView(view) this.list.reload() - this.rulesChanged() } saveViewConfig() { @@ -113,6 +114,7 @@ export class DocumentListComponent implements OnInit, OnDestroy { } this.savedViewService.patch(savedView).subscribe(result => { this.toastService.showInfo($localize`View "${this.list.activeSavedViewTitle}" saved successfully.`) + this.unmodifiedFilterRules = this.list.filterRules }) } } @@ -141,46 +143,6 @@ export class DocumentListComponent implements OnInit, OnDestroy { }) } - resetFilters(): void { - this.filterRulesModified = false - if (this.list.activeSavedViewId) { - this.savedViewService.getCached(this.list.activeSavedViewId).subscribe(viewUntouched => { - this.list.filterRules = viewUntouched.filter_rules - this.list.reload() - }) - } else { - this.list.filterRules = [] - this.list.reload() - } - } - - rulesChanged() { - let modified = false - if (this.list.activeSavedViewId == null) { - modified = this.list.filterRules.length > 0 // documents list is modified if it has any filters - } else { - // compare savedView current filters vs original - this.savedViewService.getCached(this.list.activeSavedViewId).subscribe(view => { - let filterRulesInitial = view.filter_rules - - if (this.list.filterRules.length !== filterRulesInitial.length) modified = true - else { - modified = this.list.filterRules.some(rule => { - return (filterRulesInitial.find(fri => fri.rule_type == rule.rule_type && fri.value == rule.value) == undefined) - }) - - if (!modified) { - // only check other direction if we havent already determined is modified - modified = filterRulesInitial.some(rule => { - this.list.filterRules.find(fr => fr.rule_type == rule.rule_type && fr.value == rule.value) == undefined - }) - } - } - }) - } - this.filterRulesModified = modified - } - toggleSelected(document: PaperlessDocument, event: MouseEvent): void { if (!event.shiftKey) this.list.toggleSelected(document) else this.list.selectRangeTo(document) @@ -207,6 +169,10 @@ export class DocumentListComponent implements OnInit, OnDestroy { }) } + clickMoreLike(documentID: number) { + this.list.quickFilter([{rule_type: FILTER_FULLTEXT_MORELIKE, value: documentID.toString()}]) + } + trackByDocumentId(index, item: PaperlessDocument) { return item.id } diff --git a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.html b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.html index 7290354eb..c61f36c3f 100644 --- a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.html +++ b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.html @@ -1,7 +1,6 @@
-
@@ -9,7 +8,7 @@
- +
diff --git a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts index c1b0f509a..b693c55ec 100644 --- a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts +++ b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, OnInit, OnDestroy } from '@angular/core'; +import { Component, EventEmitter, Input, Output, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { PaperlessTag } from 'src/app/data/paperless-tag'; import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; @@ -8,14 +8,17 @@ import { DocumentTypeService } from 'src/app/services/rest/document-type.service import { TagService } from 'src/app/services/rest/tag.service'; import { CorrespondentService } from 'src/app/services/rest/correspondent.service'; import { FilterRule } from 'src/app/data/filter-rule'; -import { FILTER_ADDED_AFTER, FILTER_ADDED_BEFORE, FILTER_ASN, FILTER_CORRESPONDENT, FILTER_CREATED_AFTER, FILTER_CREATED_BEFORE, FILTER_DOCUMENT_TYPE, FILTER_HAS_ANY_TAG, FILTER_HAS_TAG, FILTER_TITLE, FILTER_TITLE_CONTENT } from 'src/app/data/filter-rule-type'; +import { FILTER_ADDED_AFTER, FILTER_ADDED_BEFORE, FILTER_ASN, FILTER_CORRESPONDENT, FILTER_CREATED_AFTER, FILTER_CREATED_BEFORE, FILTER_DOCUMENT_TYPE, FILTER_FULLTEXT_MORELIKE, FILTER_FULLTEXT_QUERY, FILTER_HAS_ANY_TAG, FILTER_HAS_TAG, FILTER_TITLE, FILTER_TITLE_CONTENT } from 'src/app/data/filter-rule-type'; import { FilterableDropdownSelectionModel } from '../../common/filterable-dropdown/filterable-dropdown.component'; import { ToggleableItemState } from '../../common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component'; import { DocumentService } from 'src/app/services/rest/document.service'; +import { PaperlessDocument } from 'src/app/data/paperless-document'; const TEXT_FILTER_TARGET_TITLE = "title" const TEXT_FILTER_TARGET_TITLE_CONTENT = "title-content" const TEXT_FILTER_TARGET_ASN = "asn" +const TEXT_FILTER_TARGET_FULLTEXT_QUERY = "fulltext-query" +const TEXT_FILTER_TARGET_FULLTEXT_MORELIKE = "fulltext-morelike" @Component({ selector: 'app-filter-editor', @@ -69,17 +72,29 @@ export class FilterEditorComponent implements OnInit, OnDestroy { private documentService: DocumentService ) { } + @ViewChild("textFilterInput") + textFilterInput: ElementRef + tags: PaperlessTag[] = [] correspondents: PaperlessCorrespondent[] = [] documentTypes: PaperlessDocumentType[] = [] _textFilter = "" + _moreLikeId: number + _moreLikeDoc: PaperlessDocument - textFilterTargets = [ - {id: TEXT_FILTER_TARGET_TITLE, name: $localize`Title`}, - {id: TEXT_FILTER_TARGET_TITLE_CONTENT, name: $localize`Title & content`}, - {id: TEXT_FILTER_TARGET_ASN, name: $localize`ASN`} - ] + get textFilterTargets() { + let targets = [ + {id: TEXT_FILTER_TARGET_TITLE, name: $localize`Title`}, + {id: TEXT_FILTER_TARGET_TITLE_CONTENT, name: $localize`Title & content`}, + {id: TEXT_FILTER_TARGET_ASN, name: $localize`ASN`}, + {id: TEXT_FILTER_TARGET_FULLTEXT_QUERY, name: $localize`Advanced search`} + ] + if (this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_MORELIKE) { + targets.push({id: TEXT_FILTER_TARGET_FULLTEXT_MORELIKE, name: $localize`More like`}) + } + return targets + } textFilterTarget = TEXT_FILTER_TARGET_TITLE_CONTENT @@ -97,12 +112,28 @@ export class FilterEditorComponent implements OnInit, OnDestroy { dateAddedBefore: string dateAddedAfter: string + _unmodifiedFilterRules: FilterRule[] = [] + _filterRules: FilterRule[] = [] + + @Input() + set unmodifiedFilterRules(value: FilterRule[]) { + this._unmodifiedFilterRules = value + this.checkIfRulesHaveChanged() + } + + get unmodifiedFilterRules(): FilterRule[] { + return this._unmodifiedFilterRules + } + @Input() set filterRules (value: FilterRule[]) { + this._filterRules = value + this.documentTypeSelectionModel.clear(false) this.tagSelectionModel.clear(false) this.correspondentSelectionModel.clear(false) this._textFilter = null + this._moreLikeId = null this.dateAddedBefore = null this.dateAddedAfter = null this.dateCreatedBefore = null @@ -122,6 +153,18 @@ export class FilterEditorComponent implements OnInit, OnDestroy { this._textFilter = rule.value this.textFilterTarget = TEXT_FILTER_TARGET_ASN break + case FILTER_FULLTEXT_QUERY: + this._textFilter = rule.value + this.textFilterTarget = TEXT_FILTER_TARGET_FULLTEXT_QUERY + break + case FILTER_FULLTEXT_MORELIKE: + this._moreLikeId = +rule.value + this.textFilterTarget = TEXT_FILTER_TARGET_FULLTEXT_MORELIKE + this.documentService.get(this._moreLikeId).subscribe(result => { + this._moreLikeDoc = result + this._textFilter = result.title + }) + break case FILTER_CREATED_AFTER: this.dateCreatedAfter = rule.value break @@ -148,6 +191,7 @@ export class FilterEditorComponent implements OnInit, OnDestroy { break } }) + this.checkIfRulesHaveChanged() } get filterRules(): FilterRule[] { @@ -161,6 +205,12 @@ export class FilterEditorComponent implements OnInit, OnDestroy { if (this._textFilter && this.textFilterTarget == TEXT_FILTER_TARGET_ASN) { filterRules.push({rule_type: FILTER_ASN, value: this._textFilter}) } + if (this._textFilter && this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_QUERY) { + filterRules.push({rule_type: FILTER_FULLTEXT_QUERY, value: this._textFilter}) + } + if (this._moreLikeId && this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_MORELIKE) { + filterRules.push({rule_type: FILTER_FULLTEXT_MORELIKE, value: this._moreLikeId?.toString()}) + } if (this.tagSelectionModel.isNoneSelected()) { filterRules.push({rule_type: FILTER_HAS_ANY_TAG, value: "false"}) } else { @@ -192,12 +242,27 @@ export class FilterEditorComponent implements OnInit, OnDestroy { @Output() filterRulesChange = new EventEmitter() - @Output() - reset = new EventEmitter() - - @Input() rulesModified: boolean = false + private checkIfRulesHaveChanged() { + let modified = false + if (this._unmodifiedFilterRules.length != this._filterRules.length) { + modified = true + } else { + modified = this._unmodifiedFilterRules.some(rule => { + return (this._filterRules.find(fri => fri.rule_type == rule.rule_type && fri.value == rule.value) == undefined) + }) + + if (!modified) { + // only check other direction if we havent already determined is modified + modified = this._filterRules.some(rule => { + this._unmodifiedFilterRules.find(fr => fr.rule_type == rule.rule_type && fr.value == rule.value) == undefined + }) + } + } + this.rulesModified = modified + } + updateRules() { this.filterRulesChange.next(this.filterRules) } @@ -235,7 +300,9 @@ export class FilterEditorComponent implements OnInit, OnDestroy { } resetSelected() { - this.reset.next() + this.textFilterTarget = TEXT_FILTER_TARGET_TITLE_CONTENT + this.filterRules = this._unmodifiedFilterRules + this.updateRules() } toggleTag(tagId: number) { @@ -263,7 +330,11 @@ export class FilterEditorComponent implements OnInit, OnDestroy { } changeTextFilterTarget(target) { + if (this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_MORELIKE && target != TEXT_FILTER_TARGET_FULLTEXT_MORELIKE) { + this._textFilter = "" + } this.textFilterTarget = target + this.textFilterInput.nativeElement.focus() this.updateRules() } } diff --git a/src-ui/src/app/components/search/result-highlight/result-highlight.component.html b/src-ui/src/app/components/search/result-highlight/result-highlight.component.html deleted file mode 100644 index 5dc5baa94..000000000 --- a/src-ui/src/app/components/search/result-highlight/result-highlight.component.html +++ /dev/null @@ -1,3 +0,0 @@ -... - {{token.text}} ... - \ No newline at end of file diff --git a/src-ui/src/app/components/search/result-highlight/result-highlight.component.scss b/src-ui/src/app/components/search/result-highlight/result-highlight.component.scss deleted file mode 100644 index e04dd13b2..000000000 --- a/src-ui/src/app/components/search/result-highlight/result-highlight.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.match { - color: black; - background-color: rgb(255, 211, 66); -} \ No newline at end of file diff --git a/src-ui/src/app/components/search/result-highlight/result-highlight.component.spec.ts b/src-ui/src/app/components/search/result-highlight/result-highlight.component.spec.ts deleted file mode 100644 index 8e00a9d0b..000000000 --- a/src-ui/src/app/components/search/result-highlight/result-highlight.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { ResultHighlightComponent } from './result-highlight.component'; - -describe('ResultHighlightComponent', () => { - let component: ResultHighlightComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ ResultHighlightComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(ResultHighlightComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src-ui/src/app/components/search/result-highlight/result-highlight.component.ts b/src-ui/src/app/components/search/result-highlight/result-highlight.component.ts deleted file mode 100644 index d9a1a50b1..000000000 --- a/src-ui/src/app/components/search/result-highlight/result-highlight.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { SearchHitHighlight } from 'src/app/data/search-result'; - -@Component({ - selector: 'app-result-highlight', - templateUrl: './result-highlight.component.html', - styleUrls: ['./result-highlight.component.scss'] -}) -export class ResultHighlightComponent implements OnInit { - - constructor() { } - - @Input() - highlights: SearchHitHighlight[][] - - ngOnInit(): void { - } - -} diff --git a/src-ui/src/app/components/search/search.component.html b/src-ui/src/app/components/search/search.component.html deleted file mode 100644 index f794a0feb..000000000 --- a/src-ui/src/app/components/search/search.component.html +++ /dev/null @@ -1,26 +0,0 @@ - - - -
Invalid search query: {{errorMessage}}
- -

Showing documents similar to {{more_like_doc?.original_file_name}}

- -

- Search query: {{query}} - - - Did you mean "{{correctedQuery}}"? - -

- -
-

{resultCount, plural, =0 {No results} =1 {One result} other {{{resultCount}} results}}

- - - - - -
diff --git a/src-ui/src/app/components/search/search.component.scss b/src-ui/src/app/components/search/search.component.scss deleted file mode 100644 index 40ca79a61..000000000 --- a/src-ui/src/app/components/search/search.component.scss +++ /dev/null @@ -1,15 +0,0 @@ -.result-content { - color: darkgray; -} - -.doc-img { - object-fit: cover; - object-position: top; - height: 100%; - position: absolute; - -} - -.result-content-searching { - opacity: 0.3; -} \ No newline at end of file diff --git a/src-ui/src/app/components/search/search.component.ts b/src-ui/src/app/components/search/search.component.ts deleted file mode 100644 index 4570ac3fa..000000000 --- a/src-ui/src/app/components/search/search.component.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { PaperlessDocument } from 'src/app/data/paperless-document'; -import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; -import { SearchHit } from 'src/app/data/search-result'; -import { DocumentService } from 'src/app/services/rest/document.service'; -import { SearchService } from 'src/app/services/rest/search.service'; - -@Component({ - selector: 'app-search', - templateUrl: './search.component.html', - styleUrls: ['./search.component.scss'] -}) -export class SearchComponent implements OnInit { - - results: SearchHit[] = [] - - query: string = "" - - more_like: number - - more_like_doc: PaperlessDocument - - searching = false - - currentPage = 1 - - pageCount = 1 - - resultCount - - correctedQuery: string = null - - errorMessage: string - - get maxScore() { - return this.results?.length > 0 ? this.results[0].score : 100 - } - - constructor(private searchService: SearchService, private route: ActivatedRoute, private router: Router, private documentService: DocumentService) { } - - ngOnInit(): void { - this.route.queryParamMap.subscribe(paramMap => { - window.scrollTo(0, 0) - this.query = paramMap.get('query') - this.more_like = paramMap.has('more_like') ? +paramMap.get('more_like') : null - if (this.more_like) { - this.documentService.get(this.more_like).subscribe(r => { - this.more_like_doc = r - }) - } else { - this.more_like_doc = null - } - this.searching = true - this.currentPage = 1 - this.loadPage() - }) - - } - - searchCorrectedQuery() { - this.router.navigate(["search"], {queryParams: {query: this.correctedQuery, more_like: this.more_like}}) - } - - loadPage(append: boolean = false) { - this.errorMessage = null - this.correctedQuery = null - - this.searchService.search(this.query, this.currentPage, this.more_like).subscribe(result => { - if (append) { - this.results.push(...result.results) - } else { - this.results = result.results - } - this.pageCount = result.page_count - this.searching = false - this.resultCount = result.count - this.correctedQuery = result.corrected_query - }, error => { - this.searching = false - this.resultCount = 1 - this.pageCount = 1 - this.results = [] - this.errorMessage = error.error - }) - } - - onScroll() { - if (this.currentPage < this.pageCount) { - this.currentPage += 1 - this.loadPage(true) - } - } - -} diff --git a/src-ui/src/app/data/filter-rule-type.ts b/src-ui/src/app/data/filter-rule-type.ts index 2c9f8a373..c215be84e 100644 --- a/src-ui/src/app/data/filter-rule-type.ts +++ b/src-ui/src/app/data/filter-rule-type.ts @@ -22,6 +22,9 @@ export const FILTER_ASN_ISNULL = 18 export const FILTER_TITLE_CONTENT = 19 +export const FILTER_FULLTEXT_QUERY = 20 +export const FILTER_FULLTEXT_MORELIKE = 21 + export const FILTER_RULE_TYPES: FilterRuleType[] = [ {id: FILTER_TITLE, filtervar: "title__icontains", datatype: "string", multi: false, default: ""}, @@ -51,7 +54,11 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [ {id: FILTER_MODIFIED_AFTER, filtervar: "modified__date__gt", datatype: "date", multi: false}, {id: FILTER_ASN_ISNULL, filtervar: "archive_serial_number__isnull", datatype: "boolean", multi: false}, - {id: FILTER_TITLE_CONTENT, filtervar: "title_content", datatype: "string", multi: false} + {id: FILTER_TITLE_CONTENT, filtervar: "title_content", datatype: "string", multi: false}, + + {id: FILTER_FULLTEXT_QUERY, filtervar: "query", datatype: "string", multi: false}, + + {id: FILTER_FULLTEXT_MORELIKE, filtervar: "more_like_id", datatype: "number", multi: false}, ] export interface FilterRuleType { diff --git a/src-ui/src/app/data/paperless-document.ts b/src-ui/src/app/data/paperless-document.ts index 9d0aeda88..e7412278b 100644 --- a/src-ui/src/app/data/paperless-document.ts +++ b/src-ui/src/app/data/paperless-document.ts @@ -4,6 +4,15 @@ import { PaperlessTag } from './paperless-tag' import { PaperlessDocumentType } from './paperless-document-type' import { Observable } from 'rxjs' +export interface SearchHit { + + score?: number + rank?: number + + highlights?: string + +} + export interface PaperlessDocument extends ObjectWithId { correspondent$?: Observable @@ -40,4 +49,6 @@ export interface PaperlessDocument extends ObjectWithId { archive_serial_number?: number + __search_hit__?: SearchHit + } diff --git a/src-ui/src/app/data/search-result.ts b/src-ui/src/app/data/search-result.ts deleted file mode 100644 index a769a8351..000000000 --- a/src-ui/src/app/data/search-result.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { PaperlessDocument } from './paperless-document' - -export class SearchHitHighlight { - text?: string - term?: number -} - -export interface SearchHit { - id?: number - title?: string - score?: number - rank?: number - - highlights?: SearchHitHighlight[][] - document?: PaperlessDocument -} - -export interface SearchResult { - - count?: number - page?: number - page_count?: number - - corrected_query?: string - - results?: SearchHit[] - - -} diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts index 334706a3c..aa82190d7 100644 --- a/src-ui/src/app/services/document-list-view.service.ts +++ b/src-ui/src/app/services/document-list-view.service.ts @@ -1,7 +1,8 @@ import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs'; import { cloneFilterRules, FilterRule } from '../data/filter-rule'; +import { FILTER_FULLTEXT_MORELIKE, FILTER_FULLTEXT_QUERY } from '../data/filter-rule-type'; import { PaperlessDocument } from '../data/paperless-document'; import { PaperlessSavedView } from '../data/paperless-saved-view'; import { DOCUMENT_LIST_SERVICE } from '../data/storage-keys'; @@ -38,6 +39,7 @@ interface ListViewState { export class DocumentListViewService { isReloading: boolean = false + error: string = null rangeSelectionAnchorIndex: number lastRangeSelectionToIndex: number @@ -101,6 +103,7 @@ export class DocumentListViewService { reload(onFinish?) { this.isReloading = true + this.error = null let activeListViewState = this.activeListViewState this.documentService.listFiltered( @@ -124,12 +127,17 @@ export class DocumentListViewService { // this happens when applying a filter: the current page might not be available anymore due to the reduced result set. activeListViewState.currentPage = 1 this.reload() + } else { + this.error = error.error } }) } set filterRules(filterRules: FilterRule[]) { this.activeListViewState.filterRules = filterRules + if (filterRules.find(r => (r.rule_type == FILTER_FULLTEXT_QUERY || r.rule_type == FILTER_FULLTEXT_MORELIKE))) { + this.activeListViewState.currentPage = 1 + } this.reload() this.reduceSelectionToFilter() this.saveDocumentListView() @@ -197,7 +205,7 @@ export class DocumentListViewService { sortField: this.activeListViewState.sortField, sortReverse: this.activeListViewState.sortReverse } - sessionStorage.setItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG, JSON.stringify(savedState)) + localStorage.setItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG, JSON.stringify(savedState)) } } @@ -207,7 +215,11 @@ export class DocumentListViewService { this.activeListViewState.currentPage = 1 this.reduceSelectionToFilter() this.saveDocumentListView() - this.router.navigate(["documents"]) + if (this.router.url == "/documents") { + this.reload() + } else { + this.router.navigate(["documents"]) + } } getLastPage(): number { @@ -317,8 +329,8 @@ export class DocumentListViewService { return this.documents.map(d => d.id).indexOf(documentID) } - constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router) { - let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) + constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router, private route: ActivatedRoute) { + let documentListViewConfigJson = localStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) if (documentListViewConfigJson) { try { let savedState: ListViewState = JSON.parse(documentListViewConfigJson) @@ -332,7 +344,7 @@ export class DocumentListViewService { let newState = Object.assign(this.defaultListViewState(), savedState) this.listViewStates.set(null, newState) } catch (e) { - sessionStorage.removeItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) + localStorage.removeItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) } } } diff --git a/src-ui/src/app/services/rest/search.service.ts b/src-ui/src/app/services/rest/search.service.ts index e750100fa..f10c53485 100644 --- a/src-ui/src/app/services/rest/search.service.ts +++ b/src-ui/src/app/services/rest/search.service.ts @@ -2,8 +2,6 @@ import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { PaperlessDocument } from 'src/app/data/paperless-document'; -import { SearchResult } from 'src/app/data/search-result'; import { environment } from 'src/environments/environment'; import { DocumentService } from './document.service'; @@ -13,30 +11,7 @@ import { DocumentService } from './document.service'; }) export class SearchService { - constructor(private http: HttpClient, private documentService: DocumentService) { } - - search(query: string, page?: number, more_like?: number): Observable { - let httpParams = new HttpParams() - if (query) { - httpParams = httpParams.set('query', query) - } - if (page) { - httpParams = httpParams.set('page', page.toString()) - } - if (more_like) { - httpParams = httpParams.set('more_like', more_like.toString()) - } - return this.http.get(`${environment.apiBaseUrl}search/`, {params: httpParams}).pipe( - map(result => { - result.results.forEach(hit => { - if (hit.document) { - this.documentService.addObservablesToDocument(hit.document) - } - }) - return result - }) - ) - } + constructor(private http: HttpClient) { } autocomplete(term: string): Observable { return this.http.get(`${environment.apiBaseUrl}search/autocomplete/`, {params: new HttpParams().set('term', term)}) diff --git a/src-ui/src/environments/environment.prod.ts b/src-ui/src/environments/environment.prod.ts index acc5843f8..63789a9d4 100644 --- a/src-ui/src/environments/environment.prod.ts +++ b/src-ui/src/environments/environment.prod.ts @@ -3,7 +3,7 @@ export const environment = { apiBaseUrl: "/api/", apiVersion: "2", appTitle: "Paperless-ng", - version: "1.3.2", + version: "1.4.0", webSocketHost: window.location.host, webSocketProtocol: (window.location.protocol == "https:" ? "wss:" : "ws:") }; diff --git a/src-ui/src/locale/messages.cs_CZ.xlf b/src-ui/src/locale/messages.cs_CZ.xlf index c24654569..335046a73 100644 --- a/src-ui/src/locale/messages.cs_CZ.xlf +++ b/src-ui/src/locale/messages.cs_CZ.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Dokumenty @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" saved successfully. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 View "" created successfully. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Title @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Document type @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Created @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Added @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirm delete @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Do you really want to delete document ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 The files for this document will be deleted permanently. This operation cannot be undone. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Delete document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Error deleting document: @@ -1042,54 +1042,6 @@ Edit document type - - Search results - - src/app/components/search/search.component.html - 1 - - Search results - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Invalid search query: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Showing documents similar to - - - Search query: - - src/app/components/search/search.component.html - 9 - - Search query: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Did you mean ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - Paperless-ng @@ -1187,35 +1139,11 @@ Close all - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Title - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Title & content - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Without correspondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Type: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Without document type @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Tag: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Without any tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Title: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Title + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Title & content + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Score: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Invalid date. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.de_DE.xlf b/src-ui/src/locale/messages.de_DE.xlf index 1d7a3e918..9047251ef 100644 --- a/src-ui/src/locale/messages.de_DE.xlf +++ b/src-ui/src/locale/messages.de_DE.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Dokumente @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Ansicht "" erfolgreich gespeichert. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Ansicht "" erfolgreich erstellt. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Korrespondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Titel @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Dokumenttyp @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Ausgestellt @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Hinzugefügt @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Löschen bestätigen @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Möchten Sie das Dokument "" wirklich löschen? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Die Dateien dieses Dokuments werden permanent gelöscht. Diese Aktion kann nicht rückgängig gemacht werden. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Dokument löschen @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Fehler beim Löschen des Dokuments: @@ -1042,54 +1042,6 @@ Dokumenttyp bearbeiten - - Search results - - src/app/components/search/search.component.html - 1 - - Suchergebnisse - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Ungültige Suchanfrage: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Zeige ähnliche Dokumente zu - - - Search query: - - src/app/components/search/search.component.html - 9 - - Suchanfrage: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Meinten Sie ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Keine Ergebnisse} =1 {Ein Ergebnis} other { Ergebnisse}} - Paperless-ng @@ -1187,35 +1139,11 @@ Alle schließen - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Titel - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titel & Inhalt - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Korrespondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Ohne Korrespondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Typ: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Ohne Dokumenttyp @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Tag: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Ohne Tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Titel: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Titel + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titel & Inhalt + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Erweiterte Suche + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + Ähnlich zu + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Relevanz: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Ausgestellt: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Hinzugefügt: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Geändert: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Ungültiges Datum. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Dokument mit ASN wird gesucht + Yes diff --git a/src-ui/src/locale/messages.en_GB.xlf b/src-ui/src/locale/messages.en_GB.xlf index 060411de2..a8d967b9e 100644 --- a/src-ui/src/locale/messages.en_GB.xlf +++ b/src-ui/src/locale/messages.en_GB.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documents @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" saved successfully. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 View "" created successfully. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Title @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Document type @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Created @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Added @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirm delete @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Do you really want to delete document ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 The files for this document will be deleted permanently. This operation cannot be undone. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Delete document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Error deleting document: @@ -1042,54 +1042,6 @@ Edit document type - - Search results - - src/app/components/search/search.component.html - 1 - - Search results - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Invalid search query: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Showing documents similar to - - - Search query: - - src/app/components/search/search.component.html - 9 - - Search query: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Did you mean ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - Paperless-ng @@ -1187,35 +1139,11 @@ Close all - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Title - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Title & content - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Without correspondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Type: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Without document type @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Tag: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Without any tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Title: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Title + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Title & content + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Score: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Invalid date. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.es_ES.xlf b/src-ui/src/locale/messages.es_ES.xlf index b743b8a83..f0ba5e8a6 100644 --- a/src-ui/src/locale/messages.es_ES.xlf +++ b/src-ui/src/locale/messages.es_ES.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documentos @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Ver "" guardado satisfactoriamente. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Ver "" creado satisfactoriamente. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 NSA @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Tipo de documento @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Título @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Tipo de documento @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Creado @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Aggregado @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirmar borrado @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 ¿Estás seguro de querer borrar el documento ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Los archivos para este documento serán borrados permanentemente. Esta operación no se puede deshacer. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Borrar documento @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Error borrando el documento: @@ -1042,54 +1042,6 @@ Editar tipo de documento - - Search results - - src/app/components/search/search.component.html - 1 - - Resultados de la busqueda - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Cadena de búsqueda no valida: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Mostrando documentos similares a - - - Search query: - - src/app/components/search/search.component.html - 9 - - Cadena de búsqueda: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - ¿Quizás quisiste decir ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Sin resultados} =1 {Un resultado} other { resultados}} - Paperless-ng @@ -1187,35 +1139,11 @@ Cerrar todos - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Título - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titulo y contenido - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - NSF - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Tipo: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Sin tipo de documento @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Tipo: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Sin tipo de documento @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Etiqueta: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Sin ninguna etiqueta @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Título: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Título + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titulo y contenido + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + NSF + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Puntuación: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Fecha no válida. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.fr_FR.xlf b/src-ui/src/locale/messages.fr_FR.xlf index d3103a6ad..6d325e6d4 100644 --- a/src-ui/src/locale/messages.fr_FR.xlf +++ b/src-ui/src/locale/messages.fr_FR.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documents @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Vue "" enregistrée avec succès. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Vue "" créée avec succès. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 NSA @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondant @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Titre @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Type de document @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Date de création @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Date d'ajout @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirmer la suppression @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Voulez-vous vraiment supprimer le document "" ? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Les fichiers liés à ce document seront supprimés définitivement. Cette action est irréversible. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Supprimer le document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Une erreur s'est produite lors de la suppression du document : @@ -1042,54 +1042,6 @@ Éditer le type de document - - Search results - - src/app/components/search/search.component.html - 1 - - Résultats de la recherche - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Requête de recherche invalide : - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Présentation des documents similaires à - - - Search query: - - src/app/components/search/search.component.html - 9 - - Requête de recherche : - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Vouliez-vous dire "" ? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Aucun résultat} =1 {Un résultat} other { résultats}} - Paperless-ng @@ -1187,35 +1139,11 @@ Fermer tout - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Titre - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titre & contenu - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - NSA - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondant : @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Sans correspondant @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Type : @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Sans type de document @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Étiquette : @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Sans étiquette @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Titre : @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 NSA : + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Titre + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titre & contenu + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + NSA + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Score : + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Date incorrecte. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.hu_HU.xlf b/src-ui/src/locale/messages.hu_HU.xlf index 218e4fa98..57a95252b 100644 --- a/src-ui/src/locale/messages.hu_HU.xlf +++ b/src-ui/src/locale/messages.hu_HU.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Dokumentumok @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" saved successfully. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Nézet "" sikeresen létrehozva. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Partner @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Cím @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Dokumentum típus @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Létrehozva @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Hozzáadva @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Törlés megerősítése @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Do you really want to delete document ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 A dokumentumhoz tartozó fájlok véglegesen törlésre kerülnek. Ez a művelet nem visszafordítható. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Dokumentum törlése @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Error deleting document: @@ -1042,54 +1042,6 @@ Dokumentum típus szerkesztése - - Search results - - src/app/components/search/search.component.html - 1 - - Találatok - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Érvénytelen keresési kifejezés: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Showing documents similar to - - - Search query: - - src/app/components/search/search.component.html - 9 - - Keresés: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Úgy értetted, hogy ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - Paperless-ng @@ -1187,35 +1139,11 @@ Összes bezárása - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Cím - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Title & content - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Partner: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Without correspondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Típus: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Without document type @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Cimke: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Without any tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Title: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Cím + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Title & content + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Pont: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Invalid date. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.it_IT.xlf b/src-ui/src/locale/messages.it_IT.xlf index c41ed083d..51ad7370f 100644 --- a/src-ui/src/locale/messages.it_IT.xlf +++ b/src-ui/src/locale/messages.it_IT.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documenti @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 La vista "" è stata salvata. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 La vista "" è stata creata. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Corrispondente @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Titolo @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Tipo di documento @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Creato @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Aggiunto @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Conferma eliminazione @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Vuoi eliminare il documento ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 I file di questo documento saranno eliminati permanentemente. Questa operazione è irreversibile. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Elimina documento @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Errore nell'eliminazione del documento: @@ -1042,54 +1042,6 @@ Modifica tipo di documento - - Search results - - src/app/components/search/search.component.html - 1 - - Risultati della ricerca - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Query di ricerca non valida: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Documenti simili a - - - Search query: - - src/app/components/search/search.component.html - 9 - - Query di ricerca: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Forse intendevi ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Nessun risultato} =1 {Un risultato} other { risultati}} - Paperless-ng @@ -1187,35 +1139,11 @@ Chiudi tutti - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Titolo - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titolo & contenuto - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Corrispondente: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Senza corrispondente @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Tipo: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Senza tipo di documento @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Tag: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Senza alcun tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Titolo: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Titolo + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titolo & contenuto + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Ricerca avanzata + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + Più come + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Punteggio: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Creato il: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Aggiunto il: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modificato il: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Data non valida. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Cercando documento con asn + Yes diff --git a/src-ui/src/locale/messages.nl_NL.xlf b/src-ui/src/locale/messages.nl_NL.xlf index c187fc531..cf67a9c80 100644 --- a/src-ui/src/locale/messages.nl_NL.xlf +++ b/src-ui/src/locale/messages.nl_NL.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documenten @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" met succes opgeslagen. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 View "" met succes gemaakt. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Titel @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Documenttype @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Aangemaakt @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Toegevoegd @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Bevestig het verwijderen @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Wilt u het document echt verwijderen ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 De bestanden voor dit document worden definitief verwijderd. Deze bewerking kan niet ongedaan worden gemaakt. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Verwijder document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Fout bij het verwijderen van het document: @@ -1042,54 +1042,6 @@ Documenttype bewerken - - Search results - - src/app/components/search/search.component.html - 1 - - Zoekresultaten - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Ongeldige zoekopdracht: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Toon documenten die lijken op - - - Search query: - - src/app/components/search/search.component.html - 9 - - Zoekopdracht: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Bedoelde u ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Geen resultaten} =1 {Eén resultaat} other { resultaten}} - Paperless-ng @@ -1187,35 +1139,11 @@ Alles sluiten - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Titel - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titel en inhoud - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Zonder correspondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Type: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Zonder documenttype @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Etiket: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Zonder enig etiket @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Titel: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Titel + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titel en inhoud + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Score: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Ongeldige datum. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.pt_BR.xlf b/src-ui/src/locale/messages.pt_BR.xlf index c95ae9670..946173aad 100644 --- a/src-ui/src/locale/messages.pt_BR.xlf +++ b/src-ui/src/locale/messages.pt_BR.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documentos @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Visualização "" salva com sucesso. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Visualização "" criada com sucesso. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 NSA @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondente @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Título @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Tipo de Documento @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Criado @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Adicionado @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirmar exclusão @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Você realmente deseja excluir o documento ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Os arquivos desse documento serão excluídos permanentemente. Essa operação não pode ser revertida. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Excluir documento @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Erro ao excluir documento: @@ -1042,54 +1042,6 @@ Editar tipo de documento - - Search results - - src/app/components/search/search.component.html - 1 - - Resultados da busca - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Termo de pesquisa inválido: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Exibindo documentos similares a - - - Search query: - - src/app/components/search/search.component.html - 9 - - Termo de pesquisa: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Você quis dizer ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Sem resultados} =1 {Um resultado} other { resultados}} - Paperless-ng @@ -1187,35 +1139,11 @@ Fechar todos - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Título - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Título & conteúdo - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - NSA - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondente: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Sem correspondente @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Tipo: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Sem tipo de documento @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Etiqueta: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Sem etiquetas @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Título: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Título + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Título & conteúdo + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + NSA + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Nota: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Data inválida. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src-ui/src/locale/messages.pt_PT.xlf b/src-ui/src/locale/messages.pt_PT.xlf index 1059654f9..2c4d6d543 100644 --- a/src-ui/src/locale/messages.pt_PT.xlf +++ b/src-ui/src/locale/messages.pt_PT.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documentos @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Visualização "" salva com sucesso. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Visualização "" criada com sucesso. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 NSA @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondente @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Título @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Tipo de Documento @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Criado @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Adicionado @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirmar exclusão @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Você realmente deseja excluir o documento ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Os arquivos desse documento serão excluídos permanentemente. Essa operação não pode ser revertida. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Excluir documento @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Erro ao excluir documento: @@ -1042,54 +1042,6 @@ Editar tipo de documento - - Search results - - src/app/components/search/search.component.html - 1 - - Resultados da pesquisa - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Termo de pesquisa inválido: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Mostrar documentos similares a - - - Search query: - - src/app/components/search/search.component.html - 9 - - Termo de pesquisa: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Será que quer dizer ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, one {} =0 {Sem resultados} =1 {Um resultado} other { resultados}} - Paperless-ng @@ -1187,35 +1139,11 @@ Fechar todos - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Título - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Título & conteúdo - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - NSA - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondente: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Sem correspondente @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Tipo: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Sem tipo de documento @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Etiqueta: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Sem etiquetas @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Título: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 NSA: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Título + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Título & conteúdo + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + NSA + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Pesquisa avançada + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + Mais semelhante + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Pontuação: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Criado em: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Adicionado a: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modificado a: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Data inválida. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + À procura do documento com nsa + Yes diff --git a/src-ui/src/locale/messages.ro_RO.xlf b/src-ui/src/locale/messages.ro_RO.xlf index c434c30bf..0eb8c72ac 100644 --- a/src-ui/src/locale/messages.ro_RO.xlf +++ b/src-ui/src/locale/messages.ro_RO.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Documente @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Vizualizarea "" a fost salvată. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Vizualizarea "" a fost creată. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 Aviz prealabil de expediție @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Corespondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Titlu @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Tipul documentului @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Creat @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Adăugat @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirmă ștergerea @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Sunteţi sigur că doriţi să ştergeţi documentul ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Fișierele pentru acest document vor fi șterse permanent. Operațiunea este ireversibila. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Șterge document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Eroare la ștergerea documentului: @@ -1042,54 +1042,6 @@ Modifică un tip de document - - Search results - - src/app/components/search/search.component.html - 1 - - Rezultatele căutarii - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Interogare invalidă: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Documente similare cu - - - Search query: - - src/app/components/search/search.component.html - 9 - - Interogare: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Ați vrut să scrieți ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Niciun rezultat} =1 {Un rezultat} other { rezultate}} - Paperless-ng @@ -1187,35 +1139,11 @@ Închide tot - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Titlu - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Titlu si conținut - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - Aviz prealabil de expediție - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Corespondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Fără corespondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Tip: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Fară tip @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Eticheta: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Fară etichete @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Titlu: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 Aviz prealabil de expediție: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Titlu + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Titlu si conținut + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + Aviz prealabil de expediție + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Scor: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Data invalidă. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes @@ -1967,7 +1967,7 @@ src/app/services/settings.service.ts 100 - Spanish + Spaniolă ISO 8601 diff --git a/src-ui/src/locale/messages.ru_RU.xlf b/src-ui/src/locale/messages.ru_RU.xlf index c2736233c..c0b9f8eff 100644 --- a/src-ui/src/locale/messages.ru_RU.xlf +++ b/src-ui/src/locale/messages.ru_RU.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 Документы @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 Представление "" успешно сохранено. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 Представление "" успешно создано. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 Архивный номер @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Корреспондент @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Название @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Тип документа @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Создано @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Добавлено @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Подтвердите удаление @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Вы действительно хотите удалить документ ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 Файлы из этого документа будут удалены незамедлительно. Это операцию нельзя отменить. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Удалить документ @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Ошибка удаления документа: @@ -1042,54 +1042,6 @@ Редактировать тип документа - - Search results - - src/app/components/search/search.component.html - 1 - - Результаты поиска - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Неверный поисковой запрос: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Показываю документы похожие на - - - Search query: - - src/app/components/search/search.component.html - 9 - - Поисковый запрос: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Может вы имели ввиду ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {Нет результатов} =1 {Один результат} other {Результаты: }} - Paperless-ng @@ -1187,35 +1139,11 @@ Закрыть всё - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Заголовок - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Название и содержимое - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - АН - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Корреспондент: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Без корреспондента @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Тип: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Без типа документа @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Тег: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Без тегов @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Название: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 Архивный номер: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Заголовок + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Название и содержимое + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + АН + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Расширенный поиск + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + Больше похожих + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Оценка: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Создано: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Добавлено: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Изменено: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Неверная дата. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Поиск документа с asn + Yes diff --git a/src-ui/src/locale/messages.xh_ZA.xlf b/src-ui/src/locale/messages.xh_ZA.xlf index 2d759ed8a..d9f1f631c 100644 --- a/src-ui/src/locale/messages.xh_ZA.xlf +++ b/src-ui/src/locale/messages.xh_ZA.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 crwdns2850:0crwdne2850:0 @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 crwdns2852:0crwdne2852:0 @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 crwdns2854:0crwdne2854:0 @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 crwdns2878:0crwdne2878:0 @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 crwdns2880:0crwdne2880:0 @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 crwdns2882:0crwdne2882:0 @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 crwdns2884:0crwdne2884:0 @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 crwdns2886:0crwdne2886:0 @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 crwdns2888:0crwdne2888:0 @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 crwdns2890:0crwdne2890:0 @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 crwdns2892:0crwdne2892:0 @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 crwdns2894:0crwdne2894:0 @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 crwdns2896:0crwdne2896:0 @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 crwdns2898:0crwdne2898:0 @@ -1042,54 +1042,6 @@ crwdns3096:0crwdne3096:0 - - Search results - - src/app/components/search/search.component.html - 1 - - crwdns3098:0crwdne3098:0 - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - crwdns3100:0{{errorMessage}}crwdne3100:0 - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - crwdns3406:0{{more_like}}crwdnd3406:0{{more_like_doc?.original_file_name}}crwdnd3406:0{{more_like_doc?.original_file_name}}crwdne3406:0 - - - Search query: - - src/app/components/search/search.component.html - 9 - - crwdns3104:0{{query}}crwdnd3104:0{{query}}crwdne3104:0 - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - crwdns3106:0[routerLink]crwdnd3106:0{{correctedQuery}}crwdnd3106:0{{correctedQuery}}crwdne3106:0 - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - crwdns3108:0VAR_PLURAL={VAR_PLURAL}crwdne3108:0 - Paperless-ng @@ -1187,35 +1139,11 @@ crwdns3132:0crwdne3132:0 - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - crwdns3134:0crwdne3134:0 - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - crwdns3136:0crwdne3136:0 - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - crwdns3354:0crwdne3354:0 - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 crwdns3138:0crwdne3138:0 @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 crwdns3140:0crwdne3140:0 @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 crwdns3142:0crwdne3142:0 @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 crwdns3144:0crwdne3144:0 @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 crwdns3146:0crwdne3146:0 @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 crwdns3148:0crwdne3148:0 @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 crwdns3150:0crwdne3150:0 @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 crwdns3416:0crwdne3416:0 + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + crwdns3134:0crwdne3134:0 + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + crwdns3136:0crwdne3136:0 + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + crwdns3354:0crwdne3354:0 + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + crwdns3434:0crwdne3434:0 + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + crwdns3436:0crwdne3436:0 + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 crwdns3186:0crwdne3186:0 + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + crwdns3426:0{{ document.created | customDate}}crwdne3426:0 + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + crwdns3428:0{{ document.added | customDate}}crwdne3428:0 + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + crwdns3430:0{{ document.modified | customDate}}crwdne3430:0 + Error executing bulk operation: @@ -1857,6 +1849,14 @@ crwdns3298:0crwdne3298:0 + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + crwdns3432:0{{asn}}crwdne3432:0 + Yes diff --git a/src-ui/src/locale/messages.zh_CN.xlf b/src-ui/src/locale/messages.zh_CN.xlf index a40acabe4..5f21489b4 100644 --- a/src-ui/src/locale/messages.zh_CN.xlf +++ b/src-ui/src/locale/messages.zh_CN.xlf @@ -54,7 +54,7 @@ Documents src/app/components/document-list/document-list.component.ts - 49 + 51 文件 @@ -62,7 +62,7 @@ View "" saved successfully. src/app/components/document-list/document-list.component.ts - 115 + 116 View "" saved successfully. @@ -70,7 +70,7 @@ View "" created successfully. src/app/components/document-list/document-list.component.ts - 136 + 138 View "" created successfully. @@ -166,7 +166,7 @@ ASN src/app/components/document-list/document-list.component.html - 105 + 111 ASN @@ -174,7 +174,7 @@ Correspondent src/app/components/document-list/document-list.component.html - 111 + 117 Correspondent @@ -182,7 +182,7 @@ Title src/app/components/document-list/document-list.component.html - 117 + 123 Title @@ -190,7 +190,7 @@ Document type src/app/components/document-list/document-list.component.html - 123 + 129 Document type @@ -198,7 +198,7 @@ Created src/app/components/document-list/document-list.component.html - 129 + 135 Created @@ -206,7 +206,7 @@ Added src/app/components/document-list/document-list.component.html - 135 + 141 Added @@ -214,7 +214,7 @@ Confirm delete src/app/components/document-detail/document-detail.component.ts - 203 + 204 Confirm delete @@ -222,7 +222,7 @@ Do you really want to delete document ""? src/app/components/document-detail/document-detail.component.ts - 204 + 205 Do you really want to delete document ""? @@ -230,7 +230,7 @@ The files for this document will be deleted permanently. This operation cannot be undone. src/app/components/document-detail/document-detail.component.ts - 205 + 206 The files for this document will be deleted permanently. This operation cannot be undone. @@ -238,7 +238,7 @@ Delete document src/app/components/document-detail/document-detail.component.ts - 207 + 208 Delete document @@ -246,7 +246,7 @@ Error deleting document: src/app/components/document-detail/document-detail.component.ts - 214 + 215 Error deleting document: @@ -1042,54 +1042,6 @@ Edit document type - - Search results - - src/app/components/search/search.component.html - 1 - - Search results - - - Invalid search query: - - src/app/components/search/search.component.html - 4 - - Invalid search query: - - - Showing documents similar to - - src/app/components/search/search.component.html - 6 - - Showing documents similar to - - - Search query: - - src/app/components/search/search.component.html - 9 - - Search query: - - - Did you mean ""? - - src/app/components/search/search.component.html - 11 - - Did you mean ""? - - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - - src/app/components/search/search.component.html - 16 - - {VAR_PLURAL, plural, =0 {No results} =1 {One result} other { results}} - Paperless-ng @@ -1187,35 +1139,11 @@ Close all - - Title - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 77 - - Title - - - Title & content - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 78 - - Title & content - - - ASN - - src/app/components/document-list/filter-editor/filter-editor.component.ts - 79 - - ASN - Correspondent: src/app/components/document-list/filter-editor/filter-editor.component.ts - 33 + 37 Correspondent: @@ -1223,7 +1151,7 @@ Without correspondent src/app/components/document-list/filter-editor/filter-editor.component.ts - 35 + 39 Without correspondent @@ -1231,7 +1159,7 @@ Type: src/app/components/document-list/filter-editor/filter-editor.component.ts - 40 + 44 Type: @@ -1239,7 +1167,7 @@ Without document type src/app/components/document-list/filter-editor/filter-editor.component.ts - 42 + 46 Without document type @@ -1247,7 +1175,7 @@ Tag: src/app/components/document-list/filter-editor/filter-editor.component.ts - 46 + 50 Tag: @@ -1255,7 +1183,7 @@ Without any tag src/app/components/document-list/filter-editor/filter-editor.component.ts - 50 + 54 Without any tag @@ -1263,7 +1191,7 @@ Title: src/app/components/document-list/filter-editor/filter-editor.component.ts - 54 + 58 Title: @@ -1271,10 +1199,50 @@ ASN: src/app/components/document-list/filter-editor/filter-editor.component.ts - 57 + 61 ASN: + + Title + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 85 + + Title + + + Title & content + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 86 + + Title & content + + + ASN + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 87 + + ASN + + + Advanced search + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 88 + + Advanced search + + + More like + + src/app/components/document-list/filter-editor/filter-editor.component.ts + 91 + + More like + Filter tags @@ -1408,10 +1376,34 @@ Score: src/app/components/document-list/document-card-large/document-card-large.component.html - 66 + 86 Score: + + Created: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 43 + + Created: + + + Added: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 44 + + Added: + + + Modified: + + src/app/components/document-list/document-card-small/document-card-small.component.html + 45 + + Modified: + Error executing bulk operation: @@ -1857,6 +1849,14 @@ Invalid date. + + Searching document with asn + + src/app/components/document-asn/document-asn.component.html + 1 + + Searching document with asn + Yes diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 3d7d98198..8c888259f 100755 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -115,6 +115,9 @@ class Consumer(LoggingMixin): f"Configured pre-consume script " f"{settings.PRE_CONSUME_SCRIPT} does not exist.") + self.log("info", + f"Executing pre-consume script {settings.PRE_CONSUME_SCRIPT}") + try: Popen((settings.PRE_CONSUME_SCRIPT, self.path)).wait() except Exception as e: @@ -135,6 +138,11 @@ class Consumer(LoggingMixin): f"{settings.POST_CONSUME_SCRIPT} does not exist." ) + self.log( + "info", + f"Executing post-consume script {settings.POST_CONSUME_SCRIPT}" + ) + try: Popen(( settings.POST_CONSUME_SCRIPT, diff --git a/src/documents/index.py b/src/documents/index.py index 89e56e930..6cd136d80 100644 --- a/src/documents/index.py +++ b/src/documents/index.py @@ -2,75 +2,70 @@ import logging import os from contextlib import contextmanager +import math +from dateutil.parser import isoparse from django.conf import settings from whoosh import highlight, classify, query -from whoosh.fields import Schema, TEXT, NUMERIC, KEYWORD, DATETIME -from whoosh.highlight import Formatter, get_text +from whoosh.fields import Schema, TEXT, NUMERIC, KEYWORD, DATETIME, BOOLEAN +from whoosh.highlight import Formatter, get_text, HtmlFormatter from whoosh.index import create_in, exists_in, open_dir from whoosh.qparser import MultifieldParser from whoosh.qparser.dateparse import DateParserPlugin +from whoosh.searching import ResultsPage, Searcher from whoosh.writing import AsyncWriter +from documents.models import Document logger = logging.getLogger("paperless.index") -class JsonFormatter(Formatter): - def __init__(self): - self.seen = {} - - def format_token(self, text, token, replace=False): - ttext = self._text(get_text(text, token, replace)) - return {'text': ttext, 'highlight': 'true'} - - def format_fragment(self, fragment, replace=False): - output = [] - index = fragment.startchar - text = fragment.text - amend_token = None - for t in fragment.matches: - if t.startchar is None: - continue - if t.startchar < index: - continue - if t.startchar > index: - text_inbetween = text[index:t.startchar] - if amend_token and t.startchar - index < 10: - amend_token['text'] += text_inbetween - else: - output.append({'text': text_inbetween, - 'highlight': False}) - amend_token = None - token = self.format_token(text, t, replace) - if amend_token: - amend_token['text'] += token['text'] - else: - output.append(token) - amend_token = token - index = t.endchar - if index < fragment.endchar: - output.append({'text': text[index:fragment.endchar], - 'highlight': False}) - return output - - def format(self, fragments, replace=False): - output = [] - for fragment in fragments: - output.append(self.format_fragment(fragment, replace=replace)) - return output - - def get_schema(): return Schema( - id=NUMERIC(stored=True, unique=True, numtype=int), - title=TEXT(stored=True), + id=NUMERIC( + stored=True, + unique=True + ), + title=TEXT( + sortable=True + ), content=TEXT(), - correspondent=TEXT(stored=True), - tag=KEYWORD(stored=True, commas=True, scorable=True, lowercase=True), - type=TEXT(stored=True), - created=DATETIME(stored=True, sortable=True), - modified=DATETIME(stored=True, sortable=True), - added=DATETIME(stored=True, sortable=True), + asn=NUMERIC( + sortable=True + ), + + correspondent=TEXT( + sortable=True + ), + correspondent_id=NUMERIC(), + has_correspondent=BOOLEAN(), + + tag=KEYWORD( + commas=True, + scorable=True, + lowercase=True + ), + tag_id=KEYWORD( + commas=True, + scorable=True + ), + has_tag=BOOLEAN(), + + type=TEXT( + sortable=True + ), + type_id=NUMERIC(), + has_type=BOOLEAN(), + + created=DATETIME( + sortable=True + ), + modified=DATETIME( + sortable=True + ), + added=DATETIME( + sortable=True + ), + ) @@ -87,11 +82,8 @@ def open_index(recreate=False): @contextmanager -def open_index_writer(ix=None, optimize=False): - if ix: - writer = AsyncWriter(ix) - else: - writer = AsyncWriter(open_index()) +def open_index_writer(optimize=False): + writer = AsyncWriter(open_index()) try: yield writer @@ -102,17 +94,35 @@ def open_index_writer(ix=None, optimize=False): writer.commit(optimize=optimize) +@contextmanager +def open_index_searcher(): + searcher = open_index().searcher() + + try: + yield searcher + finally: + searcher.close() + + def update_document(writer, doc): tags = ",".join([t.name for t in doc.tags.all()]) + tags_ids = ",".join([str(t.id) for t in doc.tags.all()]) writer.update_document( id=doc.pk, title=doc.title, content=doc.content, correspondent=doc.correspondent.name if doc.correspondent else None, + correspondent_id=doc.correspondent.id if doc.correspondent else None, + has_correspondent=doc.correspondent is not None, tag=tags if tags else None, + tag_id=tags_ids if tags_ids else None, + has_tag=len(tags) > 0, type=doc.document_type.name if doc.document_type else None, + type_id=doc.document_type.id if doc.document_type else None, + has_type=doc.document_type is not None, created=doc.created, added=doc.added, + asn=doc.archive_serial_number, modified=doc.modified, ) @@ -135,50 +145,137 @@ def remove_document_from_index(document): remove_document(writer, document) -@contextmanager -def query_page(ix, page, querystring, more_like_doc_id, more_like_doc_content): - searcher = ix.searcher() - try: - if querystring: - qp = MultifieldParser( - ["content", "title", "correspondent", "tag", "type"], - ix.schema) - qp.add_plugin(DateParserPlugin()) - str_q = qp.parse(querystring) - corrected = searcher.correct_query(str_q, querystring) - else: - str_q = None - corrected = None +class DelayedQuery: - if more_like_doc_id: - docnum = searcher.document_number(id=more_like_doc_id) - kts = searcher.key_terms_from_text( - 'content', more_like_doc_content, numterms=20, - model=classify.Bo1Model, normalize=False) - more_like_q = query.Or( - [query.Term('content', word, boost=weight) - for word, weight in kts]) - result_page = searcher.search_page( - more_like_q, page, filter=str_q, mask={docnum}) - elif str_q: - result_page = searcher.search_page(str_q, page) - else: - raise ValueError( - "Either querystring or more_like_doc_id is required." - ) + @property + def _query(self): + raise NotImplementedError() - result_page.results.fragmenter = highlight.ContextFragmenter( + @property + def _query_filter(self): + criterias = [] + for k, v in self.query_params.items(): + if k == 'correspondent__id': + criterias.append(query.Term('correspondent_id', v)) + elif k == 'tags__id__all': + for tag_id in v.split(","): + criterias.append(query.Term('tag_id', tag_id)) + elif k == 'document_type__id': + criterias.append(query.Term('type_id', v)) + elif k == 'correspondent__isnull': + criterias.append(query.Term("has_correspondent", v == "false")) + elif k == 'is_tagged': + criterias.append(query.Term("has_tag", v == "true")) + elif k == 'document_type__isnull': + criterias.append(query.Term("has_type", v == "false")) + elif k == 'created__date__lt': + criterias.append( + query.DateRange("created", start=None, end=isoparse(v))) + elif k == 'created__date__gt': + criterias.append( + query.DateRange("created", start=isoparse(v), end=None)) + elif k == 'added__date__gt': + criterias.append( + query.DateRange("added", start=isoparse(v), end=None)) + elif k == 'added__date__lt': + criterias.append( + query.DateRange("added", start=None, end=isoparse(v))) + if len(criterias) > 0: + return query.And(criterias) + else: + return None + + @property + def _query_sortedby(self): + # if not 'ordering' in self.query_params: + return None, False + + # o: str = self.query_params['ordering'] + # if o.startswith('-'): + # return o[1:], True + # else: + # return o, False + + def __init__(self, searcher: Searcher, query_params, page_size): + self.searcher = searcher + self.query_params = query_params + self.page_size = page_size + self.saved_results = dict() + self.first_score = None + + def __len__(self): + page = self[0:1] + return len(page) + + def __getitem__(self, item): + if item.start in self.saved_results: + return self.saved_results[item.start] + + q, mask = self._query + sortedby, reverse = self._query_sortedby + + page: ResultsPage = self.searcher.search_page( + q, + mask=mask, + filter=self._query_filter, + pagenum=math.floor(item.start / self.page_size) + 1, + pagelen=self.page_size, + sortedby=sortedby, + reverse=reverse + ) + page.results.fragmenter = highlight.ContextFragmenter( surround=50) - result_page.results.formatter = JsonFormatter() + page.results.formatter = HtmlFormatter(tagname="span", between=" ... ") - if corrected and corrected.query != str_q: + if not self.first_score and len(page.results) > 0: + self.first_score = page.results[0].score + + if self.first_score: + page.results.top_n = list(map( + lambda hit: (hit[0] / self.first_score, hit[1]), + page.results.top_n + )) + + self.saved_results[item.start] = page + + return page + + +class DelayedFullTextQuery(DelayedQuery): + + @property + def _query(self): + q_str = self.query_params['query'] + qp = MultifieldParser( + ["content", "title", "correspondent", "tag", "type"], + self.searcher.ixreader.schema) + qp.add_plugin(DateParserPlugin()) + q = qp.parse(q_str) + + corrected = self.searcher.correct_query(q, q_str) + if corrected.query != q: corrected_query = corrected.string - else: - corrected_query = None - yield result_page, corrected_query - finally: - searcher.close() + return q, None + + +class DelayedMoreLikeThisQuery(DelayedQuery): + + @property + def _query(self): + more_like_doc_id = int(self.query_params['more_like_id']) + content = Document.objects.get(id=more_like_doc_id).content + + docnum = self.searcher.document_number(id=more_like_doc_id) + kts = self.searcher.key_terms_from_text( + 'content', content, numterms=20, + model=classify.Bo1Model, normalize=False) + q = query.Or( + [query.Term('content', word, boost=weight) + for word, weight in kts]) + mask = {docnum} + + return q, mask def autocomplete(ix, term, limit=10): diff --git a/src/documents/migrations/1015_remove_null_characters.py b/src/documents/migrations/1015_remove_null_characters.py new file mode 100644 index 000000000..2f7ee99b6 --- /dev/null +++ b/src/documents/migrations/1015_remove_null_characters.py @@ -0,0 +1,29 @@ +# Generated by Django 3.1.7 on 2021-04-04 18:28 +import logging + +from django.db import migrations + + +logger = logging.getLogger("paperless.migrations") + + +def remove_null_characters(apps, schema_editor): + Document = apps.get_model('documents', 'Document') + + for doc in Document.objects.all(): + content: str = doc.content + if '\0' in content: + logger.info(f"Removing null characters from document {doc}...") + doc.content = content.replace('\0', ' ') + doc.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '1014_auto_20210228_1614'), + ] + + operations = [ + migrations.RunPython(remove_null_characters, migrations.RunPython.noop) + ] diff --git a/src/documents/migrations/1016_auto_20210317_1351.py b/src/documents/migrations/1016_auto_20210317_1351.py new file mode 100644 index 000000000..733c1bb33 --- /dev/null +++ b/src/documents/migrations/1016_auto_20210317_1351.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.7 on 2021-03-17 12:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '1015_remove_null_characters'), + ] + + operations = [ + migrations.AlterField( + model_name='savedview', + name='sort_field', + field=models.CharField(blank=True, max_length=128, null=True, verbose_name='sort field'), + ), + migrations.AlterField( + model_name='savedviewfilterrule', + name='rule_type', + field=models.PositiveIntegerField(choices=[(0, 'title contains'), (1, 'content contains'), (2, 'ASN is'), (3, 'correspondent is'), (4, 'document type is'), (5, 'is in inbox'), (6, 'has tag'), (7, 'has any tag'), (8, 'created before'), (9, 'created after'), (10, 'created year is'), (11, 'created month is'), (12, 'created day is'), (13, 'added before'), (14, 'added after'), (15, 'modified before'), (16, 'modified after'), (17, 'does not have tag'), (18, 'does not have ASN'), (19, 'title or content contains'), (20, 'fulltext query'), (21, 'more like this')], verbose_name='rule type'), + ), + ] diff --git a/src/documents/models.py b/src/documents/models.py index 6ee93e3ad..cdd35a2f7 100755 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -359,7 +359,10 @@ class SavedView(models.Model): sort_field = models.CharField( _("sort field"), - max_length=128) + max_length=128, + null=True, + blank=True + ) sort_reverse = models.BooleanField( _("sort reverse"), default=False) @@ -387,6 +390,8 @@ class SavedViewFilterRule(models.Model): (17, _("does not have tag")), (18, _("does not have ASN")), (19, _("title or content contains")), + (20, _("fulltext query")), + (21, _("more like this")) ] saved_view = models.ForeignKey( diff --git a/src/documents/tests/test_admin.py b/src/documents/tests/test_admin.py index ce00a0698..fc1d7ffaf 100644 --- a/src/documents/tests/test_admin.py +++ b/src/documents/tests/test_admin.py @@ -27,7 +27,7 @@ class TestDocumentAdmin(DirectoriesMixin, TestCase): doc.title = "new title" self.doc_admin.save_model(None, doc, None, None) self.assertEqual(Document.objects.get(id=doc.id).title, "new title") - self.assertEqual(self.get_document_from_index(doc)['title'], "new title") + self.assertEqual(self.get_document_from_index(doc)['id'], doc.id) def test_delete_model(self): doc = Document.objects.create(title="test") diff --git a/src/documents/tests/test_api.py b/src/documents/tests/test_api.py index 853131db2..cfde28e2d 100644 --- a/src/documents/tests/test_api.py +++ b/src/documents/tests/test_api.py @@ -7,6 +7,7 @@ import tempfile import zipfile from unittest import mock +import pytest from django.conf import settings from django.contrib.auth.models import User from django.test import override_settings @@ -294,12 +295,6 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): results = response.data['results'] self.assertEqual(len(results), 0) - def test_search_no_query(self): - response = self.client.get("/api/search/") - results = response.data['results'] - - self.assertEqual(len(results), 0) - def test_search(self): d1=Document.objects.create(title="invoice", content="the thing i bought at a shop and paid with bank account", checksum="A", pk=1) d2=Document.objects.create(title="bank statement 1", content="things i paid for in august", pk=2, checksum="B") @@ -311,32 +306,24 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): index.update_document(writer, d1) index.update_document(writer, d2) index.update_document(writer, d3) - response = self.client.get("/api/search/?query=bank") + response = self.client.get("/api/documents/?query=bank") results = response.data['results'] self.assertEqual(response.data['count'], 3) - self.assertEqual(response.data['page'], 1) - self.assertEqual(response.data['page_count'], 1) self.assertEqual(len(results), 3) - response = self.client.get("/api/search/?query=september") + response = self.client.get("/api/documents/?query=september") results = response.data['results'] self.assertEqual(response.data['count'], 1) - self.assertEqual(response.data['page'], 1) - self.assertEqual(response.data['page_count'], 1) self.assertEqual(len(results), 1) - response = self.client.get("/api/search/?query=statement") + response = self.client.get("/api/documents/?query=statement") results = response.data['results'] self.assertEqual(response.data['count'], 2) - self.assertEqual(response.data['page'], 1) - self.assertEqual(response.data['page_count'], 1) self.assertEqual(len(results), 2) - response = self.client.get("/api/search/?query=sfegdfg") + response = self.client.get("/api/documents/?query=sfegdfg") results = response.data['results'] self.assertEqual(response.data['count'], 0) - self.assertEqual(response.data['page'], 0) - self.assertEqual(response.data['page_count'], 0) self.assertEqual(len(results), 0) def test_search_multi_page(self): @@ -349,53 +336,34 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): seen_ids = [] for i in range(1, 6): - response = self.client.get(f"/api/search/?query=content&page={i}") + response = self.client.get(f"/api/documents/?query=content&page={i}&page_size=10") results = response.data['results'] self.assertEqual(response.data['count'], 55) - self.assertEqual(response.data['page'], i) - self.assertEqual(response.data['page_count'], 6) self.assertEqual(len(results), 10) for result in results: self.assertNotIn(result['id'], seen_ids) seen_ids.append(result['id']) - response = self.client.get(f"/api/search/?query=content&page=6") + response = self.client.get(f"/api/documents/?query=content&page=6&page_size=10") results = response.data['results'] self.assertEqual(response.data['count'], 55) - self.assertEqual(response.data['page'], 6) - self.assertEqual(response.data['page_count'], 6) self.assertEqual(len(results), 5) for result in results: self.assertNotIn(result['id'], seen_ids) seen_ids.append(result['id']) - response = self.client.get(f"/api/search/?query=content&page=7") - results = response.data['results'] - self.assertEqual(response.data['count'], 55) - self.assertEqual(response.data['page'], 6) - self.assertEqual(response.data['page_count'], 6) - self.assertEqual(len(results), 5) - def test_search_invalid_page(self): with AsyncWriter(index.open_index()) as writer: for i in range(15): doc = Document.objects.create(checksum=str(i), pk=i+1, title=f"Document {i+1}", content="content") index.update_document(writer, doc) - first_page = self.client.get(f"/api/search/?query=content&page=1").data - second_page = self.client.get(f"/api/search/?query=content&page=2").data - should_be_first_page_1 = self.client.get(f"/api/search/?query=content&page=0").data - should_be_first_page_2 = self.client.get(f"/api/search/?query=content&page=dgfd").data - should_be_first_page_3 = self.client.get(f"/api/search/?query=content&page=").data - should_be_first_page_4 = self.client.get(f"/api/search/?query=content&page=-7868").data - - self.assertDictEqual(first_page, should_be_first_page_1) - self.assertDictEqual(first_page, should_be_first_page_2) - self.assertDictEqual(first_page, should_be_first_page_3) - self.assertDictEqual(first_page, should_be_first_page_4) - self.assertNotEqual(len(first_page['results']), len(second_page['results'])) + response = self.client.get(f"/api/documents/?query=content&page=0&page_size=10") + self.assertEqual(response.status_code, 404) + response = self.client.get(f"/api/documents/?query=content&page=3&page_size=10") + self.assertEqual(response.status_code, 404) @mock.patch("documents.index.autocomplete") def test_search_autocomplete(self, m): @@ -419,6 +387,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 10) + @pytest.mark.skip(reason="Not implemented yet") def test_search_spelling_correction(self): with AsyncWriter(index.open_index()) as writer: for i in range(55): @@ -444,7 +413,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): index.update_document(writer, d2) index.update_document(writer, d3) - response = self.client.get(f"/api/search/?more_like={d2.id}") + response = self.client.get(f"/api/documents/?more_like_id={d2.id}") self.assertEqual(response.status_code, 200) @@ -454,6 +423,54 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertEqual(results[0]['id'], d3.id) self.assertEqual(results[1]['id'], d1.id) + def test_search_filtering(self): + t = Tag.objects.create(name="tag") + t2 = Tag.objects.create(name="tag2") + c = Correspondent.objects.create(name="correspondent") + dt = DocumentType.objects.create(name="type") + + d1 = Document.objects.create(checksum="1", correspondent=c, content="test") + d2 = Document.objects.create(checksum="2", document_type=dt, content="test") + d3 = Document.objects.create(checksum="3", content="test") + d3.tags.add(t) + d3.tags.add(t2) + d4 = Document.objects.create(checksum="4", created=datetime.datetime(2020, 7, 13), content="test") + d4.tags.add(t2) + d5 = Document.objects.create(checksum="5", added=datetime.datetime(2020, 7, 13), content="test") + d6 = Document.objects.create(checksum="6", content="test2") + + with AsyncWriter(index.open_index()) as writer: + for doc in Document.objects.all(): + index.update_document(writer, doc) + + def search_query(q): + r = self.client.get("/api/documents/?query=test" + q) + self.assertEqual(r.status_code, 200) + return [hit['id'] for hit in r.data['results']] + + self.assertCountEqual(search_query(""), [d1.id, d2.id, d3.id, d4.id, d5.id]) + self.assertCountEqual(search_query("&is_tagged=true"), [d3.id, d4.id]) + self.assertCountEqual(search_query("&is_tagged=false"), [d1.id, d2.id, d5.id]) + self.assertCountEqual(search_query("&correspondent__id=" + str(c.id)), [d1.id]) + self.assertCountEqual(search_query("&document_type__id=" + str(dt.id)), [d2.id]) + self.assertCountEqual(search_query("&correspondent__isnull"), [d2.id, d3.id, d4.id, d5.id]) + self.assertCountEqual(search_query("&document_type__isnull"), [d1.id, d3.id, d4.id, d5.id]) + self.assertCountEqual(search_query("&tags__id__all=" + str(t.id) + "," + str(t2.id)), [d3.id]) + self.assertCountEqual(search_query("&tags__id__all=" + str(t.id)), [d3.id]) + self.assertCountEqual(search_query("&tags__id__all=" + str(t2.id)), [d3.id, d4.id]) + + self.assertIn(d4.id, search_query("&created__date__lt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d"))) + self.assertNotIn(d4.id, search_query("&created__date__gt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d"))) + + self.assertNotIn(d4.id, search_query("&created__date__lt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d"))) + self.assertIn(d4.id, search_query("&created__date__gt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d"))) + + self.assertIn(d5.id, search_query("&added__date__lt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d"))) + self.assertNotIn(d5.id, search_query("&added__date__gt=" + datetime.datetime(2020, 9, 2).strftime("%Y-%m-%d"))) + + self.assertNotIn(d5.id, search_query("&added__date__lt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d"))) + self.assertIn(d5.id, search_query("&added__date__gt=" + datetime.datetime(2020, 1, 2).strftime("%Y-%m-%d"))) + def test_statistics(self): doc1 = Document.objects.create(title="none1", checksum="A") @@ -1375,8 +1392,7 @@ class TestApiAuth(APITestCase): self.assertEqual(self.client.get("/api/logs/").status_code, 401) self.assertEqual(self.client.get("/api/saved_views/").status_code, 401) - self.assertEqual(self.client.get("/api/search/").status_code, 401) - self.assertEqual(self.client.get("/api/search/auto_complete/").status_code, 401) + self.assertEqual(self.client.get("/api/search/autocomplete/").status_code, 401) self.assertEqual(self.client.get("/api/documents/bulk_edit/").status_code, 401) self.assertEqual(self.client.get("/api/documents/bulk_download/").status_code, 401) self.assertEqual(self.client.get("/api/documents/selection_data/").status_code, 401) diff --git a/src/documents/tests/test_index.py b/src/documents/tests/test_index.py index 2baa9621d..14304ab28 100644 --- a/src/documents/tests/test_index.py +++ b/src/documents/tests/test_index.py @@ -1,20 +1,10 @@ from django.test import TestCase from documents import index -from documents.index import JsonFormatter from documents.models import Document from documents.tests.utils import DirectoriesMixin -class JsonFormatterTest(TestCase): - - def setUp(self) -> None: - self.formatter = JsonFormatter() - - def test_empty_fragments(self): - self.assertListEqual(self.formatter.format([]), []) - - class TestAutoComplete(DirectoriesMixin, TestCase): def test_auto_complete(self): diff --git a/src/documents/tests/test_migration_remove_null_characters.py b/src/documents/tests/test_migration_remove_null_characters.py new file mode 100644 index 000000000..ba6f18539 --- /dev/null +++ b/src/documents/tests/test_migration_remove_null_characters.py @@ -0,0 +1,15 @@ +from documents.tests.utils import DirectoriesMixin, TestMigrations + + +class TestMigrateNullCharacters(DirectoriesMixin, TestMigrations): + + migrate_from = '1014_auto_20210228_1614' + migrate_to = '1015_remove_null_characters' + + def setUpBeforeMigration(self, apps): + Document = apps.get_model("documents", "Document") + self.doc = Document.objects.create(content="aaa\0bbb") + + def testMimeTypesMigrated(self): + Document = self.apps.get_model('documents', 'Document') + self.assertNotIn("\0", Document.objects.get(id=self.doc.id).content) diff --git a/src/documents/views.py b/src/documents/views.py index 7b282dfb7..d8fcca2a9 100755 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -17,6 +17,7 @@ from django_filters.rest_framework import DjangoFilterBackend from django_q.tasks import async_task from rest_framework import parsers from rest_framework.decorators import action +from rest_framework.exceptions import NotFound from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.generics import GenericAPIView from rest_framework.mixins import ( @@ -327,6 +328,70 @@ class DocumentViewSet(RetrieveModelMixin, raise Http404() +class SearchResultSerializer(DocumentSerializer): + + def to_representation(self, instance): + doc = Document.objects.get(id=instance['id']) + r = super(SearchResultSerializer, self).to_representation(doc) + r['__search_hit__'] = { + "score": instance.score, + "highlights": instance.highlights("content", + text=doc.content) if doc else None, # NOQA: E501 + "rank": instance.rank + } + + return r + + +class UnifiedSearchViewSet(DocumentViewSet): + + def __init__(self, *args, **kwargs): + super(UnifiedSearchViewSet, self).__init__(*args, **kwargs) + self.searcher = None + + def get_serializer_class(self): + if self._is_search_request(): + return SearchResultSerializer + else: + return DocumentSerializer + + def _is_search_request(self): + return ("query" in self.request.query_params or + "more_like_id" in self.request.query_params) + + def filter_queryset(self, queryset): + if self._is_search_request(): + from documents import index + + if "query" in self.request.query_params: + query_class = index.DelayedFullTextQuery + elif "more_like_id" in self.request.query_params: + query_class = index.DelayedMoreLikeThisQuery + else: + raise ValueError() + + return query_class( + self.searcher, + self.request.query_params, + self.paginator.get_page_size(self.request)) + else: + return super(UnifiedSearchViewSet, self).filter_queryset(queryset) + + def list(self, request, *args, **kwargs): + if self._is_search_request(): + from documents import index + try: + with index.open_index_searcher() as s: + self.searcher = s + return super(UnifiedSearchViewSet, self).list(request) + except NotFound: + raise + except Exception as e: + return HttpResponseBadRequest(str(e)) + else: + return super(UnifiedSearchViewSet, self).list(request) + + class LogViewSet(ViewSet): permission_classes = (IsAuthenticated,) @@ -478,74 +543,6 @@ class SelectionDataView(GenericAPIView): return r -class SearchView(APIView): - - permission_classes = (IsAuthenticated,) - - def add_infos_to_hit(self, r): - try: - doc = Document.objects.get(id=r['id']) - except Document.DoesNotExist: - logger.warning( - f"Search index returned a non-existing document: " - f"id: {r['id']}, title: {r['title']}. " - f"Search index needs reindex." - ) - doc = None - - return {'id': r['id'], - 'highlights': r.highlights("content", text=doc.content) if doc else None, # NOQA: E501 - 'score': r.score, - 'rank': r.rank, - 'document': DocumentSerializer(doc).data if doc else None, - 'title': r['title'] - } - - def get(self, request, format=None): - from documents import index - - if 'query' in request.query_params: - query = request.query_params['query'] - else: - query = None - - if 'more_like' in request.query_params: - more_like_id = request.query_params['more_like'] - more_like_content = Document.objects.get(id=more_like_id).content - else: - more_like_id = None - more_like_content = None - - if not query and not more_like_id: - return Response({ - 'count': 0, - 'page': 0, - 'page_count': 0, - 'corrected_query': None, - 'results': []}) - - try: - page = int(request.query_params.get('page', 1)) - except (ValueError, TypeError): - page = 1 - - if page < 1: - page = 1 - - ix = index.open_index() - - try: - with index.query_page(ix, page, query, more_like_id, more_like_content) as (result_page, corrected_query): # NOQA: E501 - return Response( - {'count': len(result_page), - 'page': result_page.pagenum, - 'page_count': result_page.pagecount, - 'corrected_query': corrected_query, - 'results': list(map(self.add_infos_to_hit, result_page))}) - except Exception as e: - return HttpResponseBadRequest(str(e)) - - class SearchAutoCompleteView(APIView): permission_classes = (IsAuthenticated,) diff --git a/src/locale/en_US/LC_MESSAGES/django.po b/src/locale/en_US/LC_MESSAGES/django.po index 2a17fd9ae..1c7cc5977 100644 --- a/src/locale/en_US/LC_MESSAGES/django.po +++ b/src/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-03-17 22:31+0100\n" +"POT-Creation-Date: 2021-04-05 22:05+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -230,7 +230,7 @@ msgstr "" msgid "logs" msgstr "" -#: documents/models.py:344 documents/models.py:396 +#: documents/models.py:344 documents/models.py:401 msgid "saved view" msgstr "" @@ -254,103 +254,111 @@ msgstr "" msgid "sort field" msgstr "" -#: documents/models.py:364 +#: documents/models.py:367 msgid "sort reverse" msgstr "" -#: documents/models.py:370 +#: documents/models.py:373 msgid "title contains" msgstr "" -#: documents/models.py:371 +#: documents/models.py:374 msgid "content contains" msgstr "" -#: documents/models.py:372 +#: documents/models.py:375 msgid "ASN is" msgstr "" -#: documents/models.py:373 +#: documents/models.py:376 msgid "correspondent is" msgstr "" -#: documents/models.py:374 +#: documents/models.py:377 msgid "document type is" msgstr "" -#: documents/models.py:375 +#: documents/models.py:378 msgid "is in inbox" msgstr "" -#: documents/models.py:376 +#: documents/models.py:379 msgid "has tag" msgstr "" -#: documents/models.py:377 +#: documents/models.py:380 msgid "has any tag" msgstr "" -#: documents/models.py:378 +#: documents/models.py:381 msgid "created before" msgstr "" -#: documents/models.py:379 +#: documents/models.py:382 msgid "created after" msgstr "" -#: documents/models.py:380 +#: documents/models.py:383 msgid "created year is" msgstr "" -#: documents/models.py:381 +#: documents/models.py:384 msgid "created month is" msgstr "" -#: documents/models.py:382 +#: documents/models.py:385 msgid "created day is" msgstr "" -#: documents/models.py:383 +#: documents/models.py:386 msgid "added before" msgstr "" -#: documents/models.py:384 +#: documents/models.py:387 msgid "added after" msgstr "" -#: documents/models.py:385 +#: documents/models.py:388 msgid "modified before" msgstr "" -#: documents/models.py:386 +#: documents/models.py:389 msgid "modified after" msgstr "" -#: documents/models.py:387 +#: documents/models.py:390 msgid "does not have tag" msgstr "" -#: documents/models.py:388 +#: documents/models.py:391 msgid "does not have ASN" msgstr "" -#: documents/models.py:389 +#: documents/models.py:392 msgid "title or content contains" msgstr "" -#: documents/models.py:400 +#: documents/models.py:393 +msgid "fulltext query" +msgstr "" + +#: documents/models.py:394 +msgid "more like this" +msgstr "" + +#: documents/models.py:405 msgid "rule type" msgstr "" -#: documents/models.py:404 +#: documents/models.py:409 msgid "value" msgstr "" -#: documents/models.py:410 +#: documents/models.py:415 msgid "filter rule" msgstr "" -#: documents/models.py:411 +#: documents/models.py:416 msgid "filter rules" msgstr "" @@ -452,7 +460,7 @@ msgstr "" msgid "Spanish" msgstr "" -#: paperless/urls.py:118 +#: paperless/urls.py:113 msgid "Paperless-ng administration" msgstr "" diff --git a/src/locale/it_IT/LC_MESSAGES/django.po b/src/locale/it_IT/LC_MESSAGES/django.po index 48dfe762e..9c7cd71ef 100644 --- a/src/locale/it_IT/LC_MESSAGES/django.po +++ b/src/locale/it_IT/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: paperless-ng\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-03-17 22:31+0100\n" -"PO-Revision-Date: 2021-03-18 00:34\n" +"PO-Revision-Date: 2021-04-01 11:51\n" "Last-Translator: \n" "Language-Team: Italian\n" "Language: it_IT\n" @@ -366,7 +366,7 @@ msgstr "Il tipo di file %(type)s non è supportato" #: documents/templates/index.html:21 msgid "Paperless-ng is loading..." -msgstr "Paperless-ng si sta caricando..." +msgstr "Paperless-ng è in caricamento..." #: documents/templates/registration/logged_out.html:13 msgid "Paperless-ng signed out" @@ -374,11 +374,11 @@ msgstr "Paperless-ng è uscito" #: documents/templates/registration/logged_out.html:41 msgid "You have been successfully logged out. Bye!" -msgstr "Vi siete disconnessi. Ciao!" +msgstr "Ti sei disconnesso. A presto!" #: documents/templates/registration/logged_out.html:42 msgid "Sign in again" -msgstr "Rientra nuovamente" +msgstr "Accedi nuovamente" #: documents/templates/registration/login.html:13 msgid "Paperless-ng sign in" diff --git a/src/locale/ro_RO/LC_MESSAGES/django.po b/src/locale/ro_RO/LC_MESSAGES/django.po index 70194eff5..dcb505aba 100644 --- a/src/locale/ro_RO/LC_MESSAGES/django.po +++ b/src/locale/ro_RO/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: paperless-ng\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-03-17 22:31+0100\n" -"PO-Revision-Date: 2021-03-17 22:42\n" +"PO-Revision-Date: 2021-03-28 09:07\n" "Last-Translator: \n" "Language-Team: Romanian\n" "Language: ro_RO\n" @@ -446,7 +446,7 @@ msgstr "Rusă" #: paperless/settings.py:308 msgid "Spanish" -msgstr "" +msgstr "Spaniolă" #: paperless/urls.py:118 msgid "Paperless-ng administration" diff --git a/src/paperless/checks.py b/src/paperless/checks.py index 0d11d8a90..1b19f1a72 100644 --- a/src/paperless/checks.py +++ b/src/paperless/checks.py @@ -23,9 +23,12 @@ def path_check(var, directory): exists_hint.format(directory) )) else: - test_file = os.path.join(directory, '__paperless_write_test__') + test_file = os.path.join( + directory, f'__paperless_write_test_{os.getpid()}__' + ) try: - open(test_file, 'w') + with open(test_file, 'w'): + pass except PermissionError: messages.append(Error( writeable_message.format(var), @@ -33,8 +36,9 @@ def path_check(var, directory): f'\n{stat.filemode(os.stat(directory).st_mode)} ' f'{directory}\n') )) - else: - os.remove(test_file) + finally: + if os.path.isfile(test_file): + os.remove(test_file) return messages diff --git a/src/paperless/urls.py b/src/paperless/urls.py index 4e0b8f191..7521d49de 100755 --- a/src/paperless/urls.py +++ b/src/paperless/urls.py @@ -12,11 +12,10 @@ from django.utils.translation import gettext_lazy as _ from paperless.consumers import StatusConsumer from documents.views import ( CorrespondentViewSet, - DocumentViewSet, + UnifiedSearchViewSet, LogViewSet, TagViewSet, DocumentTypeViewSet, - SearchView, IndexView, SearchAutoCompleteView, StatisticsView, @@ -31,7 +30,7 @@ from paperless.views import FaviconView api_router = DefaultRouter() api_router.register(r"correspondents", CorrespondentViewSet) api_router.register(r"document_types", DocumentTypeViewSet) -api_router.register(r"documents", DocumentViewSet) +api_router.register(r"documents", UnifiedSearchViewSet) api_router.register(r"logs", LogViewSet, basename="logs") api_router.register(r"tags", TagViewSet) api_router.register(r"saved_views", SavedViewViewSet) @@ -47,10 +46,6 @@ urlpatterns = [ SearchAutoCompleteView.as_view(), name="autocomplete"), - re_path(r"^search/", - SearchView.as_view(), - name="search"), - re_path(r"^statistics/", StatisticsView.as_view(), name="statistics"), diff --git a/src/paperless/version.py b/src/paperless/version.py index 183d98d3f..532acc3df 100644 --- a/src/paperless/version.py +++ b/src/paperless/version.py @@ -1 +1 @@ -__version__ = (1, 3, 2) +__version__ = (1, 4, 0)