Compare commits
2087 Commits
ng-0.9.12
...
beta-1.6.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
77cc7cebf9 | ||
![]() |
f61105c041 | ||
![]() |
b4dc073a48 | ||
![]() |
2324f91622 | ||
![]() |
6b5c89b6f8 | ||
![]() |
e5e94ffb6d | ||
![]() |
e3584eb61e | ||
![]() |
bb5d8497c9 | ||
![]() |
3ea6028c9f | ||
![]() |
6e901ff362 | ||
![]() |
d1032e4d7d | ||
![]() |
67efda7cf4 | ||
![]() |
0545d9bab7 | ||
![]() |
a233e5d404 | ||
![]() |
2484563ac7 | ||
![]() |
4d4ed7bc7b | ||
![]() |
ff9df4a6ed | ||
![]() |
fdc051114b | ||
![]() |
7aa8dcb0e3 | ||
![]() |
37531ec5e0 | ||
![]() |
f8991ca8e0 | ||
![]() |
cd9c46e88e | ||
![]() |
04c28d4105 | ||
![]() |
59975087c5 | ||
![]() |
0f804937f7 | ||
![]() |
f3cda7d551 | ||
![]() |
209dba6a4a | ||
![]() |
43bc42826b | ||
![]() |
004375b478 | ||
![]() |
49a1c3f8c2 | ||
![]() |
c748394ff0 | ||
![]() |
9d246b1ad4 | ||
![]() |
038dc21c78 | ||
![]() |
7c758c0750 | ||
![]() |
0925c90047 | ||
![]() |
74b94bc66a | ||
![]() |
65e2177964 | ||
![]() |
a48c6e5b43 | ||
![]() |
b00f3102a6 | ||
![]() |
f8679a251e | ||
![]() |
9484eb9f6b | ||
![]() |
dd6c25be13 | ||
![]() |
4e917b249d | ||
![]() |
a87f96d780 | ||
![]() |
b959455ff8 | ||
![]() |
1e6c666df4 | ||
![]() |
1fd0f45a02 | ||
![]() |
93487b1aeb | ||
![]() |
0772231ac0 | ||
![]() |
37a5627b40 | ||
![]() |
a679a1966a | ||
![]() |
b21e8a77be | ||
![]() |
049a2dde96 | ||
![]() |
78a4891dfc | ||
![]() |
5c9c10a6db | ||
![]() |
16cb3ee779 | ||
![]() |
5bfadc2147 | ||
![]() |
80d05add03 | ||
![]() |
3493f4da7b | ||
![]() |
374ce47fcd | ||
![]() |
bc58e459ea | ||
![]() |
25c8fe5c0e | ||
![]() |
dad9de3be3 | ||
![]() |
f8d1fc749c | ||
![]() |
bbd4da5a27 | ||
![]() |
acc94dcde0 | ||
![]() |
72685b0330 | ||
![]() |
cffd59f9ba | ||
![]() |
c5e55be84a | ||
![]() |
03b48078df | ||
![]() |
f0908f3a58 | ||
![]() |
49e6e54e0b | ||
![]() |
cbe4e698c5 | ||
![]() |
aa39abc41a | ||
![]() |
c0ce6e28d4 | ||
![]() |
9b42c0aa50 | ||
![]() |
f7caad9af9 | ||
![]() |
992406d5a0 | ||
![]() |
60ad0bb4e2 | ||
![]() |
f23d53fe1a | ||
![]() |
12fa3c7417 | ||
![]() |
fc695896dd | ||
![]() |
13885968e3 | ||
![]() |
e331f23bb0 | ||
![]() |
d89ac59004 | ||
![]() |
5b365a15c5 | ||
![]() |
d8617746eb | ||
![]() |
1a830eb555 | ||
![]() |
bb0e858dfe | ||
![]() |
4377998232 | ||
![]() |
6852127c33 | ||
![]() |
83e40f3e87 | ||
![]() |
31d96ea85b | ||
![]() |
9f895fe65f | ||
![]() |
84f96d7a98 | ||
![]() |
a6144e9692 | ||
![]() |
88d5bdc8bf | ||
![]() |
c2fae07c11 | ||
![]() |
2309b12a31 | ||
![]() |
8dc57e8e87 | ||
![]() |
da4c6e8fb6 | ||
![]() |
a1a01870e6 | ||
![]() |
80d2f34ad0 | ||
![]() |
b5b7cf67bf | ||
![]() |
ca87b6dbfd | ||
![]() |
7cfad2d7ef | ||
![]() |
ae18b82282 | ||
![]() |
701506e569 | ||
![]() |
2f04e0de85 | ||
![]() |
a561cfe808 | ||
![]() |
9ce3708647 | ||
![]() |
9dcfda1f41 | ||
![]() |
e23859f776 | ||
![]() |
ae94b90fe4 | ||
![]() |
cbac6fc8d5 | ||
![]() |
5941c383b6 | ||
![]() |
396c3fb554 | ||
![]() |
dbdd9b93f8 | ||
![]() |
84e7e74d00 | ||
![]() |
0103e6546f | ||
![]() |
a1f09bdc4e | ||
![]() |
ba561604f0 | ||
![]() |
bad4be4cbc | ||
![]() |
2f7c351039 | ||
![]() |
4b05a18e3e | ||
![]() |
b7352e255e | ||
![]() |
1408270fb1 | ||
![]() |
cd46b7ae45 | ||
![]() |
6ad5d19cf8 | ||
![]() |
66bbf322c5 | ||
![]() |
7bdd397c78 | ||
![]() |
86069c291f | ||
![]() |
ba87146c61 | ||
![]() |
47e177a575 | ||
![]() |
b700b3d1f7 | ||
![]() |
11a377b973 | ||
![]() |
e889c2e54e | ||
![]() |
ab81439aac | ||
![]() |
75b4d46f4c | ||
![]() |
d680711ffc | ||
![]() |
ba38c2ad63 | ||
![]() |
49d7492e05 | ||
![]() |
1e288100a9 | ||
![]() |
d13fdd0791 | ||
![]() |
73a8569d21 | ||
![]() |
2a47b3f1a1 | ||
![]() |
41494ee689 | ||
![]() |
8bf6fadf0e | ||
![]() |
13b2c438b9 | ||
![]() |
368f7ab0ed | ||
![]() |
8b23a5e4c1 | ||
![]() |
60a87f1541 | ||
![]() |
0827553a69 | ||
![]() |
1688af7a0d | ||
![]() |
1412daf615 | ||
![]() |
57db05f95b | ||
![]() |
1c1e7183e3 | ||
![]() |
ed48001fb2 | ||
![]() |
d864734bc5 | ||
![]() |
150740766f | ||
![]() |
848f52688b | ||
![]() |
bcab0e8579 | ||
![]() |
e6cce4069e | ||
![]() |
ddfeeb6af7 | ||
![]() |
5c2b524d07 | ||
![]() |
17d51a1cf6 | ||
![]() |
01ce6c5f6f | ||
![]() |
79aa56c898 | ||
![]() |
93e8d49540 | ||
![]() |
c5f31481b9 | ||
![]() |
56cdbc0c60 | ||
![]() |
d0a5160978 | ||
![]() |
106b55fc93 | ||
![]() |
573da8bd03 | ||
![]() |
7845cece6b | ||
![]() |
74dea42687 | ||
![]() |
0d610e364c | ||
![]() |
0476c7204f | ||
![]() |
e0683c19c8 | ||
![]() |
a7e1c1c4d0 | ||
![]() |
335b8c63e0 | ||
![]() |
f9bbb9a8c3 | ||
![]() |
fe5293ba36 | ||
![]() |
3297596f2e | ||
![]() |
5b5e8d7860 | ||
![]() |
7049d04d71 | ||
![]() |
17ddf18a67 | ||
![]() |
e60bfda93f | ||
![]() |
40dda1e0f7 | ||
![]() |
3715afbb97 | ||
![]() |
6f22f720e9 | ||
![]() |
ddce6e1f0a | ||
![]() |
199affb244 | ||
![]() |
899e3eed1b | ||
![]() |
744a0f1c8c | ||
![]() |
c6fc435869 | ||
![]() |
81ef51fd01 | ||
![]() |
0eaa1e3385 | ||
![]() |
e9a3a53849 | ||
![]() |
4ae4fb65e6 | ||
![]() |
95a4d7e8a9 | ||
![]() |
bf30297829 | ||
![]() |
f5f6985e4e | ||
![]() |
efe5df3459 | ||
![]() |
99409f258f | ||
![]() |
4400915e0c | ||
![]() |
37f6b249dc | ||
![]() |
4826c645cd | ||
![]() |
545b8e2b6e | ||
![]() |
d6744f0996 | ||
![]() |
55b980991b | ||
![]() |
add09db40a | ||
![]() |
f08901c639 | ||
![]() |
fd58096112 | ||
![]() |
3a652a8941 | ||
![]() |
52e6b45580 | ||
![]() |
7b7ba83a87 | ||
![]() |
8ba282362d | ||
![]() |
4451acbf0b | ||
![]() |
d257eeeabf | ||
![]() |
9f062fa14b | ||
![]() |
ba1038b4a8 | ||
![]() |
ef1b971fca | ||
![]() |
3444f9e5f2 | ||
![]() |
af768b8d66 | ||
![]() |
fbe0cdadd4 | ||
![]() |
ff3d455f45 | ||
![]() |
2eba2942d0 | ||
![]() |
556143a941 | ||
![]() |
e82011a91d | ||
![]() |
f2f80685a8 | ||
![]() |
7aa77eab07 | ||
![]() |
419fe7fc68 | ||
![]() |
1d4b5e243c | ||
![]() |
d25604da81 | ||
![]() |
17617b82c6 | ||
![]() |
3f89fdf300 | ||
![]() |
0cc9b7e357 | ||
![]() |
32e1188207 | ||
![]() |
c634e6a801 | ||
![]() |
d1a7557405 | ||
![]() |
b1a7c27d96 | ||
![]() |
5ebf8534ba | ||
![]() |
65bb5d067a | ||
![]() |
0a5da90f84 | ||
![]() |
59827290dc | ||
![]() |
b0f8d15542 | ||
![]() |
366ffec165 | ||
![]() |
0cd3059831 | ||
![]() |
db4da7092b | ||
![]() |
c6851c9f70 | ||
![]() |
7c4a098977 | ||
![]() |
cfb3db311c | ||
![]() |
b049ad4f3a | ||
![]() |
fd5a761c8c | ||
![]() |
e9befc44ec | ||
![]() |
180c82c694 | ||
![]() |
36b041376c | ||
![]() |
387db5ffb6 | ||
![]() |
ee27e71e29 | ||
![]() |
189110ec09 | ||
![]() |
4fc44060ea | ||
![]() |
c945b90b64 | ||
![]() |
7113a18f3b | ||
![]() |
921000625e | ||
![]() |
b272d695e3 | ||
![]() |
e93c85ba92 | ||
![]() |
6d58491d1c | ||
![]() |
413897639f | ||
![]() |
065d9bc1e3 | ||
![]() |
bb56254e88 | ||
![]() |
8b01336d54 | ||
![]() |
4d5f1bd81a | ||
![]() |
78efd4961e | ||
![]() |
1ab157c2a9 | ||
![]() |
10bde76494 | ||
![]() |
81499665d8 | ||
![]() |
8621546736 | ||
![]() |
abd27342b6 | ||
![]() |
f9a3a7f2c6 | ||
![]() |
165b476635 | ||
![]() |
7448609ba7 | ||
![]() |
7380e056cd | ||
![]() |
0b6c749b60 | ||
![]() |
1ba1df2529 | ||
![]() |
8ef913b117 | ||
![]() |
e1c29d09e7 | ||
![]() |
1b7f1614b5 | ||
![]() |
dcb8c17c75 | ||
![]() |
f42811285d | ||
![]() |
f9aa40fb57 | ||
![]() |
d3900536a1 | ||
![]() |
01c139ef2d | ||
![]() |
6442f1c572 | ||
![]() |
8b5a35cc70 | ||
![]() |
8d443f212a | ||
![]() |
6ab2e881a3 | ||
![]() |
c9baa76afd | ||
![]() |
66b9a99e71 | ||
![]() |
27a835a69c | ||
![]() |
1830cd856a | ||
![]() |
c656610c93 | ||
![]() |
e32f63d76e | ||
![]() |
7eca68dfc0 | ||
![]() |
75e3506046 | ||
![]() |
c839a5dd55 | ||
![]() |
7349ab063d | ||
![]() |
165f1d3341 | ||
![]() |
2a91a09835 | ||
![]() |
8f20003687 | ||
![]() |
94e07fee96 | ||
![]() |
c6618b2cc0 | ||
![]() |
7af291622f | ||
![]() |
e7603eff5f | ||
![]() |
866f365e0b | ||
![]() |
eac40ccd26 | ||
![]() |
1e6d9dda40 | ||
![]() |
7ecf42d70f | ||
![]() |
d92e48bc33 | ||
![]() |
51be0f07a5 | ||
![]() |
6751ed33af | ||
![]() |
5313909cd8 | ||
![]() |
a6e65583f2 | ||
![]() |
e17a33e110 | ||
![]() |
2a99765020 | ||
![]() |
98f2ba949c | ||
![]() |
66318b7e39 | ||
![]() |
eb91b02ebf | ||
![]() |
c643c0fe36 | ||
![]() |
285579822a | ||
![]() |
adacb2ab92 | ||
![]() |
e338274669 | ||
![]() |
7ce65cbbaa | ||
![]() |
7e0345cda6 | ||
![]() |
c27a7ac60a | ||
![]() |
0e7f03c595 | ||
![]() |
6bc44fd93f | ||
![]() |
074decc320 | ||
![]() |
ccc99a45f9 | ||
![]() |
dab8b6ac87 | ||
![]() |
a134ca098a | ||
![]() |
8d2a809df2 | ||
![]() |
0b8db1fec9 | ||
![]() |
791e6cf54f | ||
![]() |
14a117acfa | ||
![]() |
6eef72d524 | ||
![]() |
05543e5341 | ||
![]() |
4b64b80d86 | ||
![]() |
c20c1f96ca | ||
![]() |
7194915bf3 | ||
![]() |
8156580e4f | ||
![]() |
b63a01f527 | ||
![]() |
10b16dbcdf | ||
![]() |
4d24f92914 | ||
![]() |
8db6d9cd34 | ||
![]() |
821398437f | ||
![]() |
1a2213b1fb | ||
![]() |
e49b4c137e | ||
![]() |
cabb5cafca | ||
![]() |
016f7d90dc | ||
![]() |
934d5f7164 | ||
![]() |
a2c0d6d920 | ||
![]() |
7e1161db62 | ||
![]() |
4cfdb54a0e | ||
![]() |
b35544a44d | ||
![]() |
46a4ec7dd0 | ||
![]() |
35202662f3 | ||
![]() |
d1267dc398 | ||
![]() |
37b1b9ae39 | ||
![]() |
31f9938d1b | ||
![]() |
f8b5ec0f7d | ||
![]() |
1dc474d33d | ||
![]() |
1dfe86a069 | ||
![]() |
63778935b0 | ||
![]() |
39f7f5e512 | ||
![]() |
e320c32182 | ||
![]() |
cd8c524b19 | ||
![]() |
f7554e7f33 | ||
![]() |
6ae39361a5 | ||
![]() |
dfe88864ad | ||
![]() |
8c14d05494 | ||
![]() |
bc77cbf956 | ||
![]() |
0bb9f47590 | ||
![]() |
effa3cd3a5 | ||
![]() |
fd811d68ff | ||
![]() |
fda64e81a5 | ||
![]() |
3c598dfca9 | ||
![]() |
0c1e1b6b68 | ||
![]() |
7f2f4c666e | ||
![]() |
94e6e36f26 | ||
![]() |
45a534e176 | ||
![]() |
3303ee1afc | ||
![]() |
337330a508 | ||
![]() |
8b6001c328 | ||
![]() |
9ebf3c270c | ||
![]() |
fbde0ce88f | ||
![]() |
5009989a59 | ||
![]() |
436368ad22 | ||
![]() |
cc7bbeca97 | ||
![]() |
d608d6a441 | ||
![]() |
cd80f7ddbe | ||
![]() |
5bff97ec96 | ||
![]() |
23c1ea1b79 | ||
![]() |
097d1a55fe | ||
![]() |
13426d3c3f | ||
![]() |
e4859412bc | ||
![]() |
95309ad4ae | ||
![]() |
41bdf1bcc9 | ||
![]() |
04a4cd7d76 | ||
![]() |
582f7a9301 | ||
![]() |
9bc48fed73 | ||
![]() |
3e7e7023fc | ||
![]() |
8c853e56e4 | ||
![]() |
1941be8f53 | ||
![]() |
06253ed8f2 | ||
![]() |
ec5416abfd | ||
![]() |
940d056657 | ||
![]() |
a10d331296 | ||
![]() |
c2035b4324 | ||
![]() |
879a239bcd | ||
![]() |
4d1e33af9e | ||
![]() |
64c7699a19 | ||
![]() |
0219aa97fe | ||
![]() |
657ed211c0 | ||
![]() |
305666378b | ||
![]() |
50102af229 | ||
![]() |
ff4fa4f164 | ||
![]() |
3e35d9cd8c | ||
![]() |
e1a36972b1 | ||
![]() |
250575acb9 | ||
![]() |
d9cd312d07 | ||
![]() |
d733de9d9f | ||
![]() |
088cc9cd71 | ||
![]() |
895781c5a3 | ||
![]() |
f493bd539d | ||
![]() |
de9fbd48df | ||
![]() |
1e58b0c43e | ||
![]() |
68cfde5b65 | ||
![]() |
99157b76b2 | ||
![]() |
5f58a329d3 | ||
![]() |
67b9977d57 | ||
![]() |
b469937d4d | ||
![]() |
30b540045e | ||
![]() |
87af195862 | ||
![]() |
0ff001b4de | ||
![]() |
d6280b7939 | ||
![]() |
07f10d3907 | ||
![]() |
9fb18802fc | ||
![]() |
0936a2c474 | ||
![]() |
edd21d1233 | ||
![]() |
86e4ec03dd | ||
![]() |
994d502c41 | ||
![]() |
3d3de5d0fe | ||
![]() |
f303a1c423 | ||
![]() |
1fa814e6e5 | ||
![]() |
0aed34cb71 | ||
![]() |
abddbb11c1 | ||
![]() |
a25ba99bfb | ||
![]() |
512615631a | ||
![]() |
98086fd04b | ||
![]() |
fe2aa2bbf3 | ||
![]() |
da361e9d64 | ||
![]() |
f75d4ccc89 | ||
![]() |
c2621f4633 | ||
![]() |
e6602f1153 | ||
![]() |
069e78881d | ||
![]() |
e4e7ee8433 | ||
![]() |
ddb25ce281 | ||
![]() |
b4863173bd | ||
![]() |
140dbe1686 | ||
![]() |
f2f7b71367 | ||
![]() |
10a57687a3 | ||
![]() |
f84be89e49 | ||
![]() |
fb6369f43c | ||
![]() |
4b7c8c6157 | ||
![]() |
81e8317326 | ||
![]() |
3d6ca2cda3 | ||
![]() |
0740473ecc | ||
![]() |
1bce697475 | ||
![]() |
baaae7f76c | ||
![]() |
bb19d4de9f | ||
![]() |
6880f72472 | ||
![]() |
89fda615f6 | ||
![]() |
2c84d29050 | ||
![]() |
85399cf99f | ||
![]() |
e655b40d3a | ||
![]() |
3e94f3c58c | ||
![]() |
61a42f45ab | ||
![]() |
4e7863c27f | ||
![]() |
f9a5081438 | ||
![]() |
ea5d7ac6f0 | ||
![]() |
b318c0ab04 | ||
![]() |
3d0a7c73e9 | ||
![]() |
e98bf547e5 | ||
![]() |
8cb2e588fb | ||
![]() |
e4f99de13d | ||
![]() |
206d5be46c | ||
![]() |
e0f80c4364 | ||
![]() |
86891323ea | ||
![]() |
69e315ee8a | ||
![]() |
ced3aefc54 | ||
![]() |
6abf26bd99 | ||
![]() |
4667a7a6a2 | ||
![]() |
6eb5f3a518 | ||
![]() |
6f87b7830d | ||
![]() |
ccf974b1b7 | ||
![]() |
d9016ed619 | ||
![]() |
bd2eade33d | ||
![]() |
11e8ea471d | ||
![]() |
992bef1553 | ||
![]() |
396235be3e | ||
![]() |
9662463510 | ||
![]() |
64e1590d9e | ||
![]() |
c751690e79 | ||
![]() |
f76915117b | ||
![]() |
ba915844a4 | ||
![]() |
59d96d170e | ||
![]() |
a9a27eda51 | ||
![]() |
249de7ec6d | ||
![]() |
8aabf4805a | ||
![]() |
2ab06d7294 | ||
![]() |
e71f38deea | ||
![]() |
0d70925abe | ||
![]() |
89bb73aa25 | ||
![]() |
1c93f26034 | ||
![]() |
86e44da695 | ||
![]() |
530ad72e18 | ||
![]() |
ae185a1848 | ||
![]() |
e3682b69f7 | ||
![]() |
fe72fc173d | ||
![]() |
3b4663639d | ||
![]() |
51b20a6e17 | ||
![]() |
ad9122cd4f | ||
![]() |
7d8bf75e44 | ||
![]() |
e36e4f61b3 | ||
![]() |
5612ad08dd | ||
![]() |
7bc8325df9 | ||
![]() |
2aca64bfcd | ||
![]() |
e9956234a3 | ||
![]() |
d656de8883 | ||
![]() |
32f0ebaac3 | ||
![]() |
73700437e4 | ||
![]() |
14d96350c3 | ||
![]() |
4e9c4ebd02 | ||
![]() |
097fe424c2 | ||
![]() |
12abb592be | ||
![]() |
4f0951402a | ||
![]() |
b555b3664f | ||
![]() |
2dcacaee14 | ||
![]() |
bf2cdae3b1 | ||
![]() |
64304c5121 | ||
![]() |
cd43bc1f66 | ||
![]() |
1b24136590 | ||
![]() |
e8d5b549de | ||
![]() |
3866a77d68 | ||
![]() |
360fe68f92 | ||
![]() |
c9229f9c80 | ||
![]() |
e5b92d895d | ||
![]() |
a7643c1c29 | ||
![]() |
45fd4e8565 | ||
![]() |
211a9d720a | ||
![]() |
da9c2735b4 | ||
![]() |
d31baca442 | ||
![]() |
499d6f79aa | ||
![]() |
49e049f1c5 | ||
![]() |
7411d7c1e2 | ||
![]() |
3f5d3d15fd | ||
![]() |
68fb85ceca | ||
![]() |
3ebe6d5aef | ||
![]() |
566b3ed53d | ||
![]() |
a688c747d7 | ||
![]() |
83b90e1416 | ||
![]() |
23c6f849d6 | ||
![]() |
ba6843df83 | ||
![]() |
0b90e69119 | ||
![]() |
dbe820323e | ||
![]() |
47d95d5b0a | ||
![]() |
757507e634 | ||
![]() |
971192f6f3 | ||
![]() |
07d3f47978 | ||
![]() |
fbfc7df593 | ||
![]() |
3c7644ce79 | ||
![]() |
4e4a8bcca8 | ||
![]() |
dc5586b16d | ||
![]() |
1d87b48471 | ||
![]() |
353a3432df | ||
![]() |
efe94bbf18 | ||
![]() |
cea6ec09bc | ||
![]() |
4a3276f69c | ||
![]() |
f164def2ed | ||
![]() |
511c76ae7a | ||
![]() |
bfa6dda0de | ||
![]() |
54af734971 | ||
![]() |
5b9763ecb4 | ||
![]() |
438bad23e8 | ||
![]() |
ae5a205ba3 | ||
![]() |
19b683e7b0 | ||
![]() |
0c92027414 | ||
![]() |
c4e3b2ca2f | ||
![]() |
ba67b89db7 | ||
![]() |
06f308ede3 | ||
![]() |
214fb8204b | ||
![]() |
2a2d7be9f9 | ||
![]() |
23304c3746 | ||
![]() |
20829c90b2 | ||
![]() |
33cc3ce7e0 | ||
![]() |
3487b23e88 | ||
![]() |
ec707bd02a | ||
![]() |
3cc463b2c3 | ||
![]() |
99e5cf0cdc | ||
![]() |
ab0ec0d5a5 | ||
![]() |
e0a2af3d98 | ||
![]() |
524bc2722f | ||
![]() |
4718fe13c2 | ||
![]() |
8592acf6b8 | ||
![]() |
88042d7072 | ||
![]() |
bf92e52d5c | ||
![]() |
419580b3be | ||
![]() |
5ee1f6b82b | ||
![]() |
410bb6a84e | ||
![]() |
af2b5fef13 | ||
![]() |
372ac3a40c | ||
![]() |
a1507d6079 | ||
![]() |
9242a8901a | ||
![]() |
1d4f25f930 | ||
![]() |
7323ec8d16 | ||
![]() |
39d45367d0 | ||
![]() |
a6521952b0 | ||
![]() |
7148c10f1b | ||
![]() |
4a1a66248d | ||
![]() |
67d0773231 | ||
![]() |
ff370172b5 | ||
![]() |
1f707e86cc | ||
![]() |
a3dae02cfb | ||
![]() |
3eae8a2210 | ||
![]() |
0f18fe1853 | ||
![]() |
513c61eb79 | ||
![]() |
4031233fd4 | ||
![]() |
76ff6100a3 | ||
![]() |
05c36f91cf | ||
![]() |
6625f8962a | ||
![]() |
63402b70d2 | ||
![]() |
2ae4a7806d | ||
![]() |
fcc4ecd007 | ||
![]() |
45497250cd | ||
![]() |
7dd957140e | ||
![]() |
4cd772a39e | ||
![]() |
b3906e7bc1 | ||
![]() |
e5009b4cd2 | ||
![]() |
10bf9fd1f8 | ||
![]() |
bd8e68692e | ||
![]() |
b8386a1531 | ||
![]() |
61534fb29d | ||
![]() |
9ad81be38c | ||
![]() |
cf7048e336 | ||
![]() |
a6105b3ad3 | ||
![]() |
a262a82cad | ||
![]() |
635c96accf | ||
![]() |
5c174a69c2 | ||
![]() |
de08d17835 | ||
![]() |
ca1e838c52 | ||
![]() |
3b73146ecd | ||
![]() |
8e3822f8e6 | ||
![]() |
3b912a0de1 | ||
![]() |
c72791bd21 | ||
![]() |
80ba5b561f | ||
![]() |
f9f4d4c937 | ||
![]() |
0419c52d35 | ||
![]() |
93a79be1e2 | ||
![]() |
f8afbae2cd | ||
![]() |
4a52d346f9 | ||
![]() |
7d59d11725 | ||
![]() |
5886348188 | ||
![]() |
a8135528b1 | ||
![]() |
df6b991161 | ||
![]() |
3f33f66387 | ||
![]() |
870808f3c2 | ||
![]() |
b12fcca20d | ||
![]() |
61b47e358f | ||
![]() |
40a2fb7936 | ||
![]() |
9afc8ba43d | ||
![]() |
b122a05c71 | ||
![]() |
f568a9fdfa | ||
![]() |
a350bb3086 | ||
![]() |
8ae4b7560b | ||
![]() |
96f4924911 | ||
![]() |
f3703fc6e3 | ||
![]() |
0d5fd229bf | ||
![]() |
1519e66550 | ||
![]() |
fcae461430 | ||
![]() |
039d797dfc | ||
![]() |
4f61868b28 | ||
![]() |
9efbc55fd6 | ||
![]() |
2e4e88114e | ||
![]() |
8ee2e8b23d | ||
![]() |
37287c3e7e | ||
![]() |
814d90745b | ||
![]() |
48e8076e34 | ||
![]() |
edb9d934b2 | ||
![]() |
ed44f0cb04 | ||
![]() |
1c2f3cf9af | ||
![]() |
13afd25690 | ||
![]() |
f9b6374685 | ||
![]() |
56c9b578e3 | ||
![]() |
e792a00feb | ||
![]() |
c35c4eade9 | ||
![]() |
5bf725546b | ||
![]() |
6b6862705e | ||
![]() |
b89b51b121 | ||
![]() |
1b31388232 | ||
![]() |
8256e73f04 | ||
![]() |
fc4e59ec00 | ||
![]() |
428e00ba23 | ||
![]() |
2ccbb08c3f | ||
![]() |
eefc026a17 | ||
![]() |
d89022a280 | ||
![]() |
93bd24c9d2 | ||
![]() |
197aec2945 | ||
![]() |
e16d58cff5 | ||
![]() |
92667009be | ||
![]() |
c93657f40e | ||
![]() |
16658f5939 | ||
![]() |
ec0af59596 | ||
![]() |
9e1f9d6d9d | ||
![]() |
e652b927ce | ||
![]() |
5a97f3f94b | ||
![]() |
9494c243a4 | ||
![]() |
c0a1be4325 | ||
![]() |
70fda8e2f8 | ||
![]() |
5765893f69 | ||
![]() |
dc26c9b7cc | ||
![]() |
17b9d7eb42 | ||
![]() |
0a897cae32 | ||
![]() |
37f56e824a | ||
![]() |
a8e7ec0e96 | ||
![]() |
b86d853cf1 | ||
![]() |
da0c94c9a1 | ||
![]() |
0547fd2760 | ||
![]() |
e0a6df8435 | ||
![]() |
c2d4ca7566 | ||
![]() |
56ce278bbd | ||
![]() |
e112541f5b | ||
![]() |
17c7b0840b | ||
![]() |
68658bd407 | ||
![]() |
9184845a9d | ||
![]() |
8ddb2fb305 | ||
![]() |
96f53986b7 | ||
![]() |
8566682209 | ||
![]() |
4f9ae17059 | ||
![]() |
7f9f805c5f | ||
![]() |
5208e81715 | ||
![]() |
01a786c117 | ||
![]() |
8bf4f31954 | ||
![]() |
07ab3e98ed | ||
![]() |
ba5899de7b | ||
![]() |
a4fef056ed | ||
![]() |
c266cd6aae | ||
![]() |
43d05b2e6d | ||
![]() |
6f0c14cc07 | ||
![]() |
2eac8fa91c | ||
![]() |
31f5e178b3 | ||
![]() |
c3d7088168 | ||
![]() |
a9e11b1cb7 | ||
![]() |
ee51a0be13 | ||
![]() |
1091387f48 | ||
![]() |
4db75537cb | ||
![]() |
cb4e738a0f | ||
![]() |
0cc32e7ed7 | ||
![]() |
94f90e1e81 | ||
![]() |
ce8f315747 | ||
![]() |
b761a549c0 | ||
![]() |
dd7c5da256 | ||
![]() |
02dd7ec615 | ||
![]() |
b7b448b870 | ||
![]() |
b7326afe5a | ||
![]() |
a3c4e4c6b6 | ||
![]() |
645297d68c | ||
![]() |
6d8782f771 | ||
![]() |
2728183eee | ||
![]() |
3d0891c73b | ||
![]() |
8226a8793e | ||
![]() |
d01477b337 | ||
![]() |
6bb07c72ab | ||
![]() |
a009462b80 | ||
![]() |
9111b130e4 | ||
![]() |
1dbd7b9bb4 | ||
![]() |
2f95dfc0e7 | ||
![]() |
acc317ddfd | ||
![]() |
1fbd3935ea | ||
![]() |
ca2bf962e9 | ||
![]() |
1d27a3a14b | ||
![]() |
8e1a9dde05 | ||
![]() |
8eabf8c77a | ||
![]() |
ec4ec41552 | ||
![]() |
8960b0300f | ||
![]() |
d6a2672cab | ||
![]() |
4b281ca89d | ||
![]() |
808b507b0f | ||
![]() |
ab47d03e1a | ||
![]() |
aca999090b | ||
![]() |
1322aaf4da | ||
![]() |
c49471fb3b | ||
![]() |
d13baab0a6 | ||
![]() |
359b46c15b | ||
![]() |
3b83e9a43d | ||
![]() |
ab7a499e8f | ||
![]() |
fffe4f694f | ||
![]() |
18c028cafd | ||
![]() |
4e289c7dab | ||
![]() |
3dfe5c9262 | ||
![]() |
be87caf7f6 | ||
![]() |
b7063b199a | ||
![]() |
1ed9c245f5 | ||
![]() |
fb1e9fe66a | ||
![]() |
38a386d5ae | ||
![]() |
726114575e | ||
![]() |
026c213ea4 | ||
![]() |
cd85d4e86a | ||
![]() |
e906bf58f0 | ||
![]() |
87d2209e6d | ||
![]() |
704f8ea680 | ||
![]() |
1e101fb3db | ||
![]() |
a16643ee29 | ||
![]() |
b783e0e211 | ||
![]() |
1ec4570c8d | ||
![]() |
434194d290 | ||
![]() |
f62e64357b | ||
![]() |
b9f49c5eca | ||
![]() |
13a839de57 | ||
![]() |
7eb4253c00 | ||
![]() |
dab210a183 | ||
![]() |
5319d4782a | ||
![]() |
0463c3fe54 | ||
![]() |
fe84430679 | ||
![]() |
9514e79bfb | ||
![]() |
b6756595d9 | ||
![]() |
8ddb3e80b7 | ||
![]() |
52bc1a62e1 | ||
![]() |
cd72ed2cec | ||
![]() |
ccaee4ce62 | ||
![]() |
0e596bd1fc | ||
![]() |
21fafd3255 | ||
![]() |
fda2bfbea7 | ||
![]() |
d26c46e034 | ||
![]() |
27cb243a2f | ||
![]() |
d3514fc5f9 | ||
![]() |
4954851b68 | ||
![]() |
6bcb12ddc9 | ||
![]() |
126a4ec21f | ||
![]() |
0aa084c792 | ||
![]() |
8f6e1360e1 | ||
![]() |
b7e570aba0 | ||
![]() |
ce2bae12af | ||
![]() |
b6111d8da6 | ||
![]() |
2fb1132b69 | ||
![]() |
9a04bc1beb | ||
![]() |
b39c3f7866 | ||
![]() |
740237a8fa | ||
![]() |
391db73ea8 | ||
![]() |
b6ff88645b | ||
![]() |
4cd1672094 | ||
![]() |
630cd814e2 | ||
![]() |
6606d7572c | ||
![]() |
b331e3388f | ||
![]() |
b6428aa85f | ||
![]() |
fa6d554d1f | ||
![]() |
816871eed3 | ||
![]() |
ee04a9226b | ||
![]() |
6b15093c43 | ||
![]() |
b9d0954924 | ||
![]() |
a94a81d839 | ||
![]() |
46be3924e4 | ||
![]() |
316a2469b8 | ||
![]() |
2e21fbf619 | ||
![]() |
e1254a053a | ||
![]() |
50bcd3daf1 | ||
![]() |
e3ba968fef | ||
![]() |
7725973b62 | ||
![]() |
30bf7418f5 | ||
![]() |
eb611b2c41 | ||
![]() |
e4909c3133 | ||
![]() |
2216330118 | ||
![]() |
ca090aa2fa | ||
![]() |
ec7ca2c352 | ||
![]() |
2eb5e289ce | ||
![]() |
40ce38254b | ||
![]() |
0ad2b05455 | ||
![]() |
c74d261f6a | ||
![]() |
68fe18fe36 | ||
![]() |
47313db2c7 | ||
![]() |
127129fbeb | ||
![]() |
f43a8d6f2e | ||
![]() |
7cde850d98 | ||
![]() |
1bcfc5b54d | ||
![]() |
7a8494da4d | ||
![]() |
65733863b1 | ||
![]() |
e62ecefcd7 | ||
![]() |
0aacebf783 | ||
![]() |
43b1700e91 | ||
![]() |
9b4625b4a5 | ||
![]() |
27998df6e4 | ||
![]() |
eb5eabf3c6 | ||
![]() |
76cee78408 | ||
![]() |
0ba35a6eb5 | ||
![]() |
6a58bd30ad | ||
![]() |
e71d055ef2 | ||
![]() |
cb2eff47cc | ||
![]() |
4696f9896b | ||
![]() |
424835880d | ||
![]() |
e0e0ee4a77 | ||
![]() |
5eca0ce554 | ||
![]() |
f5a06ac0dd | ||
![]() |
81ea8873e0 | ||
![]() |
63b4ccacde | ||
![]() |
ccc39e0e55 | ||
![]() |
d264df1504 | ||
![]() |
9b7bc16b3e | ||
![]() |
f7f51f4f73 | ||
![]() |
143ae1092c | ||
![]() |
6470a443ac | ||
![]() |
7795baf989 | ||
![]() |
5ab717c6be | ||
![]() |
fac265486a | ||
![]() |
707efff644 | ||
![]() |
15291fd659 | ||
![]() |
6535a20b21 | ||
![]() |
8c922dbffc | ||
![]() |
874f5fd2ca | ||
![]() |
50864b10dd | ||
![]() |
57a5df1fce | ||
![]() |
14828b15d8 | ||
![]() |
5f03e9e4cc | ||
![]() |
c2b82fa063 | ||
![]() |
40c4cfda75 | ||
![]() |
5c5ce6eedb | ||
![]() |
f9263ddb62 | ||
![]() |
2fd1074729 | ||
![]() |
2e379ad422 | ||
![]() |
c1cecb3e0e | ||
![]() |
b0d13bed72 | ||
![]() |
d23a0d230c | ||
![]() |
91b87f4e2c | ||
![]() |
a77c1f3ad1 | ||
![]() |
4c3cdaab0e | ||
![]() |
3e86c3d0d0 | ||
![]() |
5a40d3c6fe | ||
![]() |
f79c1e0bcc | ||
![]() |
8f14ff7210 | ||
![]() |
90732d6a2f | ||
![]() |
f179ff9da4 | ||
![]() |
90fd999220 | ||
![]() |
04afbdd938 | ||
![]() |
5d3ef3d338 | ||
![]() |
4477d083e8 | ||
![]() |
b7b3f54617 | ||
![]() |
5fc9f3f4da | ||
![]() |
c4b31f2f72 | ||
![]() |
6c6b0511a6 | ||
![]() |
6d20fc14ab | ||
![]() |
895c10600d | ||
![]() |
c024efa578 | ||
![]() |
0022588b02 | ||
![]() |
47ec3d9149 | ||
![]() |
811b82181d | ||
![]() |
32318ddbf6 | ||
![]() |
65a416fdae | ||
![]() |
58d1f98368 | ||
![]() |
4cd7bf7123 | ||
![]() |
d4dea13eee | ||
![]() |
507cdca757 | ||
![]() |
27bfb2d3b0 | ||
![]() |
43118a1ffd | ||
![]() |
729b305860 | ||
![]() |
72950d7872 | ||
![]() |
364ffe8f38 | ||
![]() |
84d822b497 | ||
![]() |
df99035c93 | ||
![]() |
63fc68cf83 | ||
![]() |
9c742fbf08 | ||
![]() |
9965c35d2f | ||
![]() |
0af567bc72 | ||
![]() |
0959a4e915 | ||
![]() |
83be71f622 | ||
![]() |
9c985b36b3 | ||
![]() |
4ef0e20b5c | ||
![]() |
d1cef044e5 | ||
![]() |
f1d4860c79 | ||
![]() |
f1d6dd7d36 | ||
![]() |
46ae7f16dd | ||
![]() |
5da441a001 | ||
![]() |
d495bfab51 | ||
![]() |
4b4f3e76cc | ||
![]() |
ab0e97c1a0 | ||
![]() |
381af329bd | ||
![]() |
4a0d17fc57 | ||
![]() |
e61f042547 | ||
![]() |
77815af5fb | ||
![]() |
e9cdb21164 | ||
![]() |
59bc467c50 | ||
![]() |
254dc62ca6 | ||
![]() |
253bde4e25 | ||
![]() |
ea9e852216 | ||
![]() |
89150e99bf | ||
![]() |
5fd05f3d20 | ||
![]() |
6c1a5f1a98 | ||
![]() |
7815a011af | ||
![]() |
efca0083bf | ||
![]() |
4c983b0e25 | ||
![]() |
d81f64ec06 | ||
![]() |
5735313392 | ||
![]() |
259b2fe429 | ||
![]() |
bb739a55a5 | ||
![]() |
7436b75566 | ||
![]() |
573ac882f5 | ||
![]() |
7f70a886d5 | ||
![]() |
4a1c0c2971 | ||
![]() |
ad37ccd76d | ||
![]() |
d3a4b17d59 | ||
![]() |
4233d73569 | ||
![]() |
6d9a0162b2 | ||
![]() |
72f89de994 | ||
![]() |
bf01799d57 | ||
![]() |
6b63d3855b | ||
![]() |
f0e0e780c5 | ||
![]() |
646803b93e | ||
![]() |
3026b59af4 | ||
![]() |
5adee00ca1 | ||
![]() |
47e887dac5 | ||
![]() |
70395a035c | ||
![]() |
2f63dcb3b5 | ||
![]() |
468ea09965 | ||
![]() |
b6a94d33b8 | ||
![]() |
40c89a8a38 | ||
![]() |
92a61902b5 | ||
![]() |
23ee01b1ce | ||
![]() |
fc727e0472 | ||
![]() |
9427c70b10 | ||
![]() |
cba71ed8e0 | ||
![]() |
728778bdf4 | ||
![]() |
30a92e25c1 | ||
![]() |
4862eb5e84 | ||
![]() |
42fd62ecfd | ||
![]() |
67437f7b9c | ||
![]() |
6c961dfad9 | ||
![]() |
b0b5f9e0a1 | ||
![]() |
69df7f8ef6 | ||
![]() |
0bb0fc5a19 | ||
![]() |
be15e86458 | ||
![]() |
24eff6b02b | ||
![]() |
ddb96829ca | ||
![]() |
4290f38e81 | ||
![]() |
ee4a5d53ad | ||
![]() |
1f4d2e76d7 | ||
![]() |
9816efb816 | ||
![]() |
8da1521508 | ||
![]() |
a7846925b1 | ||
![]() |
d678bd71e8 | ||
![]() |
67754efd36 | ||
![]() |
80e0fc21cc | ||
![]() |
1025f6ccb5 | ||
![]() |
ede06f4fd4 | ||
![]() |
6dd0de0201 | ||
![]() |
7f01ead374 | ||
![]() |
cba507258d | ||
![]() |
ae93999f6a | ||
![]() |
1ff7a89a35 | ||
![]() |
31cd32406c | ||
![]() |
e5f750dcbe | ||
![]() |
59ecff8701 | ||
![]() |
80e91cde70 | ||
![]() |
b1c2c79d80 | ||
![]() |
5b2576ace4 | ||
![]() |
da9f370924 | ||
![]() |
e56daf07d4 | ||
![]() |
9e3caa57ec | ||
![]() |
4fd7b9ef1f | ||
![]() |
12235cc853 | ||
![]() |
56e4264394 | ||
![]() |
baf8203b80 | ||
![]() |
41d966895f | ||
![]() |
551792274f | ||
![]() |
c7abdb61e8 | ||
![]() |
72ebe7df58 | ||
![]() |
97f3c214e8 | ||
![]() |
47842bac1c | ||
![]() |
ede498fa52 | ||
![]() |
c8a06416e7 | ||
![]() |
5fea7f2bc4 | ||
![]() |
15420137fa | ||
![]() |
73791e0e50 | ||
![]() |
7af0f12e6b | ||
![]() |
895f9c911b | ||
![]() |
204f47265b | ||
![]() |
b240b4821a | ||
![]() |
249f6e4f27 | ||
![]() |
32facd2877 | ||
![]() |
fd3cb6e2ca | ||
![]() |
1df6d857e5 | ||
![]() |
3b9c2fd4d2 | ||
![]() |
baa130e646 | ||
![]() |
c3ec40189f | ||
![]() |
686ae5b213 | ||
![]() |
5c19a8bb70 | ||
![]() |
efa7b7b0b5 | ||
![]() |
e466c31bb3 | ||
![]() |
942acf5940 | ||
![]() |
b38d8d8640 | ||
![]() |
c4c8a96f25 | ||
![]() |
65377d881c | ||
![]() |
b847e0c65e | ||
![]() |
6ab884a95c | ||
![]() |
4b17a485ae | ||
![]() |
e5a4715161 | ||
![]() |
53b7b14467 | ||
![]() |
5eeb012557 | ||
![]() |
cf9884aaba | ||
![]() |
d811cab57e | ||
![]() |
d5a3443076 | ||
![]() |
bd11d3a34f | ||
![]() |
5f6a202d65 | ||
![]() |
6db3f7023f | ||
![]() |
8a64898798 | ||
![]() |
6ad14d63d6 | ||
![]() |
a26150ca40 | ||
![]() |
57c9066f81 | ||
![]() |
fe3c3b8946 | ||
![]() |
76686c22fc | ||
![]() |
bba4057616 | ||
![]() |
10a1f34164 | ||
![]() |
4516a5def5 | ||
![]() |
4ef4af452a | ||
![]() |
8f1e95a0ce | ||
![]() |
824aea0c7b | ||
![]() |
7d54f0e336 | ||
![]() |
961b47239b | ||
![]() |
248f19a550 | ||
![]() |
29e6529884 | ||
![]() |
cb4f822a19 | ||
![]() |
2159fefc87 | ||
![]() |
d341bf14ff | ||
![]() |
c793ac9c6c | ||
![]() |
289589654b | ||
![]() |
8cb9c9faf9 | ||
![]() |
1c0069e95e | ||
![]() |
8f23642e7d | ||
![]() |
b59758379e | ||
![]() |
d91267ee91 | ||
![]() |
6196bc7b2e | ||
![]() |
adfe5c123c | ||
![]() |
573726d0b2 | ||
![]() |
5cb95b6e55 | ||
![]() |
4ce79955f8 | ||
![]() |
3d320b4e61 | ||
![]() |
420feb3a52 | ||
![]() |
4d425cf7b8 | ||
![]() |
f716300152 | ||
![]() |
fea625e443 | ||
![]() |
068fdbd3f9 | ||
![]() |
fd2cbc13ff | ||
![]() |
6a70b9c4b4 | ||
![]() |
4ee7d16d3e | ||
![]() |
6fd25da80d | ||
![]() |
2fb286cd43 | ||
![]() |
3a75b2571a | ||
![]() |
66fe821b04 | ||
![]() |
ba478c6cbb | ||
![]() |
7b1145c75e | ||
![]() |
b45630080b | ||
![]() |
170ddbc76f | ||
![]() |
91b364f531 | ||
![]() |
aadcc85e73 | ||
![]() |
548b1ea7ec | ||
![]() |
463696e6a8 | ||
![]() |
66f7ae3773 | ||
![]() |
cc2b836646 | ||
![]() |
816a4c1887 | ||
![]() |
604da64f52 | ||
![]() |
247edc89f0 | ||
![]() |
6a1f5fb4cd | ||
![]() |
01c11f9fa0 | ||
![]() |
9434851c54 | ||
![]() |
a331e4b49c | ||
![]() |
772f5cb1a8 | ||
![]() |
0fa9d71da8 | ||
![]() |
3872c3c49b | ||
![]() |
018b53db1b | ||
![]() |
33ed2c8851 | ||
![]() |
c75e30fd28 | ||
![]() |
7cc940a16c | ||
![]() |
ba853be00d | ||
![]() |
a720ed6a77 | ||
![]() |
d84ca511d4 | ||
![]() |
95fe803bf6 | ||
![]() |
87c364a104 | ||
![]() |
7233695824 | ||
![]() |
3d3300ac32 | ||
![]() |
ef7775b658 | ||
![]() |
a8776603c3 | ||
![]() |
ee92ab1136 | ||
![]() |
83c88ca472 | ||
![]() |
6f22297158 | ||
![]() |
df87599f1b | ||
![]() |
367b5e73cb | ||
![]() |
d6cbea97f9 | ||
![]() |
e43ab23a45 | ||
![]() |
706b1f4622 | ||
![]() |
5b75321a31 | ||
![]() |
2f2b5b90ea | ||
![]() |
cf3dedf4bb | ||
![]() |
d874145f52 | ||
![]() |
800f4deb90 | ||
![]() |
c22af0a782 | ||
![]() |
8465b8cfca | ||
![]() |
6ae65e0ab4 | ||
![]() |
6a64bf6fc1 | ||
![]() |
f038bb90bb | ||
![]() |
a5ba14e446 | ||
![]() |
70f657beff | ||
![]() |
b1085c36ff | ||
![]() |
1896aa7da1 | ||
![]() |
087856c535 | ||
![]() |
27f1364caa | ||
![]() |
bec5365ac9 | ||
![]() |
0db14d6f74 | ||
![]() |
ccb44e1bd1 | ||
![]() |
8c3db627e4 | ||
![]() |
56204f8497 | ||
![]() |
fc75e88cb7 | ||
![]() |
d2719b5309 | ||
![]() |
e5254abfcd | ||
![]() |
96b8d35a00 | ||
![]() |
035b0a449b | ||
![]() |
6b20177b09 | ||
![]() |
15861ea41a | ||
![]() |
d836756e19 | ||
![]() |
191d9a7b2b | ||
![]() |
0394cd7631 | ||
![]() |
c1ddff4ee5 | ||
![]() |
55cc428cd3 | ||
![]() |
39505c9764 | ||
![]() |
887a2f9be1 | ||
![]() |
1328fa9e5e | ||
![]() |
513830f319 | ||
![]() |
440abcda7c | ||
![]() |
6f3fdbecea | ||
![]() |
3a46cc33ee | ||
![]() |
ae3eb84e01 | ||
![]() |
7a73e18596 | ||
![]() |
c89779e8fc | ||
![]() |
5ca8d10d04 | ||
![]() |
1ce6aef57c | ||
![]() |
49b23aafa3 | ||
![]() |
f888647b12 | ||
![]() |
065ff6eaf5 | ||
![]() |
bf976fe188 | ||
![]() |
5ce73574c8 | ||
![]() |
5d94a983d2 | ||
![]() |
25366af4bb | ||
![]() |
f397c5472c | ||
![]() |
6273eb0061 | ||
![]() |
734fd7c0fc | ||
![]() |
8797a58efc | ||
![]() |
8da85d3609 | ||
![]() |
127d30918d | ||
![]() |
3b553f6455 | ||
![]() |
6d934da5dd | ||
![]() |
aa3d91a338 | ||
![]() |
d64818b46c | ||
![]() |
99a18516b2 | ||
![]() |
30b0a30146 | ||
![]() |
cb10617979 | ||
![]() |
265432f2a5 | ||
![]() |
a13e9f23b1 | ||
![]() |
65b37f61ca | ||
![]() |
7751755399 | ||
![]() |
14e2ad7bc4 | ||
![]() |
dfc23a2b38 | ||
![]() |
d2fc840293 | ||
![]() |
37fe6fb9c3 | ||
![]() |
a21ec76997 | ||
![]() |
501d8d9683 | ||
![]() |
8562ca9a77 | ||
![]() |
29641e5d66 | ||
![]() |
ee7308be2d | ||
![]() |
ef4009e94f | ||
![]() |
27d2ae6976 | ||
![]() |
0f9675f9d6 | ||
![]() |
bac4a63cc8 | ||
![]() |
0453787d38 | ||
![]() |
afc3e41f13 | ||
![]() |
86d6316cc9 | ||
![]() |
7b2c1f82f5 | ||
![]() |
e2a932d744 | ||
![]() |
b978994525 | ||
![]() |
6da237dd9e | ||
![]() |
50c1978d36 | ||
![]() |
fdb310c497 | ||
![]() |
ce121a261d | ||
![]() |
ebdfd4241a | ||
![]() |
9cbb1c5726 | ||
![]() |
85dabccbe7 | ||
![]() |
a9a8189d4b | ||
![]() |
30579112d2 | ||
![]() |
ccfd009c1a | ||
![]() |
044a939623 | ||
![]() |
203bc162cd | ||
![]() |
31f03ef1d3 | ||
![]() |
4d3552dc64 | ||
![]() |
ea8a52404f | ||
![]() |
0ae9aecdef | ||
![]() |
4de4789605 | ||
![]() |
950bb46827 | ||
![]() |
44936dc5f0 | ||
![]() |
1140a878b4 | ||
![]() |
efb49af7ac | ||
![]() |
b5a8106a6a | ||
![]() |
0f80eee54e | ||
![]() |
0e237fa459 | ||
![]() |
702b985ceb | ||
![]() |
7d87bcbb98 | ||
![]() |
340521aa0d | ||
![]() |
7bc557a999 | ||
![]() |
dfa7cdf47e | ||
![]() |
0d78e58d77 | ||
![]() |
58df3d5767 | ||
![]() |
4e4d6e806c | ||
![]() |
6ff99945f3 | ||
![]() |
b7f1b9f8ad | ||
![]() |
08a44cf468 | ||
![]() |
a1162d6d5a | ||
![]() |
1c81d88013 | ||
![]() |
1e4ec7e29e | ||
![]() |
2c4e34dd0c | ||
![]() |
cb308fae7b | ||
![]() |
3f03d51b24 | ||
![]() |
831db6ab87 | ||
![]() |
43fdf634f2 | ||
![]() |
f07a6b4586 | ||
![]() |
2fcf484229 | ||
![]() |
8bf4241b16 | ||
![]() |
56bd966c02 | ||
![]() |
416101d557 | ||
![]() |
c330cca2c9 | ||
![]() |
7e88085377 | ||
![]() |
5e669534f2 | ||
![]() |
98b147b622 | ||
![]() |
df6c59bc4f | ||
![]() |
6e48da41e5 | ||
![]() |
5c8a01a6e8 | ||
![]() |
3d0a52c25f | ||
![]() |
43c729568b | ||
![]() |
62caeed283 | ||
![]() |
12836d4c68 | ||
![]() |
b48e67d714 | ||
![]() |
f91f4d71bb | ||
![]() |
0a1f264c71 | ||
![]() |
64d61ae2fa | ||
![]() |
5f0e800f6e | ||
![]() |
8b2965d55b | ||
![]() |
ed478a1d73 | ||
![]() |
13e91d8c95 | ||
![]() |
6ac90181cb | ||
![]() |
d6c3471909 | ||
![]() |
5b56fad9c7 | ||
![]() |
ed0b1fe115 | ||
![]() |
4211153527 | ||
![]() |
2f85461109 | ||
![]() |
3fa7dcb0cb | ||
![]() |
857fe3a55c | ||
![]() |
dd19ea46fe | ||
![]() |
21740a9d87 | ||
![]() |
658fb2f208 | ||
![]() |
252d4cb513 | ||
![]() |
5aed41223b | ||
![]() |
45dfbf3747 | ||
![]() |
e4fe5bebab | ||
![]() |
04519ee623 | ||
![]() |
6c8f010f7a | ||
![]() |
ed84cf26e7 | ||
![]() |
1bc961f0c0 | ||
![]() |
77d745381f | ||
![]() |
7082cb9c36 | ||
![]() |
34e84cc757 | ||
![]() |
9246411610 | ||
![]() |
8330b3598c | ||
![]() |
1d002149dc | ||
![]() |
8d6071e977 | ||
![]() |
7d67766508 | ||
![]() |
887dd122fe | ||
![]() |
a1293c77b9 | ||
![]() |
ee9a73aa95 | ||
![]() |
9df332b614 | ||
![]() |
d13e86a892 | ||
![]() |
69d7f8c180 | ||
![]() |
1ba89ddd09 | ||
![]() |
0c40a28ad3 | ||
![]() |
2b7424c42a | ||
![]() |
a9f1766d1c | ||
![]() |
fca8576d80 | ||
![]() |
05f59e7d5e | ||
![]() |
c9511680b3 | ||
![]() |
0ed001c56e | ||
![]() |
1e5a418191 | ||
![]() |
e05735bc0f | ||
![]() |
7621e10840 | ||
![]() |
d90080f325 | ||
![]() |
0c676b90f2 | ||
![]() |
c2d8bda83c | ||
![]() |
302ebf737e | ||
![]() |
816c95a4ae | ||
![]() |
40106f6fcc | ||
![]() |
61143b3ad1 | ||
![]() |
9b64eebd10 | ||
![]() |
731418349f | ||
![]() |
5306d58991 | ||
![]() |
7728920670 | ||
![]() |
f555bb95ae | ||
![]() |
bcee17c3ac | ||
![]() |
dcb17f2f21 | ||
![]() |
37b3a30619 | ||
![]() |
7bc16edfe2 | ||
![]() |
b0fed61a01 | ||
![]() |
40f3e8e45a | ||
![]() |
4a471138b2 | ||
![]() |
656b4708ac | ||
![]() |
7702f5012b | ||
![]() |
ffe96c8fff | ||
![]() |
0024c2aae4 | ||
![]() |
ed39e9e15f | ||
![]() |
fd8c40fee7 | ||
![]() |
0e76441684 | ||
![]() |
d2c34fb9c7 | ||
![]() |
d09ea8408c | ||
![]() |
e8a1fde1c7 | ||
![]() |
5ef6f2697e | ||
![]() |
80b3fa75a5 | ||
![]() |
9993381cda | ||
![]() |
9fa3f91e8a | ||
![]() |
fe435f6653 | ||
![]() |
5696c02ac3 | ||
![]() |
019dfeb3ee | ||
![]() |
e35723e7af | ||
![]() |
1d50d017ac | ||
![]() |
9e5d1ad952 | ||
![]() |
9faaf4b1e4 | ||
![]() |
ac229ce004 | ||
![]() |
41540a3a5f | ||
![]() |
968614a289 | ||
![]() |
2f68f236bb | ||
![]() |
00903bd90c | ||
![]() |
96d7114fa7 | ||
![]() |
431d4fd8e4 | ||
![]() |
0d3ab3aaf7 | ||
![]() |
138f38d1f3 | ||
![]() |
222fb48378 | ||
![]() |
5718f50c4f | ||
![]() |
d8e0ef257e | ||
![]() |
866c8fc848 | ||
![]() |
758631c53f | ||
![]() |
8711a206a0 | ||
![]() |
44ec3a3d9c | ||
![]() |
883a6b26a4 | ||
![]() |
b9e1ed7d7e | ||
![]() |
c51fa60172 | ||
![]() |
e300ee0c92 | ||
![]() |
ba3c8308b3 | ||
![]() |
63b11514c9 | ||
![]() |
49d2084d8a | ||
![]() |
c36fe577de | ||
![]() |
28c79f1abb | ||
![]() |
a1f07417da | ||
![]() |
611b4fe31b | ||
![]() |
697670ef97 | ||
![]() |
ee487529fe | ||
![]() |
2129cda38d | ||
![]() |
afb63f763a | ||
![]() |
a186d6fae2 | ||
![]() |
d17de45791 | ||
![]() |
18980bbbe3 | ||
![]() |
32c9369ba1 | ||
![]() |
bdc247ce49 | ||
![]() |
85f46424a8 | ||
![]() |
d198a89f22 | ||
![]() |
82730ab491 | ||
![]() |
c78d54e71e | ||
![]() |
08d96a1b76 | ||
![]() |
b2a744e880 | ||
![]() |
3f421a4f64 | ||
![]() |
2624aec758 | ||
![]() |
f3a18c26f4 | ||
![]() |
47ea60372f | ||
![]() |
8efba4c57f | ||
![]() |
060dcd71cd | ||
![]() |
fd6e727299 | ||
![]() |
c4adb20eff | ||
![]() |
e70af00321 | ||
![]() |
9ebe16d823 | ||
![]() |
fd05da96d5 | ||
![]() |
5f44ab5abc | ||
![]() |
ffc82c17ba | ||
![]() |
b33e25b1f7 | ||
![]() |
55c50e3ac2 | ||
![]() |
211a88129e | ||
![]() |
2a629b81ce | ||
![]() |
2efb99192a | ||
![]() |
0a28ccf62f | ||
![]() |
48b042bfb0 | ||
![]() |
da08eec91f | ||
![]() |
684f91b2e3 | ||
![]() |
689579c7f2 | ||
![]() |
4a549ccd33 | ||
![]() |
32f0a2fdbc | ||
![]() |
abee54ebe3 | ||
![]() |
58ae14c364 | ||
![]() |
34104f0d42 | ||
![]() |
dabcdbad00 | ||
![]() |
4c314130f7 | ||
![]() |
53a71384b0 | ||
![]() |
294a5ebec6 | ||
![]() |
6a4b31b354 | ||
![]() |
76c9715748 | ||
![]() |
e657ca7496 | ||
![]() |
ddf01eef14 | ||
![]() |
3d093f2c08 | ||
![]() |
004e3134fc | ||
![]() |
85ee74f2d8 | ||
![]() |
406ec17050 | ||
![]() |
7f85180264 | ||
![]() |
ad29fc23a6 | ||
![]() |
b9690de9ab | ||
![]() |
d4deefc81c | ||
![]() |
32780472db | ||
![]() |
b1f906461e | ||
![]() |
7e449d661b | ||
![]() |
24b3a03000 | ||
![]() |
cd28fbf563 | ||
![]() |
d7b2906977 | ||
![]() |
3180b38797 | ||
![]() |
fd59def1bd | ||
![]() |
8cd1dd71e8 | ||
![]() |
48cfb64416 | ||
![]() |
adb76eafaf | ||
![]() |
4e2efebaa7 | ||
![]() |
eb6153c5aa | ||
![]() |
9c3b16c879 | ||
![]() |
ba637c8582 | ||
![]() |
46ea86a6d2 | ||
![]() |
9d148c08ce | ||
![]() |
ac459f7b05 | ||
![]() |
35a4779cc0 | ||
![]() |
ffa44f51cd | ||
![]() |
682a9d2a09 | ||
![]() |
4c6a02aee7 | ||
![]() |
87a18eae2d | ||
![]() |
269673ce05 | ||
![]() |
d9e06958dc | ||
![]() |
063bfc245c | ||
![]() |
21c501de28 | ||
![]() |
d50d1bd2ea | ||
![]() |
e4aa31a62d | ||
![]() |
fdf58bed6a | ||
![]() |
a54784da11 | ||
![]() |
a40e4fe3bc | ||
![]() |
ea30fbf14f | ||
![]() |
d22d9a023c | ||
![]() |
ddcc0883eb | ||
![]() |
047a21eb48 | ||
![]() |
439f06ccda | ||
![]() |
05866da04b | ||
![]() |
dcd350a30c | ||
![]() |
107cc2ca20 | ||
![]() |
f872221c49 | ||
![]() |
2faa425caf | ||
![]() |
94be8781e9 | ||
![]() |
47189342e4 | ||
![]() |
fafe259e53 | ||
![]() |
41fe607157 | ||
![]() |
062008269b | ||
![]() |
29e1b51164 | ||
![]() |
d2a8bc5c4c | ||
![]() |
7414b3d23a | ||
![]() |
a0a781a3d5 | ||
![]() |
d9e6f6e07c | ||
![]() |
9167357908 | ||
![]() |
3b541b22e8 | ||
![]() |
71d5af233d | ||
![]() |
b0ed06003b | ||
![]() |
91f7c4e685 | ||
![]() |
5a4cb5fe4a | ||
![]() |
cc74be9ccc | ||
![]() |
68a9dd7e05 | ||
![]() |
682cf33c78 | ||
![]() |
763b780aa4 | ||
![]() |
23d8305027 | ||
![]() |
1950f805b3 | ||
![]() |
d275a75517 | ||
![]() |
1576e07011 | ||
![]() |
24313fe001 | ||
![]() |
51dc40ae73 | ||
![]() |
ab04817bea | ||
![]() |
8dde7fa043 | ||
![]() |
edfebe18a2 | ||
![]() |
0b07c3bd8f | ||
![]() |
1483f450ad | ||
![]() |
600c13204e | ||
![]() |
2073279473 | ||
![]() |
d126ecfa4d | ||
![]() |
944aaf5438 | ||
![]() |
52f17a9ba6 | ||
![]() |
44600961d8 | ||
![]() |
d60b532b8f | ||
![]() |
55584a6a87 | ||
![]() |
7c02a8b414 | ||
![]() |
18d105b4f8 | ||
![]() |
f0d49a1382 | ||
![]() |
277bf0eb83 | ||
![]() |
3b5d55c428 | ||
![]() |
313f2886d7 | ||
![]() |
868fd4155a | ||
![]() |
4eeb5642f5 | ||
![]() |
532a3d955c | ||
![]() |
53309f017f | ||
![]() |
5651a03b14 | ||
![]() |
07faba3983 | ||
![]() |
d9547e87af | ||
![]() |
d672455ad8 | ||
![]() |
96a572b7a6 | ||
![]() |
2a7bb27a78 | ||
![]() |
3f73cd5bfc | ||
![]() |
9c427f202d | ||
![]() |
bc02dc30b1 | ||
![]() |
8080b7a119 | ||
![]() |
b0fa0f2319 | ||
![]() |
6c5f9bbabb | ||
![]() |
7dedb99dae | ||
![]() |
b581e42216 | ||
![]() |
ede3bd1391 | ||
![]() |
339e96b63c | ||
![]() |
f31073a341 | ||
![]() |
2fa78f7820 | ||
![]() |
77b85b9e93 | ||
![]() |
29ce2515ee | ||
![]() |
d57c237980 | ||
![]() |
37ade0c6b2 | ||
![]() |
28a2479f24 | ||
![]() |
be2013975c | ||
![]() |
6e688a5b82 | ||
![]() |
bfbdfe857f | ||
![]() |
0d19957d4b | ||
![]() |
05d69c0882 | ||
![]() |
a5edbcf9ef | ||
![]() |
2104e65462 | ||
![]() |
c0882e74e2 | ||
![]() |
ced6a61869 | ||
![]() |
6c3b1db4dd | ||
![]() |
25a0845efd | ||
![]() |
8d62493774 | ||
![]() |
eca1289ce2 | ||
![]() |
a6bd118f5e | ||
![]() |
a73ff4ffa6 | ||
![]() |
14d04ff8d2 | ||
![]() |
d7cefabe98 | ||
![]() |
f95fd4ced2 | ||
![]() |
227f7b6946 | ||
![]() |
1a0b954397 | ||
![]() |
87ad2ce1d6 | ||
![]() |
63cd16e29e | ||
![]() |
66fc9e9111 | ||
![]() |
43bee38b3c | ||
![]() |
18ebb58dc9 | ||
![]() |
099b84a66d | ||
![]() |
3b22d7131d | ||
![]() |
11f9616411 | ||
![]() |
c926e0242a | ||
![]() |
9ac19417e7 | ||
![]() |
795dbc16d2 | ||
![]() |
29a7737829 | ||
![]() |
10b53bdfd0 | ||
![]() |
aeb10d3407 | ||
![]() |
3e0c3c0bb2 | ||
![]() |
cde867c9c6 | ||
![]() |
ff8eb7fbce | ||
![]() |
3766d8687f | ||
![]() |
8f08201633 | ||
![]() |
893dcd9f28 | ||
![]() |
79059b9aa7 | ||
![]() |
ddf386c4d4 | ||
![]() |
861b2efb1d | ||
![]() |
9575b0fe32 | ||
![]() |
6c7290bd34 | ||
![]() |
19032fe433 | ||
![]() |
8fce8d4677 | ||
![]() |
2333ea9dc7 | ||
![]() |
937cdaccad | ||
![]() |
54916fec2e | ||
![]() |
03e159f67c | ||
![]() |
482ef6313d | ||
![]() |
43685baff3 | ||
![]() |
f6a2cc74e8 | ||
![]() |
9f1436a865 | ||
![]() |
020df6c8ea | ||
![]() |
08046cb83f | ||
![]() |
f06edebbd8 | ||
![]() |
c808011b75 | ||
![]() |
da60fc8150 | ||
![]() |
04a0d01b21 | ||
![]() |
02a066f8f3 | ||
![]() |
7834d369c6 | ||
![]() |
5e841531be | ||
![]() |
5355f2b027 | ||
![]() |
e1533202fc | ||
![]() |
0b949a14c0 | ||
![]() |
5175206179 | ||
![]() |
0af0dffeda | ||
![]() |
74a1b36005 | ||
![]() |
8884a4dfdf | ||
![]() |
19f73f5782 | ||
![]() |
8e95310602 | ||
![]() |
fe31b8d160 | ||
![]() |
6515d1ae85 | ||
![]() |
a8ec9f29cd | ||
![]() |
bab53838ec | ||
![]() |
bf2e98527c | ||
![]() |
e1e11de2b5 | ||
![]() |
4fda8f3348 | ||
![]() |
8427d58337 | ||
![]() |
385076cf28 | ||
![]() |
b9725437d9 | ||
![]() |
72616def4f | ||
![]() |
6c972bd08a | ||
![]() |
a71a991084 | ||
![]() |
0927f9d477 | ||
![]() |
a68b858733 | ||
![]() |
08199f09b6 | ||
![]() |
5f8151282b | ||
![]() |
efde4828d6 | ||
![]() |
016c168404 | ||
![]() |
741ccfa280 | ||
![]() |
31b74515b6 | ||
![]() |
b9a2f82ce0 | ||
![]() |
3c59d9b787 | ||
![]() |
f919ec0d57 | ||
![]() |
9c380f5aac | ||
![]() |
fc5def157d | ||
![]() |
d5eff386db | ||
![]() |
864e421cd3 | ||
![]() |
2c9825193b | ||
![]() |
98f3e99e2e | ||
![]() |
961354aa8a | ||
![]() |
fa27c895ed | ||
![]() |
c31b6e63f5 | ||
![]() |
ef924e896b | ||
![]() |
5b1619cba3 | ||
![]() |
a3a9949ebc | ||
![]() |
ada8493838 | ||
![]() |
cc06d528cb | ||
![]() |
0926266663 | ||
![]() |
59008ea765 | ||
![]() |
01cd4c7546 | ||
![]() |
8d606b9f34 | ||
![]() |
86376c8c5f | ||
![]() |
48220ceeb8 | ||
![]() |
f94da1cf27 | ||
![]() |
6d786f8987 | ||
![]() |
8d433ac0de | ||
![]() |
4b42c97d0a | ||
![]() |
d8637ff4b1 | ||
![]() |
342e9c9734 | ||
![]() |
af1d084391 | ||
![]() |
e6961d5287 | ||
![]() |
7562bdb218 | ||
![]() |
cb94e15ba7 | ||
![]() |
c8b0674b93 | ||
![]() |
4fa1779ef3 | ||
![]() |
db23a5cf37 | ||
![]() |
7cc3c73994 | ||
![]() |
014859185c | ||
![]() |
6dae900d74 | ||
![]() |
a4187b2b70 | ||
![]() |
556e4f7430 | ||
![]() |
02c2d388ed | ||
![]() |
c0692f03a3 | ||
![]() |
a2342d98d3 | ||
![]() |
24c20e38ff | ||
![]() |
cd12c1b300 | ||
![]() |
a008dff368 | ||
![]() |
769356733a | ||
![]() |
f5be2ac4bb | ||
![]() |
2824fcb497 | ||
![]() |
2f42eab217 | ||
![]() |
338324d5b6 | ||
![]() |
0628d10076 | ||
![]() |
bc4017d54a | ||
![]() |
96dc7583bf | ||
![]() |
deb9698ff6 | ||
![]() |
654c7fd2ac | ||
![]() |
24e34e95cd | ||
![]() |
d093c004fb | ||
![]() |
ceb9426fd4 | ||
![]() |
e4f2016678 | ||
![]() |
40842689fd | ||
![]() |
59f955e08b | ||
![]() |
91e6503503 | ||
![]() |
c7c98c623d | ||
![]() |
80aa847457 | ||
![]() |
f1c981338c | ||
![]() |
d4225a459e | ||
![]() |
75ae37d90f | ||
![]() |
2159115679 | ||
![]() |
0384de9a3c | ||
![]() |
ae2e1fc381 | ||
![]() |
d45993c905 | ||
![]() |
4e6c7b01b6 | ||
![]() |
775ce56d2e | ||
![]() |
d41c466f6e | ||
![]() |
387135ffa5 | ||
![]() |
64b176103e | ||
![]() |
7f88c7d70c | ||
![]() |
1a89ad95e0 | ||
![]() |
376f991db5 | ||
![]() |
623893b528 | ||
![]() |
890f6f35b5 | ||
![]() |
ab4af350dd | ||
![]() |
95bfc4be9a | ||
![]() |
95d9c8fa2b | ||
![]() |
83dd5f51cd | ||
![]() |
5d1dddfac8 | ||
![]() |
50ba88231f | ||
![]() |
221cf12184 | ||
![]() |
681b769a71 | ||
![]() |
27517c15ca | ||
![]() |
56f566e13a | ||
![]() |
6131a40c31 | ||
![]() |
040e652e6a | ||
![]() |
caf0e1d15b | ||
![]() |
9dd8b7cd88 | ||
![]() |
8702a739b0 | ||
![]() |
8104851c08 | ||
![]() |
0e03c48beb | ||
![]() |
3fbf24a1c2 | ||
![]() |
64a966c9a5 | ||
![]() |
18a128b917 | ||
![]() |
cfd263da90 | ||
![]() |
0f4a7f0a04 | ||
![]() |
ae5dd62105 | ||
![]() |
b73ff095e6 | ||
![]() |
4503be110a | ||
![]() |
7fef27e6de | ||
![]() |
d8eabd66ea | ||
![]() |
a62e5f32b8 | ||
![]() |
24fe5bb838 | ||
![]() |
5217acc471 | ||
![]() |
f96d97a637 | ||
![]() |
de38f46a53 | ||
![]() |
8f94607409 | ||
![]() |
88ee3694f7 | ||
![]() |
584307dc54 | ||
![]() |
62fd32afbc | ||
![]() |
bfcfcde71a | ||
![]() |
6ce0945aeb | ||
![]() |
f701479d77 | ||
![]() |
4e93d92e46 | ||
![]() |
ebcdcc6a1e | ||
![]() |
b5cd713e16 | ||
![]() |
0adb8cea91 | ||
![]() |
bce79189e5 | ||
![]() |
8927e0185b | ||
![]() |
df95fad9be | ||
![]() |
e96809a08e | ||
![]() |
7ebc1351fe | ||
![]() |
ee31249d65 | ||
![]() |
a9d6e7f402 | ||
![]() |
296be9135a | ||
![]() |
f24640dec2 | ||
![]() |
64d6e6eded | ||
![]() |
587cd80055 | ||
![]() |
527b7bee3f | ||
![]() |
e1f52d706f | ||
![]() |
2e2e69f07c | ||
![]() |
6a3e4f0857 | ||
![]() |
ff3bdd7f5a | ||
![]() |
1e185d1502 | ||
![]() |
8f9aab407d | ||
![]() |
4cf0ce1b06 | ||
![]() |
8430aa75da | ||
![]() |
f5a47de1d6 | ||
![]() |
1fe322bbac | ||
![]() |
f6da608154 | ||
![]() |
22fc16f4a3 | ||
![]() |
def85a3d37 | ||
![]() |
f638079361 | ||
![]() |
e87ab91d0e | ||
![]() |
fb56602081 | ||
![]() |
2c1d9f2d7b | ||
![]() |
49385959b8 | ||
![]() |
3511c86abd | ||
![]() |
9908580409 | ||
![]() |
5bad23d7be | ||
![]() |
8cde2cd4b2 | ||
![]() |
74db555f78 | ||
![]() |
a1a415a5d1 | ||
![]() |
49053b6ad2 | ||
![]() |
fbfdd95958 | ||
![]() |
2c065da987 | ||
![]() |
6c7281ae88 | ||
![]() |
4bb0da397a | ||
![]() |
6a355b8dff | ||
![]() |
aa1fb63714 | ||
![]() |
c9ce69c1c1 | ||
![]() |
06ee41226d | ||
![]() |
bf634eee66 | ||
![]() |
e606ae5097 | ||
![]() |
ecc40d022d | ||
![]() |
262e8ee999 | ||
![]() |
141315cf42 | ||
![]() |
6fa0d00b8f | ||
![]() |
47339c84b3 | ||
![]() |
692a5081c7 | ||
![]() |
28c3f8d614 | ||
![]() |
fb5d35e43e | ||
![]() |
a4bff61e5b | ||
![]() |
2c4bbf8a00 | ||
![]() |
d2ec38d5fd | ||
![]() |
517e037724 | ||
![]() |
0051d9f76e | ||
![]() |
c0915a3dee | ||
![]() |
4363d4c9ed | ||
![]() |
d7095f7ee1 | ||
![]() |
ebc5f1a01d | ||
![]() |
d6ad41ab3a | ||
![]() |
9c2e55407f | ||
![]() |
7c70659212 | ||
![]() |
5822273c8d | ||
![]() |
001cd83ef8 | ||
![]() |
b48c290e9c | ||
![]() |
327f00e312 | ||
![]() |
b1ae8d1332 | ||
![]() |
38cb8201a1 | ||
![]() |
e3478edeeb | ||
![]() |
69f1931f4f | ||
![]() |
6eb8908a16 | ||
![]() |
88dcd889fa | ||
![]() |
9cd6235947 | ||
![]() |
bcb2853150 | ||
![]() |
ad241f12a3 | ||
![]() |
b29627c92b | ||
![]() |
8518d583d9 | ||
![]() |
81dee38e4a | ||
![]() |
fa6cc9692e | ||
![]() |
c3a92d659e | ||
![]() |
ffed65533b | ||
![]() |
5a393569f0 | ||
![]() |
6cf20a93d0 | ||
![]() |
a2b5fb8374 | ||
![]() |
f4f9200fba | ||
![]() |
52640f08d2 | ||
![]() |
bbb5783b4f | ||
![]() |
cde937a9eb | ||
![]() |
a4ee4e9b17 | ||
![]() |
34a06435cf | ||
![]() |
fad6e7284a | ||
![]() |
29f73b2dbb | ||
![]() |
968725f09f | ||
![]() |
42064df3e0 | ||
![]() |
c980a52244 | ||
![]() |
38f279fd2a | ||
![]() |
1170827f3d | ||
![]() |
838631b057 | ||
![]() |
89476e4479 | ||
![]() |
1b61765df8 | ||
![]() |
40da245d8d | ||
![]() |
1238d8b994 | ||
![]() |
460d202eb0 | ||
![]() |
248e4e5eb9 | ||
![]() |
08299fb808 | ||
![]() |
c06f6145a1 | ||
![]() |
6101f42ae3 | ||
![]() |
9ffd9027fa | ||
![]() |
10995788d1 | ||
![]() |
98bc51a3ec | ||
![]() |
cc9f9b6e8b | ||
![]() |
d7b3e7bd69 | ||
![]() |
257ebb88f0 | ||
![]() |
9257cdac8f | ||
![]() |
44da3fd195 | ||
![]() |
c7c167a058 | ||
![]() |
6f3cdbc165 | ||
![]() |
5b4a3e4288 | ||
![]() |
b7ff94900f | ||
![]() |
e761cc76fa | ||
![]() |
96da61f4e4 | ||
![]() |
729d2da764 | ||
![]() |
2587d7fec8 | ||
![]() |
a6c6f64453 | ||
![]() |
b31bfeebd7 | ||
![]() |
d153672f0d | ||
![]() |
9f9581e1f8 | ||
![]() |
b0588321e0 | ||
![]() |
574ab7d696 | ||
![]() |
336b908e8f | ||
![]() |
b41dd2780e | ||
![]() |
7e99d7515f | ||
![]() |
c9de592832 | ||
![]() |
69ac7b9bcf | ||
![]() |
05f57249d6 | ||
![]() |
e91befabc0 | ||
![]() |
2e641b0e30 | ||
![]() |
586db3bc5e | ||
![]() |
51fd19c315 | ||
![]() |
a21fb36cd2 | ||
![]() |
28209bb474 | ||
![]() |
376efcde27 | ||
![]() |
4684d19953 | ||
![]() |
4bea504690 | ||
![]() |
90f4ccfb94 | ||
![]() |
d292f71007 | ||
![]() |
4a45a77753 | ||
![]() |
ef28ae8117 | ||
![]() |
b8b0b61e67 | ||
![]() |
41c1b711c2 | ||
![]() |
8ab251c5f7 | ||
![]() |
97d068c3bb | ||
![]() |
3f01a9e1e2 | ||
![]() |
916ea79e57 | ||
![]() |
b855222ee1 | ||
![]() |
fc31195fa0 | ||
![]() |
be56707a8a | ||
![]() |
a74404170d | ||
![]() |
e4e4efcba7 | ||
![]() |
14f87f5aee | ||
![]() |
bb569b4e78 | ||
![]() |
f075384b44 | ||
![]() |
bf3ffc29a9 | ||
![]() |
9bf4ce25b2 | ||
![]() |
d51848cdc0 | ||
![]() |
7497e0f6b9 | ||
![]() |
bdf2e29843 | ||
![]() |
ba9b5c50d2 | ||
![]() |
61834581d5 | ||
![]() |
1276419ec6 | ||
![]() |
ef9631ae24 | ||
![]() |
0560ac2a95 | ||
![]() |
02e81f7ab5 | ||
![]() |
85cf931d0a | ||
![]() |
6907b91420 | ||
![]() |
227934a7f0 | ||
![]() |
089a8c0498 | ||
![]() |
92fa978735 | ||
![]() |
8135de49f0 | ||
![]() |
ccfa14b9b7 | ||
![]() |
e48294a74b | ||
![]() |
50c5a23de8 | ||
![]() |
1f62b6d0d4 | ||
![]() |
c751fe7520 | ||
![]() |
46ecdefde8 | ||
![]() |
e8ea373eb2 | ||
![]() |
162626209c | ||
![]() |
bf3b110804 | ||
![]() |
7d1f931234 | ||
![]() |
ade951a600 | ||
![]() |
48b59c8e24 | ||
![]() |
b3a13cec17 | ||
![]() |
7817315f8b | ||
![]() |
ba18258750 | ||
![]() |
23381f7d17 | ||
![]() |
dd6aa2f775 | ||
![]() |
5b344963b9 | ||
![]() |
cbf844e7db | ||
![]() |
88b39faa7e | ||
![]() |
08495deebb | ||
![]() |
05b9af6195 | ||
![]() |
e2456f4b3f | ||
![]() |
fcaaf7ce03 | ||
![]() |
522ada88ea | ||
![]() |
26784a5325 | ||
![]() |
6cf0b851b7 | ||
![]() |
d252a1dcda | ||
![]() |
391020a2b0 | ||
![]() |
cb2340539d | ||
![]() |
17430210a1 | ||
![]() |
9e81c82452 | ||
![]() |
b3126934b3 | ||
![]() |
37bd4a7d0e | ||
![]() |
ae8a048ea6 | ||
![]() |
b0465e65c3 | ||
![]() |
036f11acaa | ||
![]() |
572e40ca27 |
@@ -1,3 +1,4 @@
|
||||
**/__pycache__
|
||||
/src-ui/.vscode
|
||||
/src-ui/node_modules
|
||||
/src-ui/dist
|
||||
@@ -10,3 +11,9 @@
|
||||
.pytest_cache
|
||||
/dist
|
||||
/scripts
|
||||
/resources
|
||||
**/tests
|
||||
**/*.spec.ts
|
||||
**/htmlcov
|
||||
/src/.pytest_cache
|
||||
.idea
|
||||
|
@@ -21,6 +21,9 @@ indent_style = space
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
|
||||
[*.rst]
|
||||
indent_style = space
|
||||
|
||||
# Tests don't get a line width restriction. It's still a good idea to follow
|
||||
# the 79 character rule, but in the interests of clarity, tests often need to
|
||||
# violate it.
|
||||
|
3
.env
@@ -1 +1,2 @@
|
||||
COMPOSE_PROJECT_NAME=paperless
|
||||
COMPOSE_PROJECT_NAME=paperless
|
||||
export PROMPT="(pipenv-projectname)$P$G"
|
48
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Something is not working
|
||||
title: "[BUG] Concise description of the issue"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!---
|
||||
=> Before opening an issue, please check the documentation and see if it helps you resolve your issue: https://paperless-ngx.readthedocs.io/en/latest/troubleshooting.html
|
||||
=> Please also make sure that you followed the installation instructions.
|
||||
=> Please search the issues and look for similar issues before opening a bug report.
|
||||
|
||||
=> If you would like to submit a feature request please submit one under https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests
|
||||
|
||||
=> If you encounter issues while installing of configuring Paperless-ngx, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably an issue with your system, and not an issue of paperless.
|
||||
|
||||
=> Don't remove the [BUG] prefix from the title.
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Webserver logs**
|
||||
```
|
||||
If available, post any logs from the web server related to your issue.
|
||||
```
|
||||
|
||||
**Relevant information**
|
||||
- Host OS of the machine running paperless: [e.g. Archlinux / Ubuntu 20.04]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 1.0.0]
|
||||
- Installation method: [docker / bare metal]
|
||||
- Any configuration changes you made in `docker-compose.yml`, `docker-compose.env` or `paperless.conf`.
|
20
.github/ISSUE_TEMPLATE/other.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Other
|
||||
about: Anything that is not a feature request or bug.
|
||||
title: "[Other] Title of your issue"
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
=> Discussions, Feedback and other suggestions belong in the "Discussion" section and not on the issue tracker.
|
||||
|
||||
=> If you would like to submit a feature request please submit one under https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests
|
||||
|
||||
=> If you encounter issues while installing of configuring Paperless-ngx, please post that in the "Support" section of the discussions. Remember that Paperless successfully runs on a variety of different systems. If paperless does not start, it's probably is an issue with your system, and not an issue of paperless.
|
||||
|
||||
=> Don't remove the [Other] prefix from the title.
|
||||
|
||||
-->
|
22
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#package-ecosystem
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
|
||||
# Enable version updates for npm
|
||||
- package-ecosystem: "npm"
|
||||
target-branch: "dev"
|
||||
# Look for `package.json` and `lock` files in the `root` directory
|
||||
directory: "/src-ui"
|
||||
# Check the npm registry for updates every week
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
# Enable version updates for Python
|
||||
- package-ecosystem: "pip"
|
||||
target-branch: "dev"
|
||||
# Look for a `Pipfile` in the `root` directory
|
||||
directory: "/"
|
||||
# Check for updates once a week
|
||||
schedule:
|
||||
interval: "weekly"
|
18
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- fixpending
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
327
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- ngx-*
|
||||
- beta-*
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'translations**'
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
-
|
||||
name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
-
|
||||
name: Persistent Github pip cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip3.8}
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pipenv
|
||||
pipenv install --system --dev --ignore-pipfile
|
||||
-
|
||||
name: Make documentation
|
||||
run: |
|
||||
cd docs/
|
||||
make html
|
||||
-
|
||||
name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: documentation
|
||||
path: docs/_build/html/
|
||||
|
||||
codestyle:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
-
|
||||
name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
-
|
||||
name: Persistent Github pip cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip${{ matrix.python-version }}
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pipenv
|
||||
pipenv install --system --dev --ignore-pipfile
|
||||
-
|
||||
name: Codestyle
|
||||
run: |
|
||||
cd src/
|
||||
pycodestyle --max-line-length=88 --ignore=E121,E123,E126,E226,E24,E704,W503,W504,E203
|
||||
codeformatting:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Run black
|
||||
uses: psf/black@stable
|
||||
with:
|
||||
options: "--check --diff"
|
||||
version: "22.1.0"
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.8', '3.9']
|
||||
fail-fast: false
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "${{ matrix.python-version }}"
|
||||
-
|
||||
name: Get pip cache dir
|
||||
id: pip-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
-
|
||||
name: Persistent Github pip cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip${{ matrix.python-version }}
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng
|
||||
pip install --upgrade pipenv
|
||||
pipenv install --system --dev --ignore-pipfile
|
||||
-
|
||||
name: Tests
|
||||
run: |
|
||||
cd src/
|
||||
pytest
|
||||
-
|
||||
name: Publish coverage results
|
||||
if: matrix.python-version == '3.9'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# https://github.com/coveralls-clients/coveralls-python/issues/251
|
||||
run: |
|
||||
cd src/
|
||||
coveralls --service=github
|
||||
|
||||
# build and push image to docker hub.
|
||||
build-docker-image:
|
||||
if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || startsWith(github.ref, 'refs/tags/ngx-') || startsWith(github.ref, 'refs/tags/beta-'))
|
||||
runs-on: ubuntu-latest
|
||||
needs: [tests, codeformatting, codestyle]
|
||||
steps:
|
||||
-
|
||||
name: Prepare
|
||||
id: prepare
|
||||
run: |
|
||||
IMAGE_NAME=ghcr.io/${{ github.repository }}
|
||||
if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
|
||||
TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/tags/ngx-},${IMAGE_NAME}:latest
|
||||
INSPECT_TAG=${IMAGE_NAME}:latest
|
||||
elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
|
||||
TAGS=${IMAGE_NAME}:beta
|
||||
INSPECT_TAG=${TAGS}
|
||||
elif [[ $GITHUB_REF == refs/heads/* ]]; then
|
||||
TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/heads/}
|
||||
INSPECT_TAG=${TAGS}
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
echo ::set-output name=tags::${TAGS}
|
||||
echo ::set-output name=inspect_tag::${INSPECT_TAG}
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Login to Github Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.prepare.outputs.tags }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
-
|
||||
name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ steps.prepare.outputs.inspect_tag }}
|
||||
-
|
||||
name: Export frontend artifact from docker
|
||||
run: |
|
||||
docker run -d --name frontend-extract ${{ steps.prepare.outputs.tags }}
|
||||
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
||||
-
|
||||
name: Upload frontend artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
|
||||
build-release:
|
||||
needs: [build-docker-image, documentation, tests, codeformatting, codestyle]
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.9
|
||||
-
|
||||
name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
||||
pip3 install --upgrade pip setuptools wheel
|
||||
pip3 install -r requirements.txt
|
||||
-
|
||||
name: Download frontend artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: frontend-compiled
|
||||
path: src/documents/static/frontend/
|
||||
-
|
||||
name: Download documentation artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: documentation
|
||||
path: docs/_build/html/
|
||||
-
|
||||
name: Move files
|
||||
run: |
|
||||
mkdir dist
|
||||
mkdir dist/paperless-ngx
|
||||
mkdir dist/paperless-ngx/scripts
|
||||
cp .dockerignore .env Dockerfile Pipfile Pipfile.lock LICENSE README.md requirements.txt dist/paperless-ngx/
|
||||
cp paperless.conf.example dist/paperless-ngx/paperless.conf
|
||||
cp gunicorn.conf.py dist/paperless-ngx/gunicorn.conf.py
|
||||
cp docker/ dist/paperless-ngx/docker -r
|
||||
cp scripts/*.service scripts/*.sh dist/paperless-ngx/scripts/
|
||||
cp src/ dist/paperless-ngx/src -r
|
||||
cp docs/_build/html/ dist/paperless-ngx/docs -r
|
||||
-
|
||||
name: Compile messages
|
||||
run: |
|
||||
cd dist/paperless-ngx/src
|
||||
python3 manage.py compilemessages
|
||||
-
|
||||
name: Collect static files
|
||||
run: |
|
||||
cd dist/paperless-ngx/src
|
||||
python3 manage.py collectstatic --no-input
|
||||
-
|
||||
name: Make release package
|
||||
run: |
|
||||
cd dist
|
||||
find . -name __pycache__ | xargs rm -r
|
||||
tar -cJf paperless-ngx.tar.xz paperless-ngx/
|
||||
-
|
||||
name: Upload release artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release
|
||||
path: dist/paperless-ngx.tar.xz
|
||||
|
||||
publish-release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-release
|
||||
if: contains(github.ref, 'refs/tags/ngx-') || contains(github.ref, 'refs/tags/beta-')
|
||||
steps:
|
||||
-
|
||||
name: Download release artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: release
|
||||
path: ./
|
||||
-
|
||||
name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/ngx-}
|
||||
echo ::set-output name=prerelease::false
|
||||
elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
|
||||
echo ::set-output name=version::${GITHUB_REF#refs/tags/beta-}
|
||||
echo ::set-output name=prerelease::true
|
||||
fi
|
||||
-
|
||||
name: Create release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ngx-${{ steps.get_version.outputs.version }}
|
||||
release_name: Paperless-ngx ${{ steps.get_version.outputs.version }}
|
||||
draft: false
|
||||
prerelease: ${{ steps.get_version.outputs.prerelease }}
|
||||
body: |
|
||||
For a complete list of changes, see the changelog at https://paperless-ngx.readthedocs.io/en/latest/changelog.html.
|
||||
-
|
||||
name: Upload release archive
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: ./paperless-ngx.tar.xz
|
||||
asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
|
||||
asset_content_type: application/x-xz
|
54
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, dev ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ dev ]
|
||||
schedule:
|
||||
- cron: '28 13 * * 5'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
4
.gitignore
vendored
@@ -65,8 +65,8 @@ target/
|
||||
.virtualenv
|
||||
virtualenv
|
||||
/venv
|
||||
docker-compose.env
|
||||
docker-compose.yml
|
||||
/docker-compose.env
|
||||
/docker-compose.yml
|
||||
|
||||
# Used for development
|
||||
scripts/import-for-development
|
||||
|
16
.readthedocs.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: "3.8"
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
51
.travis.yml
@@ -1,51 +0,0 @@
|
||||
language: python
|
||||
|
||||
dist: focal
|
||||
os: linux
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "Paperless on Python 3.6"
|
||||
python: "3.6"
|
||||
|
||||
- name: "Paperless on Python 3.7"
|
||||
python: "3.7"
|
||||
|
||||
- name: "Paperless on Python 3.8"
|
||||
python: "3.8"
|
||||
|
||||
- name: "Documentation"
|
||||
script:
|
||||
- cd docs/
|
||||
- make html
|
||||
after_success: true
|
||||
|
||||
- name: "Front end"
|
||||
language: node_js
|
||||
node_js:
|
||||
- 15
|
||||
before_install: true
|
||||
install:
|
||||
- cd src-ui/
|
||||
- npm install -g @angular/cli
|
||||
- npm install
|
||||
script:
|
||||
- ng build --prod
|
||||
after_success: true
|
||||
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libpoppler-cpp-dev unpaper tesseract-ocr imagemagick ghostscript optipng
|
||||
|
||||
install:
|
||||
- pip install --upgrade pipenv
|
||||
- pipenv install --system --dev
|
||||
|
||||
script:
|
||||
- cd src/
|
||||
- pipenv run pytest --cov
|
||||
- pipenv run pycodestyle
|
||||
|
||||
after_success:
|
||||
- pipenv run coveralls
|
@@ -1,30 +1,95 @@
|
||||
# Contributing
|
||||
|
||||
There's still lots of things to be done, just have a look at that issue log. If you feel like conctributing 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.
|
||||
If you feel like contributing to the project, please do! Bug fixes and improvements are always welcome.
|
||||
|
||||
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 in the readme.
|
||||
If you want to implement something big:
|
||||
|
||||
* Please start a discussion about that in the issues! Maybe something similar is already in development and we can make it happen together.
|
||||
* When making additions to the project, consider if the majority of users will benefit from your change. If not, you're probably better of forking the project.
|
||||
* Also consider if your change will get in the way of other users. A good change is a change that enhances the experience of some users who want that change and does not affect users who do not care about the change.
|
||||
* Please see the [paperless-ngx merge process](#merging-prs) below.
|
||||
|
||||
## Python
|
||||
|
||||
Use python 3.6 for development. Paperless supports python 3.6, 3.7 and 3.8.
|
||||
Paperless supports python 3.8 and 3.9. We format Python code with [Black](https://github.com/psf/black).
|
||||
|
||||
## Branches
|
||||
|
||||
master always reflects the latest release.
|
||||
`master` always reflects the latest release. Apart from changes to the documentation or readme, absolutely no functional changes on this branch in between releases.
|
||||
|
||||
dev contains all changes that will be part of the next release. Use this branch to start making your changes.
|
||||
`dev` contains all changes that will be part of the next release. Use this branch to start making your changes.
|
||||
|
||||
feature-X branches is for experimental stuff that will eventually be merged into dev, and then released as part of the next release.
|
||||
`feature-X` branches are for experimental stuff that will eventually be merged into dev.
|
||||
|
||||
## Testing:
|
||||
|
||||
I'm trying to get most of paperless tested, so please do the same for your code! I know its a hassle, but it makes sure that your code works now and will allow us to detect regressions easily.
|
||||
Please format and test your code! I know it's a hassle, but it makes sure that your code works now and will allow us to detect regressions easily.
|
||||
|
||||
To test your code, execute `pytest` in the src/ directory. Executing that in the project root is no good. This also generates a html coverage report, which you can use to see if you missed anything important during testing.
|
||||
To test your code, execute `pytest` in the src/ directory. This also generates a html coverage report, which you can use to see if you missed anything important during testing.
|
||||
|
||||
## More info:
|
||||
|
||||
... is available in the documentation. https://paperless-ng.readthedocs.io/en/latest/extending.html
|
||||
... is available in the documentation. https://paperless-ngx.readthedocs.io/en/latest/extending.html
|
||||
|
||||
# Merging PRs
|
||||
|
||||
Once you have submitted a **P**ull **R**equest it will be reviewed, approved, and merged by one or more community members of any team. Automated code tests and formatting checks must be passed.
|
||||
|
||||
## Non-Trivial Requests
|
||||
|
||||
PRs deemed `non-trivial` will go through a stricter review process before being merged into `dev`. This is to ensure code quality and complete functionality (free of side effects).
|
||||
|
||||
Examples of `non-trivial` PRs might include:
|
||||
|
||||
* Additional features
|
||||
* Large changes to many distinct files
|
||||
* Breaking or depreciation of existing features
|
||||
|
||||
Our community review process for `non-trivial` PRs is the following:
|
||||
|
||||
1. Must pass usual automated code tests and formatting checks.
|
||||
2. The PR will be assigned and pinged to the appropriately experienced team (i.e. @paperless-ngx/backend for backend changes).
|
||||
3. Development team will check and test code manually (possibly over several days).
|
||||
- You may be asked to make changes or rebase.
|
||||
- The team may ask for additional testing done by @paperless-ngx/test
|
||||
4. **At least two** members of the team will approve and finally merge the request into `dev` 🎉.
|
||||
|
||||
This process might be slow as community members have different schedules and time to dedicate to the Paperless project. However it ensures community code reviews are as brilliantly thorough as they once were with @jonaswinkler.
|
||||
|
||||
# Translating Paperless-ngx
|
||||
|
||||
Some notes about translation:
|
||||
|
||||
- There are two resources:
|
||||
- `src-ui/messages.xlf` contains the translation strings for the front end. This is the most important.
|
||||
- `django.po` contains strings for the administration section of paperless, which is nice to have translated.
|
||||
- Most of the front-end strings are used on buttons, menu items, etc., so ideally the translated string should not be much longer than the English original.
|
||||
- Translation units may contain placeholders. These usually mean that there's a name of a tag or document or something in the string. You can click on the placeholders to copy them.
|
||||
- Translation units may contain plural expressions such as `{PLURAL_VAR, plural, =1 {one result} =0 {no results} other {<placeholder> results}}`. Copy these verbatim and translate only the content in the inner `{}` brackets. Example: `{PLURAL_VAR, plural, =1 {Ein Ergebnis} =0 {Keine Ergebnisse} other {<placeholder> Ergebnisse}}`
|
||||
- Changes to translations on Crowdin will get pushed into the repository automatically.
|
||||
|
||||
## Adding new languages to the codebase
|
||||
|
||||
If a language has already been added, and you would like to contribute new translations or change existing translations, please read the "Translation" section in the README.md file for further details on that.
|
||||
|
||||
If you would like the project to be translated to another language, first head over to https://crwd.in/paperless-ngx to check if that language has already been enabled for translation.
|
||||
If not, please request the language to be added by creating an issue on GitHub. The issue should contain:
|
||||
|
||||
* English name of the language (the localized name can be added on Crowdin).
|
||||
* ISO language code. A list of those can be found here: https://support.crowdin.com/enterprise/language-codes/
|
||||
* Date format commonly used for the language, e.g. dd/mm/yyyy, mm/dd/yyyy, etc.
|
||||
|
||||
After the language has been added and some translations have been made on Crowdin, the language needs to be enabled in the code.
|
||||
Note that there is no need to manually add a .po of .xlf file as those will be automatically generated and imported from Crowdin.
|
||||
The following files need to be changed:
|
||||
|
||||
* src-ui/angular.json (under the _projects/paperless-ui/i18n/locales_ JSON key)
|
||||
* src/paperless/settings.py (in the _LANGUAGES_ array)
|
||||
* src-ui/src/app/services/settings.service.ts (inside the _getLanguageOptions_ method)
|
||||
* src-ui/src/app/app.module.ts (import locale from _angular/common/locales_ and call _registerLocaleData_)
|
||||
|
||||
Please add the language in the correct order, alphabetically by locale.
|
||||
Note that _en-us_ needs to stay on top of the list, as it is the default project language
|
||||
|
||||
If you are familiar with Git, feel free to send a Pull Request with those changes.
|
||||
If not, let us know in the issue you created for the language, so that another developer can make these changes.
|
||||
|
134
Dockerfile
Normal file
@@ -0,0 +1,134 @@
|
||||
FROM node:16 AS compile-frontend
|
||||
|
||||
COPY . /src
|
||||
|
||||
WORKDIR /src/src-ui
|
||||
RUN npm update npm -g && npm install
|
||||
RUN ./node_modules/.bin/ng build --configuration production
|
||||
|
||||
|
||||
FROM ubuntu:20.04 AS jbig2enc
|
||||
|
||||
WORKDIR /usr/src/jbig2enc
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends build-essential automake libtool libleptonica-dev zlib1g-dev git ca-certificates
|
||||
|
||||
RUN git clone https://github.com/agl/jbig2enc .
|
||||
RUN ./autogen.sh
|
||||
RUN ./configure && make
|
||||
|
||||
|
||||
FROM python:3.9-slim-bullseye
|
||||
|
||||
# Binary dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
# Basic dependencies
|
||||
curl \
|
||||
gnupg \
|
||||
imagemagick \
|
||||
gettext \
|
||||
tzdata \
|
||||
gosu \
|
||||
# fonts for text file thumbnail generation
|
||||
fonts-liberation \
|
||||
# for Numpy
|
||||
libatlas-base-dev \
|
||||
libxslt1-dev \
|
||||
# thumbnail size reduction
|
||||
optipng \
|
||||
libxml2 \
|
||||
pngquant \
|
||||
unpaper \
|
||||
zlib1g \
|
||||
ghostscript \
|
||||
icc-profiles-free \
|
||||
# Mime type detection
|
||||
file \
|
||||
libmagic-dev \
|
||||
media-types \
|
||||
# OCRmyPDF dependencies
|
||||
liblept5 \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-eng \
|
||||
tesseract-ocr-deu \
|
||||
tesseract-ocr-fra \
|
||||
tesseract-ocr-ita \
|
||||
tesseract-ocr-spa \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# copy jbig2enc
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/.libs/libjbig2enc* /usr/local/lib/
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/jbig2 /usr/local/bin/
|
||||
COPY --from=jbig2enc /usr/src/jbig2enc/src/*.h /usr/local/include/
|
||||
|
||||
WORKDIR /usr/src/paperless/src/
|
||||
|
||||
COPY requirements.txt ../
|
||||
|
||||
# Python dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
build-essential \
|
||||
libpq-dev \
|
||||
git \
|
||||
zlib1g-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
&& if [ "$(uname -m)" = "armv7l" ] || [ "$(uname -m)" = "aarch64" ]; \
|
||||
then echo "Building qpdf" \
|
||||
&& mkdir -p /usr/src/qpdf \
|
||||
&& cd /usr/src/qpdf \
|
||||
&& git clone https://github.com/qpdf/qpdf.git . \
|
||||
&& git checkout --quiet release-qpdf-10.6.2 \
|
||||
&& ./configure \
|
||||
&& make \
|
||||
&& make install \
|
||||
&& cd /usr/src/paperless/src/ \
|
||||
&& rm -rf /usr/src/qpdf; \
|
||||
else \
|
||||
echo "Skipping qpdf build because pikepdf binary wheels are available."; \
|
||||
fi \
|
||||
&& python3 -m pip install --upgrade pip wheel \
|
||||
&& python3 -m pip install --default-timeout=1000 --upgrade --no-cache-dir supervisor \
|
||||
&& python3 -m pip install --default-timeout=1000 --no-cache-dir -r ../requirements.txt \
|
||||
&& apt-get -y purge build-essential git zlib1g-dev libjpeg62-turbo-dev \
|
||||
&& apt-get -y autoremove --purge \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# setup docker-specific things
|
||||
COPY docker/ ./docker/
|
||||
|
||||
RUN cd docker \
|
||||
&& cp imagemagick-policy.xml /etc/ImageMagick-6/policy.xml \
|
||||
&& mkdir /var/log/supervisord /var/run/supervisord \
|
||||
&& cp supervisord.conf /etc/supervisord.conf \
|
||||
&& cp docker-entrypoint.sh /sbin/docker-entrypoint.sh \
|
||||
&& cp docker-prepare.sh /sbin/docker-prepare.sh \
|
||||
&& chmod 755 /sbin/docker-entrypoint.sh \
|
||||
&& chmod +x install_management_commands.sh \
|
||||
&& ./install_management_commands.sh \
|
||||
&& cd .. \
|
||||
&& rm docker -rf
|
||||
|
||||
COPY gunicorn.conf.py ../
|
||||
|
||||
# copy app
|
||||
COPY --from=compile-frontend /src/src/ ./
|
||||
|
||||
# add users, setup scripts
|
||||
RUN addgroup --gid 1000 paperless \
|
||||
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
||||
&& chown -R paperless:paperless ../ \
|
||||
&& gosu paperless python3 manage.py collectstatic --clear --no-input \
|
||||
&& gosu paperless python3 manage.py compilemessages
|
||||
|
||||
VOLUME ["/usr/src/paperless/data", "/usr/src/paperless/media", "/usr/src/paperless/consume", "/usr/src/paperless/export"]
|
||||
ENTRYPOINT ["/sbin/docker-entrypoint.sh"]
|
||||
EXPOSE 8000
|
||||
CMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||
|
||||
LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>"
|
||||
LABEL org.opencontainers.image.documentation="https://paperless-ngx.readthedocs.io/en/latest/"
|
||||
LABEL org.opencontainers.image.source="https://github.com/paperless-ngx/paperless-ngx"
|
||||
LABEL org.opencontainers.image.url="https://github.com/paperless-ngx/paperless-ngx"
|
||||
LABEL org.opencontainers.image.licenses="GPL-3.0-only"
|
43
Pipfile
@@ -8,41 +8,49 @@ url = "https://www.piwheels.org/simple"
|
||||
verify_ssl = true
|
||||
name = "piwheels"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
|
||||
[packages]
|
||||
dateparser = "~=0.7.6"
|
||||
django = "~=3.1.3"
|
||||
dateparser = "~=1.1.0"
|
||||
django = "~=3.2"
|
||||
django-cors-headers = "*"
|
||||
django-extensions = "*"
|
||||
django-filter = "~=2.4.0"
|
||||
django-filter = "~=21.1"
|
||||
django-q = "~=1.3.4"
|
||||
djangorestframework = "~=3.12.2"
|
||||
djangorestframework = "~=3.13.1"
|
||||
filelock = "*"
|
||||
fuzzywuzzy = "*"
|
||||
fuzzywuzzy = {extras = ["speedup"], version = "*"}
|
||||
gunicorn = "*"
|
||||
imap-tools = "*"
|
||||
langdetect = "*"
|
||||
pdftotext = "*"
|
||||
numpy = "~=1.22.0"
|
||||
pathvalidate = "*"
|
||||
pillow = "*"
|
||||
pikepdf = "*"
|
||||
pillow = "~=9.0"
|
||||
pikepdf = "~=5.0"
|
||||
python-gnupg = "*"
|
||||
python-dotenv = "*"
|
||||
python-dateutil = "*"
|
||||
python-Levenshtein = "*"
|
||||
python-magic = "*"
|
||||
psycopg2-binary = "*"
|
||||
redis = "*"
|
||||
scikit-learn="~=0.23.2"
|
||||
whitenoise = "~=5.2.0"
|
||||
watchdog = "*"
|
||||
# Pinned because aarch64 wheels and updates cause warnings when loading the classifier model.
|
||||
scikit-learn="==0.24.0"
|
||||
whitenoise = "~=6.0.0"
|
||||
watchdog = "~=2.1.0"
|
||||
whoosh="~=2.7.4"
|
||||
inotifyrecursive = "~=0.3.4"
|
||||
ocrmypdf = "~=11.4.5"
|
||||
ocrmypdf = "~=13.4.0"
|
||||
tqdm = "*"
|
||||
tika = "*"
|
||||
# TODO: This will sadly also install daphne+dependencies,
|
||||
# which an ASGI server we don't need. Adds about 15MB image size.
|
||||
channels = "~=3.0"
|
||||
channels-redis = "*"
|
||||
uvicorn = {extras = ["standard"], version = "*"}
|
||||
concurrent-log-handler = "*"
|
||||
# uvloop 0.15+ incompatible with python 3.6
|
||||
uvloop = "~=0.16"
|
||||
cryptography = "~=36.0.1"
|
||||
"pdfminer.six" = "*"
|
||||
"backports.zoneinfo" = "*"
|
||||
|
||||
[dev-packages]
|
||||
coveralls = "*"
|
||||
@@ -54,6 +62,7 @@ pytest-django = "*"
|
||||
pytest-env = "*"
|
||||
pytest-sugar = "*"
|
||||
pytest-xdist = "*"
|
||||
sphinx = "~=3.3"
|
||||
sphinx = "~=3.4.2"
|
||||
sphinx_rtd_theme = "*"
|
||||
tox = "*"
|
||||
black = "*"
|
||||
|
2308
Pipfile.lock
generated
155
README.md
@@ -1,38 +1,46 @@
|
||||
[](https://travis-ci.com/jonaswinkler/paperless-ng)
|
||||
[](https://paperless-ng.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://gitter.im/paperless-ng/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://hub.docker.com/r/jonaswinkler/paperless-ng)
|
||||
[](https://coveralls.io/github/jonaswinkler/paperless-ng?branch=master)
|
||||
[](https://github.com/paperless-ngx/paperless-ngx/actions)
|
||||
[](https://crowdin.com/project/paperless-ngx)
|
||||
[](https://paperless-ngx.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://coveralls.io/github/paperless-ngx/paperless-ngx?branch=master)
|
||||
[](https://matrix.to/#/#paperless:adnidor.de)
|
||||
|
||||
# Paperless-ng
|
||||
<p align="center">
|
||||
<img src="https://github.com/paperless-ngx/paperless-ngx/raw/main/resources/logo/web/png/Black%20logo%20-%20no%20background.png#gh-light-mode-only" width="50%" />
|
||||
<img src="https://github.com/paperless-ngx/paperless-ngx/raw/main/resources/logo/web/png/White%20logo%20-%20no%20background.png#gh-dark-mode-only" width="50%" />
|
||||
</p>
|
||||
|
||||
[Paperless](https://github.com/the-paperless-project/paperless) is an application by Daniel Quinn and contributors that indexes your scanned documents and allows you to easily search for documents and store metadata alongside your documents.
|
||||
<!-- omit in toc -->
|
||||
# Paperless-ngx
|
||||
|
||||
Paperless-ng is a fork of the original project, adding a new interface and many other changes under the hood. For a detailed list of changes, have a look at the changelog in the documentation.
|
||||
Paperless-ngx is a document management system that transforms your physical documents into a searchable online archive so you can keep, well, *less paper*.
|
||||
|
||||
This project is still in development and some things may not work as expected.
|
||||
Paperless-ngx forked from [paperless-ng](https://github.com/jonaswinkler/paperless-ng) to continue the great work and distribute responsibility of supporting and advancing the project among a team of people. [Consider joining us!](#community-support) Discussion of this transition can be found in issues
|
||||
[#1599](https://github.com/jonaswinkler/paperless-ng/issues/1599) and [#1632](https://github.com/jonaswinkler/paperless-ng/issues/1632).
|
||||
|
||||
# How it Works
|
||||
A demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) using login `demo` / `demo`. *Note: demo content is reset frequently and confidential information should not be uploaded.*
|
||||
|
||||
Paperless does not control your scanner, it only helps you deal with what your scanner produces.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
4. Download the PDF you need/want via the web interface and do whatever you like with it. You can even print it and send it as if it's the original. In most cases, no one will care or notice.
|
||||
|
||||
Here's what you get:
|
||||
|
||||

|
||||
- [Features](#features)
|
||||
- [Getting started](#getting-started)
|
||||
- [Contributing](#contributing)
|
||||
- [Community Support](#community-support)
|
||||
- [Translation](#translation)
|
||||
- [Feature Requests](#feature-requests)
|
||||
- [Bugs](#bugs)
|
||||
- [Affiliated Projects](#affiliated-projects)
|
||||
- [Important Note](#important-note)
|
||||
|
||||
# Features
|
||||
|
||||

|
||||

|
||||
|
||||
* Organize and index your scanned documents with tags, correspondents, types, and more.
|
||||
* Performs OCR on your documents, adds selectable text to image only documents and adds tags, correspondents and document types to your documents.
|
||||
* Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and can be configured freely.
|
||||
* Single page application front end. Should be pretty snappy. Will be mobile friendly in the future.
|
||||
* Supports PDF documents, images, plain text files, and Office documents (Word, Excel, Powerpoint, and LibreOffice equivalents).
|
||||
* Office document support is optional and provided by Apache Tika (see [configuration](https://paperless-ngx.readthedocs.io/en/latest/configuration.html#tika-settings))
|
||||
* Paperless stores your documents plain on disk. Filenames and folders are managed by paperless and their format can be configured freely.
|
||||
* Single page application front end.
|
||||
* Includes a dashboard that shows basic statistics and has document upload.
|
||||
* Filtering by tags, correspondents, types, and more.
|
||||
* Customizable views can be saved and displayed on the dashboard.
|
||||
@@ -43,94 +51,69 @@ Here's what you get:
|
||||
* Searching for similar documents ("More like this")
|
||||
* Email processing: Paperless adds documents from your email accounts.
|
||||
* Configure multiple accounts and filters for each account.
|
||||
* When adding documents from mails, paperless can move these mails to a new folder, mark them as read, flag them or delete them.
|
||||
* When adding documents from mail, paperless can move these mail to a new folder, mark them as read, flag them as important or delete them.
|
||||
* Machine learning powered document matching.
|
||||
* Paperless learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless.
|
||||
* A task processor that processes documents in parallel and also tells you when something goes wrong. On modern multi core systems, consumption is blazing fast.
|
||||
|
||||
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).
|
||||
|
||||
For a complete list of changes from paperless, check out the [changelog](https://paperless-ng.readthedocs.io/en/latest/changelog.html)
|
||||
|
||||
# Roadmap for 1.0
|
||||
|
||||
- Make the front end nice (except mobile).
|
||||
- Fix whatever bugs I and you find.
|
||||
- Start using CI to build the app.
|
||||
- Simplify updates.
|
||||
- Make the documentation nice.
|
||||
|
||||
## Roadmap for versions beyond 1.0
|
||||
|
||||
These are things that I want to add to paperless eventually. They are sorted by priority.
|
||||
|
||||
- **More search.** The search backend is incredibly versatile and customizable. Searching is the most important feature of this project and thus, I want to implement things like:
|
||||
- Group and limit search results by correspondent, show “more from this” links in the results.
|
||||
- **Nested tags**. Organize tags in a hierarchical structure. This will combine the benefits of folders and tags in one coherent system.
|
||||
- **An interactive consumer** that shows its progress for documents it processes on the web page.
|
||||
- With live updates and websockets. This already works on a dev branch, but requires a lot of new dependencies, which I'm not particularly happy about.
|
||||
- Notifications when a document was added with buttons to open the new document right away.
|
||||
- **Arbitrary tag colors**. Allow the selection of any color with a color picker.
|
||||
|
||||
Apart from that, paperless is pretty much feature complete.
|
||||
|
||||
## On the chopping block.
|
||||
|
||||
- **GnuPG encrypion.** [Here's a note about encryption in paperless](https://paperless-ng.readthedocs.io/en/latest/administration.html#managing-encryption). The gist of it is that I don't see which attacks this implementation protects against. It gives a false sense of security to users who don't care about how it works.
|
||||
|
||||
## Wont-do list.
|
||||
|
||||
These features will probably never make it into paperless, since paperless is meant to be an easy to use set-and-forget solution.
|
||||
|
||||
- **Document versions.** I might consider adding the ability to update a document with a newer version, but that's about it. The kind of documents that get added to paperless usually don't change at all.
|
||||
- **Workflows.** I don't see a use case for these, yet.
|
||||
- **Folders.** Tags are superior in just about every way.
|
||||
- **Apps / extension support.** Again, paperless is meant to be simple.
|
||||
* Paperless-ngx learns from your documents and will be able to automatically assign tags, correspondents and types to documents once you've stored a few documents in paperless.
|
||||
* Optimized for multi core systems: Paperless-ngx consumes multiple documents in parallel.
|
||||
* The integrated sanity checker makes sure that your document archive is in good health.
|
||||
* [More screenshots are available in the documentation](https://paperless-ngx.readthedocs.io/en/latest/screenshots.html).
|
||||
|
||||
# Getting started
|
||||
|
||||
The recommended way to deploy paperless is docker-compose. Don't clone the repository, grab the latest release to get started instead. The dockerfiles archive contains just the docker files which will pull the image from docker hub. The source archive contains everything you need to build the docker image yourself (i.e. if you want to run on Raspberry Pi).
|
||||
The easiest way to deploy paperless is docker-compose. The files in the [`/docker/compose` directory](https://github.com/paperless-ngx/paperless-ngx/tree/main/docker/compose) are configured to pull the image from Github Packages.
|
||||
|
||||
Read the [documentation](https://paperless-ng.readthedocs.io/en/latest/setup.html#installation) on how to get started.
|
||||
If you'd like to jump right in, you can configure a docker-compose environment with our install script:
|
||||
|
||||
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.
|
||||
```bash
|
||||
bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/master/install-paperless-ngx.sh)"
|
||||
```
|
||||
|
||||
# Migrating to paperless-ng
|
||||
Alternatively, you can install the dependencies and setup apache and a database server yourself. The [documentation](https://paperless-ngx.readthedocs.io/en/latest/setup.html#installation) has a step by step guide on how to do it.
|
||||
|
||||
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.
|
||||
Migrating from Paperless-ng is easy, just drop in the new docker image! See the [documentation on migrating](https://paperless-ngx.readthedocs.io/en/latest/setup.html#migrating-from-paperless-ng) for more details.
|
||||
|
||||
# Documentation
|
||||
<!-- omit in toc -->
|
||||
### Documentation
|
||||
|
||||
The documentation for Paperless-ng is available on [ReadTheDocs](https://paperless-ng.readthedocs.io/).
|
||||
The documentation for Paperless-ngx is available on [ReadTheDocs](https://paperless-ngx.readthedocs.io/).
|
||||
|
||||
# Translation
|
||||
# Contributing
|
||||
|
||||
Paperless is currently available in English, German, Dutch and French. Translation is coordinated at transifex: https://www.transifex.com/paperless/paperless-ng
|
||||
If you feel like contributing to the project, please do! Bug fixes, enhancements, visual fixes etc. are always welcome. If you want to implement something big: Please start a discussion about that! The [documentation](https://paperless-ngx.readthedocs.io/en/latest/extending.html) has some basic information on how to get started.
|
||||
|
||||
If you want to see paperless in your own language, request that language at transifex and you can start translating after I approve the language.
|
||||
## Community Support
|
||||
|
||||
# Suggestions? Questions? Something not working?
|
||||
People interested in continuing the work on paperless-ngx are encouraged to reach out here on github and in the [Matrix Room](https://matrix.to/#/#paperless:adnidor.de). If you would like to contribute to the project on an ongoing basis there are multiple [teams](https://github.com/orgs/paperless-ngx/people) (frontend, ci/cd, etc) that could use your help so please reach out!
|
||||
|
||||
Please open an issue and start a discussion about it!
|
||||
## Translation
|
||||
|
||||
## Feel like helping out?
|
||||
Paperless-ngx is available in many languages that are coordinated on Crowdin. If you want to help out by translating paperless-ngx into your language, please head over to https://crwd.in/paperless-ngx, and thank you! More details can be found in [CONTRIBUTING.md](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md#translating-paperless-ngx).
|
||||
|
||||
There's still lots of things to be done, just have a look at that issue log. 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.
|
||||
## Feature Requests
|
||||
|
||||
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.
|
||||
Feature requests can be submitted via [GitHub Discussions](https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests), you can search for existing ideas, add your own and vote for the ones you care about.
|
||||
|
||||
## Bugs
|
||||
|
||||
For bugs please [open an issue](https://github.com/paperless-ngx/paperless-ngx/issues) or [start a discussion](https://github.com/paperless-ngx/paperless-ngx/discussions) if you have questions.
|
||||
|
||||
# Affiliated Projects
|
||||
|
||||
Paperless has been around a while now, and people are starting to build stuff on top of it. If you're one of those people, we can add your project to this list:
|
||||
Paperless has been around a while now, and people are starting to build stuff on top of it. If you're one of those people, we can add your project to this list:
|
||||
|
||||
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless. Updated to work with paperless-ng.
|
||||
* [Paperless App](https://github.com/bauerj/paperless_app): An Android/iOS app for Paperless-ngx. Also works with the original Paperless and Paperless-ngx.
|
||||
* [Paperless Share](https://github.com/qcasey/paperless_share). Share any files from your Android application with paperless. Very simple, but works with all of the mobile scanning apps out there that allow you to share scanned documents.
|
||||
* [Scan to Paperless](https://github.com/sbrunner/scan-to-paperless): Scan and prepare (crop, deskew, OCR, ...) your documents for Paperless.
|
||||
|
||||
These projects also exist, but their status and compatibility with paperless-ng is unknown.
|
||||
These projects also exist, but their status and compatibility with paperless-ngx is unknown.
|
||||
|
||||
* [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): A desktop UI for your Paperless installation. Runs on Mac, Linux, and Windows.
|
||||
* [paperless-cli](https://github.com/stgarf/paperless-cli): A golang command line binary to interact with a Paperless instance.
|
||||
|
||||
This project also exists, but needs updates to be compatible with paperless-ngx.
|
||||
|
||||
* [Paperless Desktop](https://github.com/thomasbrueggemann/paperless-desktop): A desktop UI for your Paperless installation. Runs on Mac, Linux, and Windows.
|
||||
Known issues on Mac: (Could not load reminders and documents)
|
||||
|
||||
# Important Note
|
||||
|
||||
Document scanners are typically used to scan sensitive documents. Things like your social insurance number, tax records, invoices, etc. Everything is stored in the clear without encryption by default (it needs to be searchable, so if someone has ideas on how to do that on encrypted data, I'm all ears). This means that Paperless should never be run on an untrusted host. Instead, I recommend that if you do want to use it, run it locally on a server in your own home.
|
||||
Document scanners are typically used to scan sensitive documents. Things like your social insurance number, tax records, invoices, etc. Everything is stored in the clear without encryption. This means that Paperless should never be run on an untrusted host. Instead, I recommend that if you do want to use it, run it locally on a server in your own home.
|
||||
|
6
crowdin.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
commit_message: '[ci skip]'
|
||||
files:
|
||||
- source: /src/locale/en_US/LC_MESSAGES/django.po
|
||||
translation: /src/locale/%locale_with_underscore%/LC_MESSAGES/django.po
|
||||
- source: /src-ui/messages.xlf
|
||||
translation: /src-ui/src/locale/messages.%locale_with_underscore%.xlf
|
1
docker/compose/.env
Normal file
@@ -0,0 +1 @@
|
||||
COMPOSE_PROJECT_NAME=paperless
|
@@ -7,7 +7,7 @@
|
||||
# Additional languages to install for text recognition, separated by a
|
||||
# whitespace. Note that this is
|
||||
# different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the
|
||||
# default language used when guessing the language from the OCR output.
|
||||
# language used for OCR.
|
||||
# The container installs English, German, Italian, Spanish and French by
|
||||
# default.
|
||||
# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster
|
97
docker/compose/docker-compose.portainer.yml
Normal file
@@ -0,0 +1,97 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8010.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Instead of SQLite (default), PostgreSQL is used as the database server.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Open portainer Stacks list and click 'Add stack'
|
||||
# - Paste the contents of this file and assign a name, e.g. 'Paperless'
|
||||
# - Click 'Deploy the stack' and wait for it to be deployed
|
||||
# - Open the list of containers, select paperless_webserver_1
|
||||
# - Click 'Console' and then 'Connect' to open the command line inside the container
|
||||
# - Run 'python3 manage.py createsuperuser' to create a user
|
||||
# - Exit the console
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8010:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
# The UID and GID of the user used to run paperless in the container. Set this
|
||||
# to your UID and GID on the host so that you have write access to the
|
||||
# consumption directory.
|
||||
USERMAP_UID: 1000
|
||||
USERMAP_GID: 100
|
||||
# Additional languages to install for text recognition, separated by a
|
||||
# whitespace. Note that this is
|
||||
# different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the
|
||||
# language used for OCR.
|
||||
# The container installs English, German, Italian, Spanish and French by
|
||||
# default.
|
||||
# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster
|
||||
# for available languages.
|
||||
#PAPERLESS_OCR_LANGUAGES: tur ces
|
||||
# Adjust this key if you plan to make paperless available publicly. It should
|
||||
# be a very long sequence of random characters. You don't need to remember it.
|
||||
#PAPERLESS_SECRET_KEY: change-me
|
||||
# Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC.
|
||||
#PAPERLESS_TIME_ZONE: America/Los_Angeles
|
||||
# The default language to use for OCR. Set this to the language most of your
|
||||
# documents are written in.
|
||||
#PAPERLESS_OCR_LANGUAGE: eng
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
||||
redisdata:
|
93
docker/compose/docker-compose.postgres-tika.yml
Normal file
@@ -0,0 +1,93 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Instead of SQLite (default), PostgreSQL is used as the database server.
|
||||
# - Apache Tika and Gotenberg servers are started with paperless and paperless
|
||||
# is configured to use these services. These provide support for consuming
|
||||
# Office documents (Word, Excel, Power Point and their LibreOffice counter-
|
||||
# parts.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
- gotenberg
|
||||
- tika
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CHROMIUM_DISABLE_ROUTES: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
||||
redisdata:
|
75
docker/compose/docker-compose.postgres.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Instead of SQLite (default), PostgreSQL is used as the database server.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
||||
redisdata:
|
81
docker/compose/docker-compose.sqlite-tika.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# SQLite is used as the database. The SQLite file is stored in the data volume.
|
||||
#
|
||||
# In addition to that, this docker-compose file adds the following optional
|
||||
# configurations:
|
||||
#
|
||||
# - Apache Tika and Gotenberg servers are started with paperless and paperless
|
||||
# is configured to use these services. These provide support for consuming
|
||||
# Office documents (Word, Excel, Power Point and their LibreOffice counter-
|
||||
# parts.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- broker
|
||||
- gotenberg
|
||||
- tika
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CHROMIUM_DISABLE_ROUTES: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
redisdata:
|
59
docker/compose/docker-compose.sqlite.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
# docker-compose file for running paperless from the Docker Hub.
|
||||
# This file contains everything paperless needs to run.
|
||||
# Paperless supports amd64, arm and arm64 hardware.
|
||||
#
|
||||
# All compose files of paperless configure paperless in the following way:
|
||||
#
|
||||
# - Paperless is (re)started on system boot, if it was running before shutdown.
|
||||
# - Docker volumes for storing data are managed by Docker.
|
||||
# - Folders for importing and exporting files are created in the same directory
|
||||
# as this file and mounted to the correct folders inside the container.
|
||||
# - Paperless listens on port 8000.
|
||||
#
|
||||
# SQLite is used as the database. The SQLite file is stored in the data volume.
|
||||
#
|
||||
# To install and update paperless with this file, do the following:
|
||||
#
|
||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||
# and '.env' into a folder.
|
||||
# - Run 'docker-compose pull'.
|
||||
# - Run 'docker-compose run --rm webserver createsuperuser' to create a user.
|
||||
# - Run 'docker-compose up -d'.
|
||||
#
|
||||
# For more extensive installation and update instructions, refer to the
|
||||
# documentation.
|
||||
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
redisdata:
|
134
docker/docker-entrypoint.sh
Normal file → Executable file
@@ -4,87 +4,42 @@ set -e
|
||||
|
||||
# Source: https://github.com/sameersbn/docker-gitlab/
|
||||
map_uidgid() {
|
||||
USERMAP_ORIG_UID=$(id -u paperless)
|
||||
USERMAP_ORIG_GID=$(id -g paperless)
|
||||
USERMAP_NEW_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
|
||||
USERMAP_NEW_GID=${USERMAP_GID:-${USERMAP_ORIG_GID:-$USERMAP_NEW_UID}}
|
||||
if [[ ${USERMAP_NEW_UID} != "${USERMAP_ORIG_UID}" || ${USERMAP_NEW_GID} != "${USERMAP_ORIG_GID}" ]]; then
|
||||
echo "Mapping UID and GID for paperless:paperless to $USERMAP_NEW_UID:$USERMAP_NEW_GID"
|
||||
usermod -u "${USERMAP_NEW_UID}" paperless
|
||||
groupmod -o -g "${USERMAP_NEW_GID}" paperless
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
wait_for_postgres() {
|
||||
attempt_num=1
|
||||
max_attempts=5
|
||||
|
||||
echo "Waiting for PostgreSQL to start..."
|
||||
|
||||
host="${PAPERLESS_DBHOST}"
|
||||
port="${PAPERLESS_DBPORT}"
|
||||
|
||||
if [[ -z $port ]] ;
|
||||
then
|
||||
port="5432"
|
||||
USERMAP_ORIG_UID=$(id -u paperless)
|
||||
USERMAP_ORIG_GID=$(id -g paperless)
|
||||
USERMAP_NEW_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
|
||||
USERMAP_NEW_GID=${USERMAP_GID:-${USERMAP_ORIG_GID:-$USERMAP_NEW_UID}}
|
||||
if [[ ${USERMAP_NEW_UID} != "${USERMAP_ORIG_UID}" || ${USERMAP_NEW_GID} != "${USERMAP_ORIG_GID}" ]]; then
|
||||
echo "Mapping UID and GID for paperless:paperless to $USERMAP_NEW_UID:$USERMAP_NEW_GID"
|
||||
usermod -u "${USERMAP_NEW_UID}" paperless
|
||||
groupmod -o -g "${USERMAP_NEW_GID}" paperless
|
||||
fi
|
||||
|
||||
while !</dev/tcp/$host/$port ;
|
||||
do
|
||||
|
||||
if [ $attempt_num -eq $max_attempts ]
|
||||
then
|
||||
echo "Unable to connect to database."
|
||||
exit 1
|
||||
else
|
||||
echo "Attempt $attempt_num failed! Trying again in 5 seconds..."
|
||||
|
||||
fi
|
||||
|
||||
attempt_num=$(expr "$attempt_num" + 1)
|
||||
sleep 5
|
||||
done
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
migrations() {
|
||||
|
||||
if [[ -n "${PAPERLESS_DBHOST}" ]]
|
||||
then
|
||||
wait_for_postgres
|
||||
fi
|
||||
|
||||
(
|
||||
# flock is in place to prevent multiple containers from doing migrations
|
||||
# simultaneously. This also ensures that the db is ready when the command
|
||||
# of the current container starts.
|
||||
flock 200
|
||||
sudo -HEu paperless python3 manage.py migrate
|
||||
) 200>/usr/src/paperless/data/migration_lock
|
||||
|
||||
}
|
||||
|
||||
initialize() {
|
||||
map_uidgid
|
||||
|
||||
for dir in export data data/index media media/documents media/documents/originals media/documents/thumbnails; do
|
||||
if [[ ! -d "../$dir" ]]
|
||||
then
|
||||
echo "creating directory ../$dir"
|
||||
if [[ ! -d "../$dir" ]]; then
|
||||
echo "Creating directory ../$dir"
|
||||
mkdir ../$dir
|
||||
fi
|
||||
done
|
||||
|
||||
chown -R paperless:paperless ../
|
||||
echo "Creating directory /tmp/paperless"
|
||||
mkdir -p /tmp/paperless
|
||||
|
||||
migrations
|
||||
set +e
|
||||
echo "Adjusting permissions of paperless files. This may take a while."
|
||||
chown -R paperless:paperless /tmp/paperless
|
||||
find .. -not \( -user paperless -and -group paperless \) -exec chown paperless:paperless {} +
|
||||
set -e
|
||||
|
||||
gosu paperless /sbin/docker-prepare.sh
|
||||
}
|
||||
|
||||
install_languages() {
|
||||
echo "Installing languages..."
|
||||
|
||||
local langs="$1"
|
||||
read -ra langs <<<"$langs"
|
||||
|
||||
@@ -95,40 +50,43 @@ install_languages() {
|
||||
apt-get update
|
||||
|
||||
for lang in "${langs[@]}"; do
|
||||
pkg="tesseract-ocr-$lang"
|
||||
# English is installed by default
|
||||
#if [[ "$lang" == "eng" ]]; then
|
||||
# continue
|
||||
#fi
|
||||
pkg="tesseract-ocr-$lang"
|
||||
# English is installed by default
|
||||
#if [[ "$lang" == "eng" ]]; then
|
||||
# continue
|
||||
#fi
|
||||
|
||||
if dpkg -s $pkg &> /dev/null; then
|
||||
echo "package $pkg already installed!"
|
||||
continue
|
||||
fi
|
||||
if dpkg -s $pkg &>/dev/null; then
|
||||
echo "Package $pkg already installed!"
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! apt-cache show $pkg &> /dev/null; then
|
||||
echo "package $pkg not found! :("
|
||||
continue
|
||||
fi
|
||||
if ! apt-cache show $pkg &>/dev/null; then
|
||||
echo "Package $pkg not found! :("
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Installing package $pkg..."
|
||||
if ! apt-get -y install "$pkg" &> /dev/null; then
|
||||
echo "Could not install $pkg"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Installing package $pkg..."
|
||||
if ! apt-get -y install "$pkg" &>/dev/null; then
|
||||
echo "Could not install $pkg"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
echo "Paperless-ngx docker container starting..."
|
||||
|
||||
# Install additional languages if specified
|
||||
if [[ ! -z "$PAPERLESS_OCR_LANGUAGES" ]]; then
|
||||
install_languages "$PAPERLESS_OCR_LANGUAGES"
|
||||
if [[ ! -z "$PAPERLESS_OCR_LANGUAGES" ]]; then
|
||||
install_languages "$PAPERLESS_OCR_LANGUAGES"
|
||||
fi
|
||||
|
||||
initialize
|
||||
|
||||
if [[ "$1" != "/"* ]]; then
|
||||
exec sudo -HEu paperless python3 manage.py "$@"
|
||||
echo Executing management command "$@"
|
||||
exec gosu paperless python3 manage.py "$@"
|
||||
else
|
||||
echo Executing "$@"
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
|
72
docker/docker-prepare.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
wait_for_postgres() {
|
||||
attempt_num=1
|
||||
max_attempts=5
|
||||
|
||||
echo "Waiting for PostgreSQL to start..."
|
||||
|
||||
host="${PAPERLESS_DBHOST}"
|
||||
port="${PAPERLESS_DBPORT}"
|
||||
|
||||
if [[ -z $port ]]; then
|
||||
port="5432"
|
||||
fi
|
||||
|
||||
while ! </dev/tcp/$host/$port; do
|
||||
|
||||
if [ $attempt_num -eq $max_attempts ]; then
|
||||
echo "Unable to connect to database."
|
||||
exit 1
|
||||
else
|
||||
echo "Attempt $attempt_num failed! Trying again in 5 seconds..."
|
||||
|
||||
fi
|
||||
|
||||
attempt_num=$(expr "$attempt_num" + 1)
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
|
||||
migrations() {
|
||||
(
|
||||
# flock is in place to prevent multiple containers from doing migrations
|
||||
# simultaneously. This also ensures that the db is ready when the command
|
||||
# of the current container starts.
|
||||
flock 200
|
||||
echo "Apply database migrations..."
|
||||
python3 manage.py migrate
|
||||
) 200>/usr/src/paperless/data/migration_lock
|
||||
}
|
||||
|
||||
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..."
|
||||
python3 manage.py document_index reindex
|
||||
echo $index_version | tee $index_version_file >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
superuser() {
|
||||
if [[ -n "${PAPERLESS_ADMIN_USER}" ]]; then
|
||||
python3 manage.py manage_superuser
|
||||
fi
|
||||
}
|
||||
|
||||
do_work() {
|
||||
if [[ -n "${PAPERLESS_DBHOST}" ]]; then
|
||||
wait_for_postgres
|
||||
fi
|
||||
|
||||
migrations
|
||||
|
||||
search_index
|
||||
|
||||
superuser
|
||||
|
||||
}
|
||||
|
||||
do_work
|
@@ -1,44 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: always
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:0.9.12
|
||||
restart: always
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
@@ -1,31 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:0.9.12
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
@@ -1,43 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
image: jonaswinkler/paperless-ng:0.9.12
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
6
docker/install_management_commands.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
for command in document_archiver document_exporter document_importer mail_fetcher document_create_classifier document_index document_renamer document_retagger document_thumbnails document_sanity_checker manage_superuser;
|
||||
do
|
||||
echo "installing $command..."
|
||||
sed "s/management_command/$command/g" management_script.sh > /usr/local/bin/$command
|
||||
chmod +x /usr/local/bin/$command
|
||||
done
|
@@ -1,74 +0,0 @@
|
||||
FROM python:3.7-slim
|
||||
|
||||
WORKDIR /usr/src/paperless/
|
||||
|
||||
COPY requirements.txt ./
|
||||
|
||||
#Dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get -y --no-install-recommends install \
|
||||
build-essential \
|
||||
curl \
|
||||
file \
|
||||
fonts-liberation \
|
||||
gettext \
|
||||
ghostscript \
|
||||
gnupg \
|
||||
icc-profiles-free \
|
||||
imagemagick \
|
||||
libatlas-base-dev \
|
||||
liblept5 \
|
||||
libmagic-dev \
|
||||
libpoppler-cpp-dev \
|
||||
libpq-dev \
|
||||
libqpdf-dev \
|
||||
libxml2 \
|
||||
libxslt1-dev \
|
||||
optipng \
|
||||
pngquant \
|
||||
qpdf \
|
||||
sudo \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-eng \
|
||||
tesseract-ocr-deu \
|
||||
tesseract-ocr-fra \
|
||||
tesseract-ocr-ita \
|
||||
tesseract-ocr-spa \
|
||||
tzdata \
|
||||
unpaper \
|
||||
zlib1g \
|
||||
&& pip3 install --upgrade supervisor setuptools \
|
||||
&& pip install --no-cache-dir -r requirements.txt \
|
||||
&& apt-get -y purge build-essential libqpdf-dev \
|
||||
&& apt-get -y autoremove --purge \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir /var/log/supervisord /var/run/supervisord
|
||||
|
||||
# copy scripts
|
||||
# this fixes issues with imagemagick and PDF
|
||||
COPY docker/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
COPY docker/gunicorn.conf.py ./
|
||||
COPY docker/supervisord.conf /etc/supervisord.conf
|
||||
COPY docker/docker-entrypoint.sh /sbin/docker-entrypoint.sh
|
||||
|
||||
# copy app
|
||||
COPY src/ ./src/
|
||||
|
||||
# add users, setup scripts
|
||||
RUN addgroup --gid 1000 paperless \
|
||||
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
||||
&& chown -R paperless:paperless . \
|
||||
&& chmod 755 /sbin/docker-entrypoint.sh
|
||||
|
||||
WORKDIR /usr/src/paperless/src/
|
||||
|
||||
RUN sudo -HEu paperless python3 manage.py collectstatic --clear --no-input
|
||||
|
||||
RUN sudo -HEu paperless python3 manage.py compilemessages
|
||||
|
||||
VOLUME ["/usr/src/paperless/data", "/usr/src/paperless/media", "/usr/src/paperless/consume", "/usr/src/paperless/export"]
|
||||
ENTRYPOINT ["/sbin/docker-entrypoint.sh"]
|
||||
EXPOSE 8000
|
||||
CMD ["/usr/local/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
||||
|
||||
LABEL maintainer="Jonas Winkler <dev@jpwinkler.de>"
|
@@ -1,44 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
db:
|
||||
image: postgres:13
|
||||
restart: always
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: paperless
|
||||
POSTGRES_USER: paperless
|
||||
POSTGRES_PASSWORD: paperless
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
restart: always
|
||||
depends_on:
|
||||
- db
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_DBHOST: db
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
pgdata:
|
@@ -1,31 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
@@ -1,43 +0,0 @@
|
||||
version: "3.4"
|
||||
services:
|
||||
broker:
|
||||
image: redis:6.0
|
||||
restart: always
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
restart: always
|
||||
depends_on:
|
||||
- broker
|
||||
ports:
|
||||
- 8000:8000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
volumes:
|
||||
- data:/usr/src/paperless/data
|
||||
- media:/usr/src/paperless/media
|
||||
- ./export:/usr/src/paperless/export
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
15
docker/management_script.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd /usr/src/paperless/src/
|
||||
|
||||
if [[ $(id -u) == 0 ]] ;
|
||||
then
|
||||
gosu paperless python3 manage.py management_command "$@"
|
||||
elif [[ $(id -un) == "paperless" ]] ;
|
||||
then
|
||||
python3 manage.py management_command "$@"
|
||||
else
|
||||
echo "Unknown user."
|
||||
fi
|
@@ -8,7 +8,7 @@ loglevel=info ; log level; default info; others: debug,warn,trace
|
||||
user=root
|
||||
|
||||
[program:gunicorn]
|
||||
command=gunicorn -c /usr/src/paperless/gunicorn.conf.py paperless.wsgi
|
||||
command=gunicorn -c /usr/src/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
user=paperless
|
||||
|
||||
stdout_logfile=/dev/stdout
|
||||
|
BIN
docs/_static/screenshots/documents-wchrome-dark.png
vendored
Normal file
After Width: | Height: | Size: 680 KiB |
BIN
docs/_static/screenshots/documents-wchrome.png
vendored
Normal file
After Width: | Height: | Size: 686 KiB |
@@ -20,6 +20,14 @@ Options available to any installation of paperless:
|
||||
metadata to a specific folder. You may import your documents into a
|
||||
fresh instance of paperless again or store your documents in another
|
||||
DMS with this export.
|
||||
* The document exporter is also able to update an already existing export.
|
||||
Therefore, incremental backups with ``rsync`` are entirely possible.
|
||||
|
||||
.. caution::
|
||||
|
||||
You cannot import the export generated with one version of paperless in a
|
||||
different version of paperless. The export contains an exact image of the
|
||||
database, and migrations may change the database layout.
|
||||
|
||||
Options available to docker installations:
|
||||
|
||||
@@ -48,17 +56,17 @@ Options available to bare-metal and non-docker installations:
|
||||
Restoring
|
||||
=========
|
||||
|
||||
|
||||
|
||||
|
||||
.. _administration-updating:
|
||||
|
||||
Updating paperless
|
||||
Updating Paperless
|
||||
##################
|
||||
|
||||
If a new release of paperless-ng is available, upgrading depends on how you
|
||||
installed paperless-ng in the first place. The releases are available at
|
||||
`release page <https://github.com/jonaswinkler/paperless-ng/releases>`_.
|
||||
Docker Route
|
||||
============
|
||||
|
||||
If a new release of paperless-ngx is available, upgrading depends on how you
|
||||
installed paperless-ngx in the first place. The releases are available at the
|
||||
`release page <https://github.com/paperless-ngx/paperless-ngx/releases>`_.
|
||||
|
||||
First of all, ensure that paperless is stopped.
|
||||
|
||||
@@ -69,112 +77,130 @@ First of all, ensure that paperless is stopped.
|
||||
|
||||
After that, :ref:`make a backup <administration-backup>`.
|
||||
|
||||
A. If you used the dockerfiles archive, simply download the files of the new release,
|
||||
adjust the settings in the files (i.e., the path to your consumption directory),
|
||||
and replace your existing docker-compose files. Then start paperless as usual,
|
||||
which will pull the new image, and update your database, if necessary:
|
||||
A. If you pull the image from the docker hub, all you need to do is:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ docker-compose pull
|
||||
$ docker-compose up
|
||||
|
||||
If you see everything working, you can start paperless-ng with "-d" to have it
|
||||
run in the background.
|
||||
The docker-compose files refer to the ``latest`` version, which is always the latest
|
||||
stable release.
|
||||
|
||||
.. hint::
|
||||
|
||||
The released docker-compose files specify exact versions to be pulled from the hub.
|
||||
This is to ensure that if the docker-compose files should change at some point
|
||||
(i.e., services updates/configured differently), you wont run into trouble due to
|
||||
docker pulling the ``latest`` image and running it in an older environment.
|
||||
|
||||
B. If you built the image yourself, grab the new archive and replace your current
|
||||
paperless folder with the new contents.
|
||||
|
||||
After that, make the necessary adjustments to the docker-compose.yml (i.e.,
|
||||
adjust your consumption directory).
|
||||
|
||||
Build and start the new image with:
|
||||
B. If you built the image yourself, do the following:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ git pull
|
||||
$ docker-compose build
|
||||
$ docker-compose up
|
||||
|
||||
If you see everything working, you can start paperless-ng with "-d" to have it
|
||||
run in the background.
|
||||
Running ``docker-compose up`` will also apply any new database migrations.
|
||||
If you see everything working, press CTRL+C once to gracefully stop paperless.
|
||||
Then you can start paperless-ngx with ``-d`` to have it run in the background.
|
||||
|
||||
.. hint::
|
||||
.. note::
|
||||
|
||||
You can usually keep your ``docker-compose.env`` file, since this file will
|
||||
never include mandatory configuration options. However, it is worth checking
|
||||
out the new version of this file, since it might have new recommendations
|
||||
on what to configure.
|
||||
In version 0.9.14, the update process was changed. In 0.9.13 and earlier, the
|
||||
docker-compose files specified exact versions and pull won't automatically
|
||||
update to newer versions. In order to enable updates as described above, either
|
||||
get the new ``docker-compose.yml`` file from `here <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`_
|
||||
or edit the ``docker-compose.yml`` file, find the line that says
|
||||
|
||||
.. code::
|
||||
|
||||
Updating paperless without docker
|
||||
=================================
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:0.9.x
|
||||
|
||||
and replace the version with ``latest``:
|
||||
|
||||
.. code::
|
||||
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
|
||||
Bare Metal Route
|
||||
================
|
||||
|
||||
After grabbing the new release and unpacking the contents, do the following:
|
||||
|
||||
1. Update dependencies. New paperless version may require additional
|
||||
dependencies. The dependencies required are listed in the section about
|
||||
dependencies. The dependencies required are listed in the section about
|
||||
:ref:`bare metal installations <setup-bare_metal>`.
|
||||
|
||||
2. Update python requirements. If you use Pipenv, this is done with the following steps.
|
||||
2. Update python requirements. Keep in mind to activate your virtual environment
|
||||
before that, if you use one.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ pip install --upgrade pipenv
|
||||
$ cd /path/to/paperless
|
||||
$ pipenv clean
|
||||
$ pipenv install
|
||||
$ pip install -r requirements.txt
|
||||
|
||||
This creates a new virtual environment (or uses your existing environment)
|
||||
and installs all dependencies into it.
|
||||
|
||||
3. Collect static files.
|
||||
3. Migrate the database.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd src
|
||||
$ pipenv run python3 manage.py collectstatic --clear
|
||||
|
||||
4. Migrate the database.
|
||||
$ python3 manage.py migrate
|
||||
|
||||
.. code:: shell-session
|
||||
This might not actually do anything. Not every new paperless version comes with new
|
||||
database migrations.
|
||||
|
||||
$ cd src
|
||||
$ pipenv run python3 manage.py migrate
|
||||
|
||||
5. Update translation files.
|
||||
Downgrading Paperless
|
||||
#####################
|
||||
|
||||
.. code:: shell-session
|
||||
Downgrades are possible. However, some updates also contain database migrations (these change the layout of the database and may move data).
|
||||
In order to move back from a version that applied database migrations, you'll have to revert the database migration *before* downgrading,
|
||||
and then downgrade paperless.
|
||||
|
||||
This table lists the compatible versions for each database migration number.
|
||||
|
||||
+------------------+-----------------+
|
||||
| Migration number | Version range |
|
||||
+------------------+-----------------+
|
||||
| 1011 | 1.0.0 |
|
||||
+------------------+-----------------+
|
||||
| 1012 | 1.1.0 - 1.2.1 |
|
||||
+------------------+-----------------+
|
||||
| 1014 | 1.3.0 - 1.3.1 |
|
||||
+------------------+-----------------+
|
||||
| 1016 | 1.3.2 - current |
|
||||
+------------------+-----------------+
|
||||
|
||||
Execute the following management command to migrate your database:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ python3 manage.py migrate documents <migration number>
|
||||
|
||||
.. note::
|
||||
|
||||
Some migrations cannot be undone. The command will issue errors if that happens.
|
||||
|
||||
.. _utilities-management-commands:
|
||||
|
||||
$ cd src
|
||||
$ pipenv run python3 manage.py compilemessages
|
||||
|
||||
Management utilities
|
||||
####################
|
||||
|
||||
Paperless comes with some management commands that perform various maintenance
|
||||
tasks on your paperless instance. You can invoke these commands either by
|
||||
tasks on your paperless instance. You can invoke these commands in the following way:
|
||||
|
||||
With docker-compose, while paperless is running:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ docker-compose run --rm webserver <command> <arguments>
|
||||
$ docker-compose exec webserver <command> <arguments>
|
||||
|
||||
or
|
||||
With docker, while paperless is running:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker exec -it <container-name> <command> <arguments>
|
||||
|
||||
Bare metal:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/src
|
||||
$ pipenv run python manage.py <command> <arguments>
|
||||
|
||||
depending on whether you use docker or not.
|
||||
$ python3 manage.py <command> <arguments>
|
||||
|
||||
All commands have built-in help, which can be accessed by executing them with
|
||||
the argument ``--help``.
|
||||
@@ -187,9 +213,16 @@ Document exporter
|
||||
The document exporter exports all your data from paperless into a folder for
|
||||
backup or migration to another DMS.
|
||||
|
||||
If you use the document exporter within a cronjob to backup your data you might use the ``-T`` flag behind exec to suppress "The input device is not a TTY" errors. For example: ``docker-compose exec -T webserver document_exporter ../export``
|
||||
|
||||
.. code::
|
||||
|
||||
document_exporter target
|
||||
document_exporter target [-c] [-f] [-d]
|
||||
|
||||
optional arguments:
|
||||
-c, --compare-checksums
|
||||
-f, --use-filename-format
|
||||
-d, --delete
|
||||
|
||||
``target`` is a folder to which the data gets written. This includes documents,
|
||||
thumbnails and a ``manifest.json`` file. The manifest contains all metadata from
|
||||
@@ -199,6 +232,24 @@ When you use the provided docker compose script, specify ``../export`` as the
|
||||
target. This path inside the container is automatically mounted on your host on
|
||||
the folder ``export``.
|
||||
|
||||
If the target directory already exists and contains files, paperless will assume
|
||||
that the contents of the export directory are a previous export and will attempt
|
||||
to update the previous export. Paperless will only export changed and added files.
|
||||
Paperless determines whether a file has changed by inspecting the file attributes
|
||||
"date/time modified" and "size". If that does not work out for you, specify
|
||||
``--compare-checksums`` and paperless will attempt to compare file checksums instead.
|
||||
This is slower.
|
||||
|
||||
Paperless will not remove any existing files in the export directory. If you want
|
||||
paperless to also remove files that do not belong to the current export such as files
|
||||
from deleted documents, specify ``--delete``. Be careful when pointing paperless to
|
||||
a directory that already contains other files.
|
||||
|
||||
The filenames generated by this command follow the format
|
||||
``[date created] [correspondent] [title].[extension]``.
|
||||
If you want paperless to use ``PAPERLESS_FILENAME_FORMAT`` for exported filenames
|
||||
instead, specify ``--use-filename-format``.
|
||||
|
||||
|
||||
.. _utilities-importer:
|
||||
|
||||
@@ -328,6 +379,36 @@ the naming scheme.
|
||||
|
||||
The command takes no arguments and processes all your documents at once.
|
||||
|
||||
Learn how to use :ref:`Management Utilities<Management utilities>`.
|
||||
|
||||
|
||||
.. _utilities-sanity-checker:
|
||||
|
||||
Sanity checker
|
||||
==============
|
||||
|
||||
Paperless has a built-in sanity checker that inspects your document collection for issues.
|
||||
|
||||
The issues detected by the sanity checker are as follows:
|
||||
|
||||
* Missing original files.
|
||||
* Missing archive files.
|
||||
* Inaccessible original files due to improper permissions.
|
||||
* Inaccessible archive files due to improper permissions.
|
||||
* Corrupted original documents by comparing their checksum against what is stored in the database.
|
||||
* Corrupted archive documents by comparing their checksum against what is stored in the database.
|
||||
* Missing thumbnails.
|
||||
* Inaccessible thumbnails due to improper permissions.
|
||||
* Documents without any content (warning).
|
||||
* Orphaned files in the media directory (warning). These are files that are not referenced by any document im paperless.
|
||||
|
||||
|
||||
.. code::
|
||||
|
||||
document_sanity_checker
|
||||
|
||||
The command takes no arguments. Depending on the size of your document archive, this may take some time.
|
||||
|
||||
|
||||
Fetching e-mail
|
||||
===============
|
||||
@@ -387,13 +468,13 @@ Documents can be stored in Paperless using GnuPG encryption.
|
||||
|
||||
.. danger::
|
||||
|
||||
Encryption is deprecated since paperless-ng 0.9 and doesn't really provide any
|
||||
Encryption is deprecated since paperless-ngx 0.9 and doesn't really provide any
|
||||
additional security, since you have to store the passphrase in a configuration
|
||||
file on the same system as the encrypted documents for paperless to work.
|
||||
Furthermore, the entire text content of the documents is stored plain in the
|
||||
database, even if your documents are encrypted. Filenames are not encrypted as
|
||||
well.
|
||||
|
||||
|
||||
Also, the web server provides transparent access to your encrypted documents.
|
||||
|
||||
Consider running paperless on an encrypted filesystem instead, which will then
|
||||
@@ -416,6 +497,3 @@ Basic usage to disable encryption of your document store:
|
||||
.. code::
|
||||
|
||||
decrypt_documents [--passphrase SECR3TP4SSPHRA$E]
|
||||
|
||||
|
||||
.. _Pipenv: https://pipenv.pypa.io/en/latest/
|
@@ -10,22 +10,21 @@ 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
|
||||
The matching logic is quite powerful. It supports searching the text of your
|
||||
document with different algorithms, and as such, some experimentation may be
|
||||
necessary to get things right.
|
||||
|
||||
In order to have a tag, correspondent or type assigned automatically to newly
|
||||
In order to have a tag, correspondent, or type assigned automatically to newly
|
||||
consumed documents, assign a match and matching algorithm using the web
|
||||
interface. These settings define when to assign correspondents, tags and types
|
||||
interface. These settings define when to assign correspondents, tags, and types
|
||||
to documents.
|
||||
|
||||
The following algorithms are available:
|
||||
@@ -35,16 +34,16 @@ The following algorithms are available:
|
||||
either of these terms.
|
||||
* **All:** Requires that every word provided appears in the PDF, albeit not in the
|
||||
order provided.
|
||||
* **Literal:** Matches only if the match appears exactly as provided in the PDF.
|
||||
* **Literal:** Matches only if the match appears exactly as provided (i.e. preserve ordering) in the PDF.
|
||||
* **Regular expression:** Parses the match as a regular expression and tries to
|
||||
find a match within the document.
|
||||
* **Fuzzy match:** I dont know. Look at the source.
|
||||
* **Auto:** Tries to automatically match new documents. This does not require you
|
||||
to set a match. See the notes below.
|
||||
|
||||
When using the "any" or "all" matching algorithms, you can search for terms
|
||||
When using the *any* or *all* matching algorithms, you can search for terms
|
||||
that consist of multiple words by enclosing them in double quotes. For example,
|
||||
defining a match text of ``"Bank of America" BofA`` using the "any" algorithm,
|
||||
defining a match text of ``"Bank of America" BofA`` using the *any* algorithm,
|
||||
will match documents that contain either "Bank of America" or "BofA", but will
|
||||
not match documents containing "Bank of South America".
|
||||
|
||||
@@ -58,9 +57,9 @@ automatically tagged with the appropriate data.
|
||||
Automatic matching
|
||||
==================
|
||||
|
||||
Paperless-ng comes with a new matching algorithm called *Auto*. This matching
|
||||
algorithm tries to assign tags, correspondents and document types to your
|
||||
documents based on how you have assigned these on existing documents. It
|
||||
Paperless-ngx comes with a new matching algorithm called *Auto*. This matching
|
||||
algorithm tries to assign tags, correspondents, and document types to your
|
||||
documents based on how you have already assigned these on existing documents. It
|
||||
uses a neural network under the hood.
|
||||
|
||||
If, for example, all your bank statements of your account 123 at the Bank of
|
||||
@@ -77,11 +76,11 @@ feature:
|
||||
changes. Paperless periodically (default: once each hour) checks for changes
|
||||
and does this automatically for you.
|
||||
* The Auto matching algorithm only takes documents into account which are NOT
|
||||
placed in your inbox (i.e., have inbox tags assigned to them). This ensures
|
||||
placed in your inbox (i.e. have any inbox tags assigned to them). This ensures
|
||||
that the neural network only learns from documents which you have correctly
|
||||
tagged before.
|
||||
* The matching algorithm can only work if there is a correlation between the
|
||||
tag, correspondent or document type and the document itself. Your bank
|
||||
tag, correspondent, or document type and the document itself. Your bank
|
||||
statements usually contain your bank account number and the name of the bank,
|
||||
so this works reasonably well, However, tags such as "TODO" cannot be
|
||||
automatically assigned.
|
||||
@@ -105,7 +104,7 @@ you execute scripts of your own choosing just before or after a document is
|
||||
consumed using a couple simple hooks.
|
||||
|
||||
Just write a script, put it somewhere that Paperless can read & execute, and
|
||||
then put the path to that script in ``paperless.conf`` with the variable name
|
||||
then put the path to that script in ``paperless.conf`` or ``docker-compose.env`` with the variable name
|
||||
of either ``PAPERLESS_PRE_CONSUME_SCRIPT`` or
|
||||
``PAPERLESS_POST_CONSUME_SCRIPT``.
|
||||
|
||||
@@ -168,12 +167,40 @@ into paperless. It receives the following arguments:
|
||||
* Correspondent
|
||||
* Tags
|
||||
|
||||
The script can be in any language you like, but for a simple shell script
|
||||
example, you can take a look at ``post-consumption-example.sh`` in the
|
||||
``scripts`` directory in this project.
|
||||
The script can be in any language, but for a simple shell script
|
||||
example, you can take a look at `post-consumption-example.sh`_ in this project.
|
||||
|
||||
The post consumption script cannot cancel the consumption process.
|
||||
|
||||
Docker
|
||||
------
|
||||
Assumed you have ``/home/foo/paperless-ngx/scripts/post-consumption-example.sh``.
|
||||
|
||||
You can pass that script into the consumer container via a host mount in your ``docker-compose.yml``.
|
||||
|
||||
.. code:: bash
|
||||
...
|
||||
consumer:
|
||||
...
|
||||
volumes:
|
||||
...
|
||||
- /home/paperless-ngx/scripts:/path/in/container/scripts/
|
||||
...
|
||||
|
||||
Example (docker-compose.yml): ``- /home/foo/paperless-ngx/scripts:/usr/src/paperless/scripts``
|
||||
|
||||
which in turn requires the variable ``PAPERLESS_POST_CONSUME_SCRIPT`` in ``docker-compose.env`` to point to ``/path/in/container/scripts/post-consumption-example.sh``.
|
||||
|
||||
Example (docker-compose.env): ``PAPERLESS_POST_CONSUME_SCRIPT=/usr/src/paperless/scripts/post-consumption-example.sh``
|
||||
|
||||
Troubleshooting:
|
||||
|
||||
- Monitor the docker-compose log ``cd ~/paperless-ngx; docker-compose logs -f``
|
||||
- Check your script's permission e.g. in case of permission error ``sudo chmod 755 post-consumption-example.sh``
|
||||
- Pipe your scripts's output to a log file e.g. ``echo "${DOCUMENT_ID}" | tee --append /usr/src/paperless/scripts/post-consumption-example.log``
|
||||
|
||||
.. _post-consumption-example.sh: https://github.com/jonaswinkler/paperless-ngx/blob/master/scripts/post-consumption-example.sh
|
||||
|
||||
.. _advanced-file_name_handling:
|
||||
|
||||
File name handling
|
||||
@@ -217,18 +244,19 @@ will create a directory structure as follows:
|
||||
|
||||
Paperless provides the following placeholders withing filenames:
|
||||
|
||||
* ``{asn}``: The archive serial number of the document, or "none".
|
||||
* ``{correspondent}``: The name of the correspondent, or "none".
|
||||
* ``{document_type}``: The name of the document type, or "none".
|
||||
* ``{tag_list}``: A comma separated list of all tags assigned to the document.
|
||||
* ``{title}``: The title of the document.
|
||||
* ``{created}``: The full date and time the document was created.
|
||||
* ``{created}``: The full date (ISO format) the document was created.
|
||||
* ``{created_year}``: Year created only.
|
||||
* ``{created_month}``: Month created only (number 1-12).
|
||||
* ``{created_day}``: Day created only (number 1-31).
|
||||
* ``{added}``: The full date and time the document was added to paperless.
|
||||
* ``{created_month}``: Month created only (number 01-12).
|
||||
* ``{created_day}``: Day created only (number 01-31).
|
||||
* ``{added}``: The full date (ISO format) the document was added to paperless.
|
||||
* ``{added_year}``: Year added only.
|
||||
* ``{added_month}``: Month added only (number 1-12).
|
||||
* ``{added_day}``: Day added only (number 1-31).
|
||||
* ``{added_month}``: Month added only (number 01-12).
|
||||
* ``{added_day}``: Day added only (number 01-31).
|
||||
|
||||
|
||||
Paperless will try to conserve the information from your database as much as possible.
|
||||
|
162
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 <https://whoosh.readthedocs.io/en/latest/querylang.html>`_
|
||||
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 <span class=\"match\">Test</span> 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/<id>/``.
|
||||
|
||||
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 ``<span>`` tags as shown above.
|
||||
* ``rank`` is the index of the search results. The first result will have rank 0.
|
||||
|
||||
``/api/search/autocomplete/``
|
||||
=============================
|
||||
@@ -284,3 +248,53 @@ The endpoint supports the following optional form fields:
|
||||
The endpoint will immediately return "OK" if the document consumption process
|
||||
was started successfully. No additional status information about the consumption
|
||||
process itself is available, since that happens in a different process.
|
||||
|
||||
|
||||
.. _api-versioning:
|
||||
|
||||
API Versioning
|
||||
##############
|
||||
|
||||
The REST API is versioned since Paperless-ngx 1.3.0.
|
||||
|
||||
* Versioning ensures that changes to the API don't break older clients.
|
||||
* Clients specify the specific version of the API they wish to use with every request and Paperless will handle the request using the specified API version.
|
||||
* Even if the underlying data model changes, older API versions will always serve compatible data.
|
||||
* If no version is specified, Paperless will serve version 1 to ensure compatibility with older clients that do not request a specific API version.
|
||||
|
||||
API versions are specified by submitting an additional HTTP ``Accept`` header with every request:
|
||||
|
||||
.. code::
|
||||
|
||||
Accept: application/json; version=6
|
||||
|
||||
If an invalid version is specified, Paperless 1.3.0 will respond with "406 Not Acceptable" and an error message in the body.
|
||||
Earlier versions of Paperless will serve API version 1 regardless of whether a version is specified via the ``Accept`` header.
|
||||
|
||||
If a client wishes to verify whether it is compatible with any given server, the following procedure should be performed:
|
||||
|
||||
1. Perform an *authenticated* request against any API endpoint. If the server is on version 1.3.0 or newer, the server will
|
||||
add two custom headers to the response:
|
||||
|
||||
.. code::
|
||||
|
||||
X-Api-Version: 2
|
||||
X-Version: 1.3.0
|
||||
|
||||
2. Determine whether the client is compatible with this server based on the presence/absence of these headers and their values if present.
|
||||
|
||||
|
||||
API Changelog
|
||||
=============
|
||||
|
||||
Version 1
|
||||
---------
|
||||
|
||||
Initial API version.
|
||||
|
||||
Version 2
|
||||
---------
|
||||
|
||||
* Added field ``Tag.color``. This read/write string field contains a hex color such as ``#a6cee3``.
|
||||
* Added read-only field ``Tag.text_color``. This field contains the text color to use for a specific tag, which is either black or white depending on the brightness of ``Tag.color``.
|
||||
* Removed field ``Tag.colour``.
|
||||
|
@@ -5,6 +5,450 @@
|
||||
Changelog
|
||||
*********
|
||||
|
||||
paperless-ngx 1.6.0
|
||||
###################
|
||||
|
||||
This is the first release of the revived paperless-ngx project 🎉. Thank you to everyone on the paperless-ngx team for your initiative and excellent teamwork!
|
||||
|
||||
Version 1.6.0 merges several pending PRs from jonaswinkler's repo and includes new feature updates and bug fixes. Major backend and UI changes include:
|
||||
|
||||
* Updated docs, scripts, CI, and containers to paperless-ngx.
|
||||
* Updated Python and Angular dependencies.
|
||||
* Dropped support for Python 3.7.
|
||||
* Dropped support for Ansible playbooks (thanks `@slankes`_ #109). If someone would like to continue supporting them, please see the `ansible repo`_.
|
||||
* Python code is now required to use Black formatting (thanks `@kpj`_ #168).
|
||||
* `@tribut`_ added support for a custom SSO logout redirect (jonaswinkler#1258). See ``PAPERLESS_LOGOUT_REDIRECT_URL``.
|
||||
* `@shamoon`_ added a loading indicator when document list is reloading (jonaswinkler#1297).
|
||||
* `@shamoon`_ improved the PDF viewer on mobile (#2).
|
||||
* `@shamoon`_ added 'any' / 'all' and 'not' filtering with tags (#10).
|
||||
* `@shamoon`_ added warnings for unsaved changes, with smart edit buttons (#13).
|
||||
* `@benjaminfrank`_ enabled a non-root access to port 80 via systemd (#18).
|
||||
* `@amenk`_ fixed the search box overlay menu on mobile (#32).
|
||||
* `@dblitt`_ updated the login form to not auto-capitalize usernames (#36).
|
||||
* `@evilsidekick293`_ made the worker timeout configurable (#37). See ``PAPERLESS_WORKER_TIMEOUT``.
|
||||
* `@Nicarim`_ fixed downloads of UTF-8 formatted documents in Firefox (#56).
|
||||
* `@mweimerskirch`_ sorted the language dropdown by locale (#78).
|
||||
* `@mweimerskirch`_ enabled the Czech (#83) and Danish (#84) translations.
|
||||
* `@cschmatzler`_ enabled specifying the webserver port (#124). See ``PAPERLESS_PORT``.
|
||||
* `@muellermartin`_ fixed an error when uploading transparent PNGs (#133).
|
||||
* `@shamoon`_ created a slick new logo (#165).
|
||||
* `@tim-vogel`_ fixed exports missing groups (#193).
|
||||
|
||||
Thank you to the following people for their documentation updates, fixes, and comprehensive testing:
|
||||
|
||||
`@m0veax`_, `@a17t`_, `@fignew`_, `@muued`_, `@bauerj`_, `@isigmund`_, `@denilsonsa`_, `@mweimerskirch`_, `@alexander-bauer`_, `@apeltzer`_, `@tribut`_, `@yschroeder`_, `@gador`_, `@sAksham-Ar`_, `@sbrunner`_, `@philpagel`_, `@davemachado`_, `@2600box`_, `@qcasey`_, `@Nicarim`_, `@kpj`_, `@filcuk`_, `@Timoms`_, `@mattlamb99`_, `@padraigkitterick`_, `@ajkavanagh`_, `@Tooa`_, `@Unkn0wnCat`_, `@pewter77`_, `@stumpylog`_, `@Toxix`_, `@azapater`_, `@jschpp`_
|
||||
|
||||
Another big thanks to the people who have contributed translations:
|
||||
|
||||
* Michel Weimerskirch (michel_weimerskirch) suggested 31 translations into French and Luxembourgish.
|
||||
* jo.vandeginste suggested 21 translations into Dutch.
|
||||
* Lars Sørensen (Lrss) suggested 486 translations into Danish.
|
||||
* Alex (Sky-Dragon) voted for 46 translations in German.
|
||||
* Yannic Schröder (yschroeder) suggested 14 translations into German.
|
||||
* David Morais Ferreira (DavidMoraisFerreira) voted for 10 translations in Portuguese and Luxembourgish.
|
||||
* David Morais Ferreira (DavidMoraisFerreira) suggested 88 translations into French, German, Portuguese, Portuguese, Brazilian and Luxembourgish.
|
||||
* 汪泠沣 (wlfcss) suggested 13 translations into Chinese Traditional.
|
||||
* Lars Sørensen (Lrss) suggested 167 translations into Danish.
|
||||
* Philmo67 suggested 11 translations into French.
|
||||
|
||||
paperless-ng 1.5.0
|
||||
##################
|
||||
|
||||
Support for Python 3.6 was dropped.
|
||||
|
||||
* Updated python dependencies.
|
||||
* Base image of the docker image changed from Debian Buster to Debian Bullseye due to its recent release.
|
||||
* The docker image now uses python 3.9.
|
||||
* Added the Luxembourgish locale. Thanks for translating!
|
||||
* `Daniel Albers`_ added support for making the files and folders ignored by the paperless consume folder scanner configurable. See ``PAPERLESS_CONSUMER_IGNORE_PATTERNS``.
|
||||
|
||||
paperless-ng 1.4.5
|
||||
##################
|
||||
|
||||
This is a maintenance release.
|
||||
|
||||
* Updated Python and Angular dependencies.
|
||||
* Changed the algorithm that changes permissions during startup. This is still fast,
|
||||
and will hopefully cause less issues.
|
||||
* Fixed an issue that would sometimes cause paperless to write an incomplete
|
||||
classification model file to disk.
|
||||
* Fixed an issue with the OCRmyPDF parser that would always try to extract text
|
||||
with PDFminer even from non-PDF files.
|
||||
|
||||
paperless-ng 1.4.4
|
||||
##################
|
||||
|
||||
* Drastically decreased the startup time of the docker container. The startup script adjusts file permissions of all data only if changes are required.
|
||||
* Paperless mail: Added ability to specify the character set for each server.
|
||||
* Document consumption: Ignore Mac OS specific files such as ``.DS_STORE`` and ``._XXXXX.pdf``.
|
||||
* Fixed an issue with the automatic matching algorithm that prevents paperless from consuming new files.
|
||||
* Updated translations.
|
||||
|
||||
paperless-ng 1.4.3
|
||||
##################
|
||||
|
||||
* Additions and changes
|
||||
|
||||
* Added Swedish locale.
|
||||
* `Stéphane Brunner`_ added an option to disable the progress bars of all management commands.
|
||||
* `Jo Vandeginste`_ added support for RTF documents to the Apache TIKA parser.
|
||||
* `Michael Shamoon`_ added dark mode for the login and logout pages.
|
||||
* `Alexander Menk`_ added additional stylesheets for printing. You can now print any page of paperless and the print result will hide the page header, sidebar, and action buttons.
|
||||
* Added support for sorting when using full text search.
|
||||
|
||||
* Fixes
|
||||
|
||||
* `puuu`_ fixed ``PAPERLESS_FORCE_SCRIPT_NAME``. You can now host paperless on sub paths such as ``https://localhost:8000/paperless/``.
|
||||
* Fixed an issue with the document consumer crashing on certain documents due to issues with pdfminer.six. This library is used for PDF text extraction.
|
||||
|
||||
paperless-ng 1.4.2
|
||||
##################
|
||||
|
||||
* Fixed an issue with ``sudo`` that caused paperless to not start on many Raspberry Pi devices. Thank you `WhiteHatTux`_!
|
||||
|
||||
paperless-ng 1.4.1
|
||||
##################
|
||||
|
||||
* Added Polish locale.
|
||||
|
||||
* Changed some parts of the Dockerfile to hopefully restore functionality on certain ARM devices.
|
||||
|
||||
* Updated python dependencies.
|
||||
|
||||
* `Michael Shamoon`_ added a sticky filter / bulk edit bar.
|
||||
|
||||
* `sbrl`_ changed the docker-entrypoint.sh script to increase compatibility with NFS shares.
|
||||
|
||||
* `Chris Nagy`_ added support for creating a super user by passing ``PAPERLESS_ADMIN_USER`` and
|
||||
``PAPERLESS_ADMIN_PASSWORD`` as environment variables to the docker container.
|
||||
|
||||
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
|
||||
|
||||
* Firefox only: Highlight search query in PDF previews.
|
||||
|
||||
* New URL pattern for accessing documents by ASN directly (http://<paperless>/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`).
|
||||
|
||||
paperless-ng 1.3.2
|
||||
##################
|
||||
|
||||
* Added translation into Portuguese.
|
||||
|
||||
* Changes
|
||||
|
||||
* The exporter now exports user accounts, mail accounts, mail rules and saved views as well.
|
||||
|
||||
* Fixes
|
||||
|
||||
* Minor layout issues with document cards and the log viewer.
|
||||
|
||||
* Fixed an issue with any/all/exact matching when characters used in regular expressions were used for the match.
|
||||
|
||||
paperless-ng 1.3.1
|
||||
##################
|
||||
|
||||
* Added translation into Spanish and Russian.
|
||||
|
||||
* Other changes
|
||||
|
||||
* ISO-8601 date format will now always show years with 4 digits.
|
||||
|
||||
* Added the ability to search for a document with a specific ASN.
|
||||
|
||||
* The document cards now display ASN, types and dates in a more organized way.
|
||||
|
||||
* Added document previews when hovering over the preview button.
|
||||
|
||||
* Fixes
|
||||
|
||||
* The startup check for write permissions now works properly on NFS shares.
|
||||
|
||||
* Fixed an issue with the search results score indicator.
|
||||
|
||||
* Paperless was unable to generate thumbnails for encrypted PDF files and failed. Paperless will now generate a default thumbnail for these files.
|
||||
|
||||
* Fixed ``AUTO_LOGIN_USERNAME``: Unable to perform POST/PUT/DELETE requests and unable to receive WebSocket messages.
|
||||
|
||||
paperless-ng 1.3.0
|
||||
##################
|
||||
|
||||
This release contains new database migrations.
|
||||
|
||||
* Changes
|
||||
|
||||
* The REST API is versioned from this point onwards. This will allow me to make changes without breaking existing clients. See the documentation about :ref:`api-versioning` for details.
|
||||
|
||||
* Added a color picker for tag colors.
|
||||
|
||||
* Added the ability to use the filter for searching the document content as well.
|
||||
|
||||
* Added translations into Italian and Romanian. Thank you!
|
||||
|
||||
* Close individual documents from the sidebar. Thanks to `Michael Shamoon`_.
|
||||
|
||||
* `BolkoSchreiber <https://github.com/BolkoSchreiber>`_ added an option to disable/enable thumbnail inversion in dark mode.
|
||||
|
||||
* `Simon Taddiken <https://github.com/skuzzle>`_ added the ability to customize the header used for remote user authentication with SSO applications.
|
||||
|
||||
* Bug fixes
|
||||
|
||||
* Fixed an issue with the auto matching algorithm when more than 256 tags were used.
|
||||
|
||||
|
||||
paperless-ng 1.2.1
|
||||
##################
|
||||
|
||||
* `Rodrigo Avelino <https://github.com/rodavelino>`_ translated Paperless into Portuguese (Brazil)!
|
||||
|
||||
* The date input fields now respect the currently selected date format.
|
||||
|
||||
* Added a fancy icon when adding paperless to the home screen on iOS devices. Thanks to `Joel Nordell <https://github.com/joelnordell>`_.
|
||||
|
||||
* When using regular expression matching, the regular expression is now validated before saving the tag/correspondent/type.
|
||||
|
||||
* Regression fix: Dates on the front end did not respect date locale settings in some cases.
|
||||
|
||||
paperless-ng 1.2.0
|
||||
##################
|
||||
|
||||
* Changes to the OCRmyPDF integration
|
||||
|
||||
* Added support for deskewing and automatic rotation of incorrectly rotated pages. This is enabled by default, see :ref:`configuration-ocr`.
|
||||
* Better support for encrypted files.
|
||||
* Better support for various other PDF files: Paperless will now attempt to force OCR with safe options when OCR fails with the configured options.
|
||||
* Added an explicit option to skip cleaning with ``unpaper``.
|
||||
|
||||
* Download multiple selected documents as a zip archive.
|
||||
|
||||
* The document list now remembers the current page.
|
||||
|
||||
* Improved responsiveness when switching between saved views and the document list.
|
||||
|
||||
* Increased the default wait time when observing files in the consumption folder
|
||||
with polling from 1 to 5 seconds. This will decrease the likelihood of paperless
|
||||
consuming partially written files.
|
||||
|
||||
* Fixed a crash of the document archiver management command when trying to process documents with unknown mime types.
|
||||
|
||||
* Paperless no longer depends on ``libpoppler-cpp-dev``.
|
||||
|
||||
paperless-ng 1.1.4
|
||||
##################
|
||||
|
||||
* Added English (GB) locale.
|
||||
|
||||
* Added ISO-8601 date display option.
|
||||
|
||||
paperless-ng 1.1.3
|
||||
##################
|
||||
|
||||
* Added a docker-specific configuration option to adjust the number of
|
||||
worker processes of the web server. See :ref:`configuration-docker`.
|
||||
|
||||
* Some more memory usage optimizations.
|
||||
|
||||
* Don't show inbox statistics if no inbox tag is defined.
|
||||
|
||||
paperless-ng 1.1.2
|
||||
##################
|
||||
|
||||
* Always show top left corner of thumbnails, even for extra wide documents.
|
||||
|
||||
* Added a management command for executing the sanity checker directly.
|
||||
See :ref:`utilities-sanity-checker`.
|
||||
|
||||
* The weekly sanity check now reports messages in the log files.
|
||||
|
||||
* Fixed an issue with the metadata tab not reporting anything in case of missing files.
|
||||
|
||||
* Reverted a change from 1.1.0 that caused huge memory usage due to redis caching.
|
||||
|
||||
* Some memory usage optimizations.
|
||||
|
||||
paperless-ng 1.1.1
|
||||
##################
|
||||
|
||||
This release contains new database migrations.
|
||||
|
||||
* Fixed a bug in the sanity checker that would cause it to display "x not in list" errors instead of actual issues.
|
||||
|
||||
* Fixed a bug with filename generation for archive filenames that would cause the archive files of two documents to overlap.
|
||||
|
||||
* This happened when ``PAPERLESS_FILENAME_FORMAT`` is used and the filenames of two or more documents are the same, except for the file extension.
|
||||
* Paperless will now store the archive filename in the database as well instead of deriving it from the original filename, and use the
|
||||
same logic for detecting and avoiding filename clashes that's also used for original filenames.
|
||||
* The migrations will repair any missing archive files. If you're using tika, ensure that tika is running while performing the migration. Docker-compose will take care of that.
|
||||
|
||||
* Fixed a bug with thumbnail regeneration when TIKA integration was used.
|
||||
|
||||
* Added ASN as a placeholder field to the filename format.
|
||||
|
||||
* The docker image now comes with built-in shortcuts for most management commands. These are now the recommended way to execute management commands, since these
|
||||
also ensure that they're always executed as the paperless user and you're less likely to run into permission issues. See :ref:`utilities-management-commands`.
|
||||
|
||||
paperless-ng 1.1.0
|
||||
##################
|
||||
|
||||
* Document processing status
|
||||
|
||||
* Paperless now shows the status of processing documents on the dashboard in real time.
|
||||
* Status notifications when
|
||||
|
||||
* New documents are detected in the consumption folder, in mails, uploaded on the front end,
|
||||
or added with one of the mobile apps.
|
||||
* Documents are successfully added to paperless.
|
||||
* Document consumption failed (with error messages)
|
||||
|
||||
* Configuration options to enable/disable individual notifications.
|
||||
|
||||
* Live updates to document lists and saved views when new documents are added.
|
||||
|
||||
.. hint::
|
||||
|
||||
For status notifications and live updates to work, paperless now requires an `ASGI <https://asgi.readthedocs.io/en/latest/>`_-enabled
|
||||
web server. The docker images uses ``gunicorn`` and an ASGI-enabled worker called `uvicorn <http://www.uvicorn.org/>`_,
|
||||
and there is no need to configure anything.
|
||||
|
||||
For bare metal installations, changes are required for the notifications to work. Adapt the service ``paperless-webserver.service``
|
||||
to use the supplied ``gunicorn.conf.py`` configuration file and adapt the reference to the ASGI application as follows:
|
||||
|
||||
.. code::
|
||||
|
||||
ExecStart=/opt/paperless/.local/bin/gunicorn -c /opt/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
|
||||
Paperless will continue to work with WSGI, but you will not get any status notifications.
|
||||
|
||||
Apache ``mod_wsgi`` users, see :ref:`this note <faq-mod_wsgi>`.
|
||||
|
||||
* Paperless now offers suggestions for tags, correspondents and types on the document detail page.
|
||||
|
||||
* Added an interactive easy install script that automatically downloads, configures and starts paperless with docker.
|
||||
|
||||
* Official support for Python 3.9.
|
||||
|
||||
* Other changes and fixes
|
||||
|
||||
* Adjusted the default parallelization settings to run more than one task in parallel on systems with 4 or less cores.
|
||||
This addresses issues with paperless not consuming any new files when other tasks are running.
|
||||
|
||||
* Fixed a rare race condition that would cause paperless to process incompletely written files when using the upload on the dashboard.
|
||||
|
||||
* The document classifier no longer issues warnings and errors when auto matching is not used at all.
|
||||
|
||||
* Better icon for document previews.
|
||||
|
||||
* Better info section in the side bar.
|
||||
|
||||
* Paperless no longer logs to the database. Instead, logs are written to rotating log files. This solves many "database is locked"
|
||||
issues on Raspberry Pi, especially when SQLite is used.
|
||||
|
||||
* By default, log files are written to ``PAPERLESS_DATA_DIR/log/``. Logging settings can be adjusted with
|
||||
``PAPERLESS_LOGGING_DIR``, ``PAPERLESS_LOGROTATE_MAX_SIZE`` and
|
||||
``PAPERLESS_LOGROTATE_MAX_BACKUPS``.
|
||||
|
||||
paperless-ng 1.0.0
|
||||
##################
|
||||
|
||||
Nothing special about this release, but since there are relatively few bug reports coming in, I think that this is reasonably stable.
|
||||
|
||||
* Document export
|
||||
|
||||
* The document exporter has been rewritten to support updating an already existing export in place.
|
||||
This enables incremental backups with ``rsync``.
|
||||
* The document exporter supports naming exported files according to ``PAPERLESS_FILENAME_FORMAT``.
|
||||
* The document exporter locks the media directory and the database during execution to ensure that
|
||||
the resulting export is consistent.
|
||||
* See the :ref:`updated documentation <utilities-exporter>` for more details.
|
||||
|
||||
* Other changes and additions
|
||||
|
||||
* Added a language selector to the settings.
|
||||
* Added date format options to the settings.
|
||||
* Range selection with shift clicking is now possible in the document list.
|
||||
* Filtering correspondent, type and tag management pages by name.
|
||||
* Focus "Name" field in dialogs by default.
|
||||
|
||||
|
||||
paperless-ng 0.9.14
|
||||
###################
|
||||
|
||||
Starting with this version, releases are getting built automatically. This release also comes with changes on how to install and
|
||||
update paperless.
|
||||
|
||||
* Paperless now uses GitHub Actions to make releases and build docker images.
|
||||
|
||||
* Docker images are available for amd64, armhf, and aarch64.
|
||||
* When you pull an image from Docker Hub, Docker will automatically select the correct image for you.
|
||||
|
||||
* Changes to docker installations and updates
|
||||
|
||||
* The ``-dockerfiles.tar.xz`` release archive is gone. Instead, simply grab the docker files from ``/docker/compose`` in the repository
|
||||
if you wish to install paperless by pulling from the hub.
|
||||
* The docker compose files in ``/docker/compose`` were changed to always use the ``latest`` version automatically. In order to do further
|
||||
updates, simply do a ``docker-compose pull``. The documentation has been updated.
|
||||
* The docker compose files were changed to restart paperless on system boot only if it was running before shutdown.
|
||||
* Documentation of the docker-compose files about what they do.
|
||||
|
||||
* Changes to bare metal installations and updates
|
||||
|
||||
* The release archive is built exactly like before. However, the release now comes with already compiled translation messages and
|
||||
collected static files. Therefore, the update steps ``compilemessages`` and ``collectstatic`` are now obsolete.
|
||||
|
||||
* Other changes
|
||||
|
||||
* A new configuration option ``PAPERLESS_IGNORE_DATES`` was added by `jayme-github`_. This can be used to instruct paperless to ignore
|
||||
certain dates (such as your date of birth) when guessing the date from the document content. This was actually introduced in 0.9.12,
|
||||
I just forgot to mention it in the changelog.
|
||||
* The filter drop downs now display selected entries on top of all other entries.
|
||||
* The PostgreSQL client now supports setting an explicit ``sslmode`` to force encryption of the connection to PostgreSQL.
|
||||
* The docker images now come with ``jbig2enc``, which is a lossless image encoder for PDF documents and decreases the size of certain
|
||||
PDF/A documents.
|
||||
* When using any of the manual matching algorithms, paperless now logs messages about when and why these matching algorithms matched.
|
||||
* The default settings for parallelization in paperless were adjusted to always leave one CPU core free.
|
||||
* Added an option to the frontend to choose which method to use for displaying PDF documents.
|
||||
|
||||
* Fixes
|
||||
|
||||
* An issue with the tika parser not picking up files from the consumption directory was fixed.
|
||||
* A couple changes to the dark mode and fixes to several other layout issues.
|
||||
* An issue with the drop downs for correspondents, tags and types not properly supporting filtering with special characters was fixed.
|
||||
* Fixed an issue with filenames of downloaded files: Dates where off by one day due to timezone issues.
|
||||
* Searching will continue to work even when the index returns non-existing documents. This resulted in "Document does not exist" errors
|
||||
before. Instead, a warning is logged, indicating the issue.
|
||||
* An issue with the consumer crashing when invalid regular expression were used was fixed.
|
||||
|
||||
paperless-ng 0.9.13
|
||||
###################
|
||||
|
||||
* Fixed an issue with Paperless not starting due to the new Tika integration when ``USERMAP_UID`` and ``USERMAP_GID`` was used
|
||||
in the ``docker-compose.env`` file.
|
||||
|
||||
paperless-ng 0.9.12
|
||||
###################
|
||||
|
||||
@@ -62,7 +506,7 @@ paperless-ng 0.9.10
|
||||
* There are some configuration options in the settings to alter the behavior.
|
||||
|
||||
* Other changes and additions
|
||||
|
||||
|
||||
* Thanks to `zjean`_, paperless now publishes a webmanifest, which is useful for adding the application to home screens on mobile devices.
|
||||
* The Paperless-ng logo now navigates to the dashboard.
|
||||
* Filter for documents that don't have any correspondents, types or tags assigned.
|
||||
@@ -82,7 +526,7 @@ paperless-ng 0.9.10
|
||||
The bulk delete operations did not update the search index. Therefore, documents that you deleted remained in the index and
|
||||
caused the search to return messages about missing documents when searching. Further bulk operations will properly update
|
||||
the index.
|
||||
|
||||
|
||||
However, this change is not retroactive: If you used the delete method of the bulk editor, you need to reindex your search index
|
||||
by :ref:`running the management command document_index with the argument reindex <administration-index>`.
|
||||
|
||||
@@ -137,12 +581,12 @@ paperless-ng 0.9.7
|
||||
|
||||
* Thanks to the hard work of `Michael Shamoon`_, paperless now comes with a much more streamlined UI for
|
||||
filtering documents.
|
||||
|
||||
|
||||
* `Michael Shamoon`_ replaced the document preview with another component. This should fix compatibility with Safari browsers.
|
||||
|
||||
* Added buttons to the management pages to quickly show all documents with one specific tag, correspondent, or title.
|
||||
|
||||
* Paperless now stores your saved views on the server and associates them with your user account.
|
||||
|
||||
* Paperless now stores your saved views on the server and associates them with your user account.
|
||||
This means that you can access your views on multiple devices and have separate views for different users.
|
||||
You will have to recreate your views.
|
||||
|
||||
@@ -160,7 +604,7 @@ paperless-ng 0.9.7
|
||||
This option enables you to be logged in into multiple instances by specifying different cookie names for each instance.
|
||||
|
||||
* Fixes
|
||||
|
||||
|
||||
* Sometimes paperless would assign dates in the future to newly consumed documents.
|
||||
* The filename format fields ``{created_month}`` and ``{created_day}`` now use a leading zero for single digit values.
|
||||
* The filename format field ``{tags}`` can no longer be used without arguments.
|
||||
@@ -1007,6 +1451,11 @@ bulk of the work on this big change.
|
||||
|
||||
* Initial release
|
||||
|
||||
.. _Alexander Menk: https://github.com/amenk
|
||||
.. _puuu: https://github.com/puuu
|
||||
.. _WhiteHatTux: https://github.com/WhiteHatTux
|
||||
.. _Chris Nagy: https://github.com/what-name
|
||||
.. _sbrl: https://github.com/sbrl
|
||||
.. _slorenz: https://github.com/sisao
|
||||
.. _Jo Vandeginste: https://github.com/jovandeginste
|
||||
.. _zjean: https://github.com/zjean
|
||||
@@ -1079,6 +1528,50 @@ bulk of the work on this big change.
|
||||
.. _JOKer: https://github.com/MasterofJOKers
|
||||
.. _Brian Cribbs: https://github.com/cribbstechnolog
|
||||
.. _Brendan M. Sleight: https://github.com/bmsleight
|
||||
.. _Daniel Albers: https://github.com/AlD
|
||||
.. _@shamoon: https://github.com/shamoon
|
||||
.. _@amenk: https://github.com/amenk
|
||||
.. _@dblitt: https://github.com/dblitt
|
||||
.. _@evilsidekick293: https://github.com/evilsidekick293
|
||||
.. _@m0veax: https://github.com/m0veax
|
||||
.. _@fignew: https://github.com/fignew
|
||||
.. _@muued: https://github.com/muued
|
||||
.. _@isigmund: https://github.com/isigmund
|
||||
.. _@denilsonsa: https://github.com/denilsonsa
|
||||
.. _@sAksham-Ar: https://github.com/sAksham-Ar
|
||||
.. _@philpagel: https://github.com/philpagel
|
||||
.. _@davemachado: https://github.com/davemachado
|
||||
.. _@2600box: https://github.com/2600box
|
||||
.. _@qcasey: https://github.com/qcasey
|
||||
.. _@kpj: https://github.com/kpj
|
||||
.. _@mweimerskirch: https://github.com/mweimerskirch
|
||||
.. _@filcuk: https://github.com/filcuk
|
||||
.. _@FrankStrieter: https://github.com/FrankStrieter
|
||||
.. _@tribut: https://github.com/tribut
|
||||
.. _@yschroeder: https://github.com/yschroeder
|
||||
.. _@gador: https://github.com/gador
|
||||
.. _@Nicarim: https://github.com/Nicarim
|
||||
.. _@bauerj: https://github.com/bauerj
|
||||
.. _@a17t: https://github.com/a17t
|
||||
.. _@alexander-bauer: https://github.com/alexander-bauer
|
||||
.. _@apeltzer: https://github.com/apeltzer
|
||||
.. _@Timoms: https://github.com/Timoms
|
||||
.. _@sbrunner: https://github.com/sbrunner
|
||||
.. _@slankes: https://github.com/slankes
|
||||
.. _@mattlamb99: https://github.com/mattlamb99
|
||||
.. _@padraigkitterick: https://github.com/padraigkitterick
|
||||
.. _@ajkavanagh: https://github.com/ajkavanagh
|
||||
.. _@Tooa: https://github.com/Tooa
|
||||
.. _@Unkn0wnCat: https://github.com/Unkn0wnCat
|
||||
.. _@pewter77: https://github.com/pewter77
|
||||
.. _@cschmatzler: https://github.com/cschmatzler
|
||||
.. _@muellermartin: https://github.com/muellermartin
|
||||
.. _@stumpylog: https://github.com/stumpylog
|
||||
.. _@Toxix: https://github.com/Toxix
|
||||
.. _@benjaminfrank: https://github.com/benjaminfrank
|
||||
.. _@azapater: https://github.com/azapater
|
||||
.. _@tim-vogel: https://github.com/tim-vogel
|
||||
.. _@jschpp: https://github.com/jschpp
|
||||
|
||||
.. _#20: https://github.com/the-paperless-project/paperless/issues/20
|
||||
.. _#44: https://github.com/the-paperless-project/paperless/issues/44
|
||||
@@ -1191,3 +1684,4 @@ bulk of the work on this big change.
|
||||
.. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/
|
||||
.. _optipng: http://optipng.sourceforge.net/
|
||||
.. _DjangoQL: https://github.com/ivelum/djangoql
|
||||
.. _ansible repo: https://github.com/paperless-ngx/paperless-ngx-ansible
|
188
docs/conf.py
@@ -6,29 +6,29 @@ exec(open("../src/paperless/version.py").read())
|
||||
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.imgmath',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx_rtd_theme',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.imgmath",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx_rtd_theme",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
# templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Paperless-ng'
|
||||
copyright = u'2015, Daniel Quinn'
|
||||
project = "Paperless-ngx"
|
||||
copyright = "2015-2022, Daniel Quinn, Jonas Winkler, and the paperless-ngx team"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
@@ -47,180 +47,174 @@ release = ".".join([str(_) for _ in __version__[:3]])
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
# language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
exclude_patterns = ["_build"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
# keep_warnings = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
# html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
# html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
# html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
# html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
# html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
# html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'paperless'
|
||||
htmlhelp_basename = "paperless"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'paperless.tex', u'Paperless Documentation',
|
||||
u'Daniel Quinn', 'manual'),
|
||||
("index", "paperless.tex", "Paperless Documentation", "Daniel Quinn", "manual"),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'paperless', u'Paperless Documentation',
|
||||
[u'Daniel Quinn'], 1)
|
||||
]
|
||||
man_pages = [("index", "paperless", "Paperless Documentation", ["Daniel Quinn"], 1)]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
@@ -229,93 +223,99 @@ man_pages = [
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'Paperless', u'Paperless Documentation',
|
||||
u'Daniel Quinn', 'paperless', 'Scan, index, and archive all of your paper documents.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
"index",
|
||||
"Paperless",
|
||||
"Paperless Documentation",
|
||||
"Daniel Quinn",
|
||||
"paperless",
|
||||
"Scan, index, and archive all of your paper documents.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
# texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# -- Options for Epub output ----------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'Paperless'
|
||||
epub_author = u'Daniel Quinn'
|
||||
epub_publisher = u'Daniel Quinn'
|
||||
epub_copyright = u'2015, Daniel Quinn'
|
||||
epub_title = "Paperless"
|
||||
epub_author = "Daniel Quinn"
|
||||
epub_publisher = "Daniel Quinn"
|
||||
epub_copyright = "2015, Daniel Quinn"
|
||||
|
||||
# The basename for the epub file. It defaults to the project name.
|
||||
#epub_basename = u'Paperless'
|
||||
# epub_basename = u'Paperless'
|
||||
|
||||
# The HTML theme for the epub output. Since the default themes are not optimized
|
||||
# for small screen space, using the same theme for HTML and epub output is
|
||||
# usually not wise. This defaults to 'epub', a theme designed to save visual
|
||||
# space.
|
||||
#epub_theme = 'epub'
|
||||
# epub_theme = 'epub'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
#epub_language = ''
|
||||
# epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
# epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
# epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
# epub_cover = ()
|
||||
|
||||
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||
#epub_guide = ()
|
||||
# epub_guide = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
# epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
# epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
epub_exclude_files = ["search.html"]
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
# epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
# epub_tocdup = True
|
||||
|
||||
# Choose between 'default' and 'includehidden'.
|
||||
#epub_tocscope = 'default'
|
||||
# epub_tocscope = 'default'
|
||||
|
||||
# Fix unsupported image types using the PIL.
|
||||
#epub_fix_images = False
|
||||
# epub_fix_images = False
|
||||
|
||||
# Scale large images.
|
||||
#epub_max_image_width = 0
|
||||
# epub_max_image_width = 0
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#epub_show_urls = 'inline'
|
||||
# epub_show_urls = 'inline'
|
||||
|
||||
# If false, no index is generated.
|
||||
#epub_use_index = True
|
||||
# epub_use_index = True
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'http://docs.python.org/': None}
|
||||
intersphinx_mapping = {"http://docs.python.org/": None}
|
||||
|
@@ -53,6 +53,12 @@ PAPERLESS_DBPASS=<password>
|
||||
|
||||
Defaults to "paperless".
|
||||
|
||||
PAPERLESS_DBSSLMODE=<mode>
|
||||
SSL mode to use when connecting to PostgreSQL.
|
||||
|
||||
See `the official documentation about sslmode <https://www.postgresql.org/docs/current/libpq-ssl.html>`_.
|
||||
|
||||
Default is ``prefer``.
|
||||
|
||||
Paths and folders
|
||||
#################
|
||||
@@ -66,13 +72,22 @@ PAPERLESS_CONSUMPTION_DIR=<path>
|
||||
container. Change the local consumption directory in the docker-compose.yml
|
||||
file instead.
|
||||
|
||||
Defaults to "../consume", relative to the "src" directory.
|
||||
Defaults to "../consume/", relative to the "src" directory.
|
||||
|
||||
PAPERLESS_DATA_DIR=<path>
|
||||
This is where paperless stores all its data (search index, SQLite database,
|
||||
classification model, etc).
|
||||
|
||||
Defaults to "../data", relative to the "src" directory.
|
||||
Defaults to "../data/", relative to the "src" directory.
|
||||
|
||||
PAPERLESS_TRASH_DIR=<path>
|
||||
Instead of removing deleted documents, they are moved to this directory.
|
||||
|
||||
This must be writeable by the user running paperless. When running inside
|
||||
docker, ensure that this path is within a permanent volume (such as
|
||||
"../media/trash") so it won't get lost on upgrades.
|
||||
|
||||
Defaults to empty (i.e. really delete documents).
|
||||
|
||||
PAPERLESS_MEDIA_ROOT=<path>
|
||||
This is where your documents and thumbnails are stored.
|
||||
@@ -80,7 +95,7 @@ PAPERLESS_MEDIA_ROOT=<path>
|
||||
You can set this and PAPERLESS_DATA_DIR to the same folder to have paperless
|
||||
store all its data within the same volume.
|
||||
|
||||
Defaults to "../media", relative to the "src" directory.
|
||||
Defaults to "../media/", relative to the "src" directory.
|
||||
|
||||
PAPERLESS_STATICDIR=<path>
|
||||
Override the default STATIC_ROOT here. This is where all static files
|
||||
@@ -88,7 +103,7 @@ PAPERLESS_STATICDIR=<path>
|
||||
|
||||
Unless you're doing something fancy, there is no need to override this.
|
||||
|
||||
Defaults to "../static", relative to the "src" directory.
|
||||
Defaults to "../static/", relative to the "src" directory.
|
||||
|
||||
PAPERLESS_FILENAME_FORMAT=<format>
|
||||
Changes the filenames paperless uses to store documents in the media directory.
|
||||
@@ -96,6 +111,25 @@ PAPERLESS_FILENAME_FORMAT=<format>
|
||||
|
||||
Default is none, which disables this feature.
|
||||
|
||||
PAPERLESS_LOGGING_DIR=<path>
|
||||
This is where paperless will store log files.
|
||||
|
||||
Defaults to "``PAPERLESS_DATA_DIR``/log/".
|
||||
|
||||
|
||||
Logging
|
||||
#######
|
||||
|
||||
PAPERLESS_LOGROTATE_MAX_SIZE=<num>
|
||||
Maximum file size for log files before they are rotated, in bytes.
|
||||
|
||||
Defaults to 1 MiB.
|
||||
|
||||
PAPERLESS_LOGROTATE_MAX_BACKUPS=<num>
|
||||
Number of rotated log files to keep.
|
||||
|
||||
Defaults to 20.
|
||||
|
||||
Hosting & Security
|
||||
##################
|
||||
|
||||
@@ -129,10 +163,6 @@ PAPERLESS_FORCE_SCRIPT_NAME=<path>
|
||||
To host paperless under a subpath url like example.com/paperless you set
|
||||
this value to /paperless. No trailing slash!
|
||||
|
||||
.. note::
|
||||
|
||||
I don't know if this works in paperless-ng. Probably not.
|
||||
|
||||
Defaults to none, which hosts paperless at "/".
|
||||
|
||||
PAPERLESS_STATIC_URL=<path>
|
||||
@@ -152,6 +182,30 @@ PAPERLESS_AUTO_LOGIN_USERNAME=<username>
|
||||
|
||||
Defaults to none, which disables this feature.
|
||||
|
||||
PAPERLESS_ADMIN_USER=<username>
|
||||
If this environment variable is specified, Paperless automatically creates
|
||||
a superuser with the provided username at start. This is useful in cases
|
||||
where you can not run the `createsuperuser` command seperately, such as Kubernetes
|
||||
or AWS ECS.
|
||||
|
||||
Requires `PAPERLESS_ADMIN_PASSWORD` to be set.
|
||||
|
||||
.. note::
|
||||
|
||||
This will not change an existing [super]user's password, nor will
|
||||
it recreate a user that already exists. You can leave this throughout
|
||||
the lifecycle of the containers.
|
||||
|
||||
PAPERLESS_ADMIN_MAIL=<email>
|
||||
(Optional) Specify superuser email address. Only used when
|
||||
`PAPERLESS_ADMIN_USER` is set.
|
||||
|
||||
Defaults to ``root@localhost``.
|
||||
|
||||
PAPERLESS_ADMIN_PASSWORD=<password>
|
||||
Only used when `PAPERLESS_ADMIN_USER` is set.
|
||||
This will be the password of the automatically created superuser.
|
||||
|
||||
|
||||
PAPERLESS_COOKIE_PREFIX=<str>
|
||||
Specify a prefix that is added to the cookies used by paperless to identify
|
||||
@@ -166,8 +220,35 @@ PAPERLESS_ENABLE_HTTP_REMOTE_USER=<bool>
|
||||
Allows authentication via HTTP_REMOTE_USER which is used by some SSO
|
||||
applications.
|
||||
|
||||
.. warning::
|
||||
|
||||
This will allow authentication by simply adding a ``Remote-User: <username>`` header
|
||||
to a request. Use with care! You especially *must* ensure that any such header is not
|
||||
passed from your proxy server to paperless.
|
||||
|
||||
If you're exposing paperless to the internet directly, do not use this.
|
||||
|
||||
Also see the warning `in the official documentation <https://docs.djangoproject.com/en/3.1/howto/auth-remote-user/#configuration>`.
|
||||
|
||||
Defaults to `false` which disables this feature.
|
||||
|
||||
PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=<str>
|
||||
If `PAPERLESS_ENABLE_HTTP_REMOTE_USER` is enabled, this property allows to
|
||||
customize the name of the HTTP header from which the authenticated username
|
||||
is extracted. Values are in terms of
|
||||
[HttpRequest.META](https://docs.djangoproject.com/en/3.1/ref/request-response/#django.http.HttpRequest.META).
|
||||
Thus, the configured value must start with `HTTP_` followed by the
|
||||
normalized actual header name.
|
||||
|
||||
Defaults to `HTTP_REMOTE_USER`.
|
||||
|
||||
PAPERLESS_LOGOUT_REDIRECT_URL=<str>
|
||||
URL to redirect the user to after a logout. This can be used together with
|
||||
`PAPERLESS_ENABLE_HTTP_REMOTE_USER` to redirect the user back to the SSO
|
||||
application's logout page.
|
||||
|
||||
Defaults to None, which disables this feature.
|
||||
|
||||
.. _configuration-ocr:
|
||||
|
||||
OCR settings
|
||||
@@ -177,7 +258,6 @@ Paperless uses `OCRmyPDF <https://ocrmypdf.readthedocs.io/en/latest/>`_ for
|
||||
performing OCR on documents and images. Paperless uses sensible defaults for
|
||||
most settings, but all of them can be configured to your needs.
|
||||
|
||||
|
||||
PAPERLESS_OCR_LANGUAGE=<lang>
|
||||
Customize the language that paperless will attempt to use when
|
||||
parsing documents.
|
||||
@@ -194,6 +274,8 @@ PAPERLESS_OCR_LANGUAGE=<lang>
|
||||
|
||||
Defaults to "eng".
|
||||
|
||||
Note: If your language contains a '-' such as chi-sim, you must use chi_sim
|
||||
|
||||
PAPERLESS_OCR_MODE=<mode>
|
||||
Tell paperless when and how to perform ocr on your documents. Four modes
|
||||
are available:
|
||||
@@ -220,6 +302,54 @@ PAPERLESS_OCR_MODE=<mode>
|
||||
The default is ``skip``, which only performs OCR when necessary and always
|
||||
creates archived documents.
|
||||
|
||||
Read more about this in the `OCRmyPDF documentation <https://ocrmypdf.readthedocs.io/en/latest/advanced.html#when-ocr-is-skipped>`_.
|
||||
|
||||
PAPERLESS_OCR_CLEAN=<mode>
|
||||
Tells paperless to use ``unpaper`` to clean any input document before
|
||||
sending it to tesseract. This uses more resources, but generally results
|
||||
in better OCR results. The following modes are available:
|
||||
|
||||
* ``clean``: Apply unpaper.
|
||||
* ``clean-final``: Apply unpaper, and use the cleaned images to build the
|
||||
output file instead of the original images.
|
||||
* ``none``: Do not apply unpaper.
|
||||
|
||||
Defaults to ``clean``.
|
||||
|
||||
.. note::
|
||||
|
||||
``clean-final`` is incompatible with ocr mode ``redo``. When both
|
||||
``clean-final`` and the ocr mode ``redo`` is configured, ``clean``
|
||||
is used instead.
|
||||
|
||||
PAPERLESS_OCR_DESKEW=<bool>
|
||||
Tells paperless to correct skewing (slight rotation of input images mainly
|
||||
due to improper scanning)
|
||||
|
||||
Defaults to ``true``, which enables this feature.
|
||||
|
||||
.. note::
|
||||
|
||||
Deskewing is incompatible with ocr mode ``redo``. Deskewing will get
|
||||
disabled automatically if ``redo`` is used as the ocr mode.
|
||||
|
||||
PAPERLESS_OCR_ROTATE_PAGES=<bool>
|
||||
Tells paperless to correct page rotation (90°, 180° and 270° rotation).
|
||||
|
||||
If you notice that paperless is not rotating incorrectly rotated
|
||||
pages (or vice versa), try adjusting the threshold up or down (see below).
|
||||
|
||||
Defaults to ``true``, which enables this feature.
|
||||
|
||||
|
||||
PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=<num>
|
||||
Adjust the threshold for automatic page rotation by ``PAPERLESS_OCR_ROTATE_PAGES``.
|
||||
This is an arbitrary value reported by tesseract. "15" is a very conservative value,
|
||||
whereas "2" is a very aggressive option and will often result in correctly rotated pages
|
||||
being rotated as well.
|
||||
|
||||
Defaults to "12".
|
||||
|
||||
PAPERLESS_OCR_OUTPUT_TYPE=<type>
|
||||
Specify the the type of PDF documents that paperless should produce.
|
||||
|
||||
@@ -246,7 +376,6 @@ PAPERLESS_OCR_PAGES=<num>
|
||||
|
||||
Defaults to 0, which disables this feature and always uses all pages.
|
||||
|
||||
|
||||
PAPERLESS_OCR_IMAGE_DPI=<num>
|
||||
Paperless will OCR any images you put into the system and convert them
|
||||
into PDF documents. This is useful if your scanner produces images.
|
||||
@@ -257,17 +386,17 @@ PAPERLESS_OCR_IMAGE_DPI=<num>
|
||||
|
||||
Set this to the DPI your scanner produces images at.
|
||||
|
||||
Default is none, which causes paperless to fail if no DPI information is
|
||||
present in an image.
|
||||
Default is none, which will automatically calculate image DPI so that
|
||||
the produced PDF documents are A4 sized.
|
||||
|
||||
|
||||
PAPERLESS_OCR_USER_ARG=<json>
|
||||
PAPERLESS_OCR_USER_ARGS=<json>
|
||||
OCRmyPDF offers many more options. Use this parameter to specify any
|
||||
additional arguments you wish to pass to OCRmyPDF. Since Paperless uses
|
||||
the API of OCRmyPDF, you have to specify these in a format that can be
|
||||
passed to the API. See `the API reference of OCRmyPDF <https://ocrmypdf.readthedocs.io/en/latest/api.html#reference>`_
|
||||
for valid parameters. All command line options are supported, but they
|
||||
use underscores instead of dashed.
|
||||
use underscores instead of dashes.
|
||||
|
||||
.. caution::
|
||||
|
||||
@@ -289,7 +418,7 @@ Tika settings
|
||||
#############
|
||||
|
||||
Paperless can make use of `Tika <https://tika.apache.org/>`_ and
|
||||
`Gotenberg <https://thecodingmachine.github.io/gotenberg/>`_ for parsing and
|
||||
`Gotenberg <https://gotenberg.dev/>`_ for parsing and
|
||||
converting "Office" documents (such as ".doc", ".xlsx" and ".odt"). If you
|
||||
wish to use this, you must provide a Tika server and a Gotenberg server,
|
||||
configure their endpoints, and enable the feature.
|
||||
@@ -327,14 +456,14 @@ requires are as follows:
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
|
||||
# ...
|
||||
|
||||
gotenberg:
|
||||
image: thecodingmachine/gotenberg
|
||||
image: gotenberg/gotenberg:7
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_GOOGLE_CHROME: 1
|
||||
CHROMIUM_DISABLE_ROUTES: 1
|
||||
|
||||
tika:
|
||||
image: apache/tika
|
||||
@@ -370,13 +499,36 @@ PAPERLESS_THREADS_PER_WORKER=<num>
|
||||
use a higher thread per worker count.
|
||||
|
||||
The default is a balance between the two, according to your CPU core count,
|
||||
with a slight favor towards threads per worker, and using as much cores as
|
||||
possible.
|
||||
with a slight favor towards threads per worker:
|
||||
|
||||
+----------------+---------+---------+
|
||||
| CPU core count | Workers | Threads |
|
||||
+----------------+---------+---------+
|
||||
| 1 | 1 | 1 |
|
||||
+----------------+---------+---------+
|
||||
| 2 | 2 | 1 |
|
||||
+----------------+---------+---------+
|
||||
| 4 | 2 | 2 |
|
||||
+----------------+---------+---------+
|
||||
| 6 | 2 | 3 |
|
||||
+----------------+---------+---------+
|
||||
| 8 | 2 | 4 |
|
||||
+----------------+---------+---------+
|
||||
| 12 | 3 | 4 |
|
||||
+----------------+---------+---------+
|
||||
| 16 | 4 | 4 |
|
||||
+----------------+---------+---------+
|
||||
|
||||
If you only specify PAPERLESS_TASK_WORKERS, paperless will adjust
|
||||
PAPERLESS_THREADS_PER_WORKER automatically.
|
||||
|
||||
|
||||
PAPERLESS_WORKER_TIMEOUT=<num>
|
||||
Machines with few cores or weak ones might not be able to finish OCR on
|
||||
large documents within the default 1800 seconds. So extending this timeout
|
||||
may prove to be useful on weak hardware setups.
|
||||
|
||||
|
||||
PAPERLESS_TIME_ZONE=<timezone>
|
||||
Set the time zone here.
|
||||
See https://docs.djangoproject.com/en/3.1/ref/settings/#std:setting-TIME_ZONE
|
||||
@@ -417,6 +569,9 @@ PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=<bool>
|
||||
E.g. <CONSUMPTION_DIR>/foo/bar/file.pdf will add the tags "foo" and "bar" to
|
||||
the consumed file. Paperless will create any tags that don't exist yet.
|
||||
|
||||
This is useful for sorting documents with certain tags such as ``car`` or
|
||||
``todo`` prior to consumption. These folders won't be deleted.
|
||||
|
||||
PAPERLESS_CONSUMER_RECURSIVE must be enabled for this to work.
|
||||
|
||||
Defaults to false.
|
||||
@@ -491,6 +646,20 @@ PAPERLESS_IGNORE_DATES=<string>
|
||||
|
||||
Defaults to an empty string to not ignore any dates.
|
||||
|
||||
PAPERLESS_DATE_ORDER=<format>
|
||||
Paperless will try to determine the document creation date from its contents.
|
||||
Specify the date format Paperless should expect to see within your documents.
|
||||
|
||||
This option defaults to DMY which translates to day first, month second, and year
|
||||
last order. Characters D, M, or Y can be shuffled to meet the required order.
|
||||
|
||||
PAPERLESS_CONSUMER_IGNORE_PATTERNS=<json>
|
||||
By default, paperless ignores certain files and folders in the consumption
|
||||
directory, such as system files created by the Mac OS.
|
||||
|
||||
This can be adjusted by configuring a custom json array with patterns to exclude.
|
||||
|
||||
Defautls to ``[".DS_STORE/*", "._*", ".stfolder/*"]``.
|
||||
|
||||
Binaries
|
||||
########
|
||||
@@ -510,3 +679,76 @@ PAPERLESS_GS_BINARY=<path>
|
||||
|
||||
PAPERLESS_OPTIPNG_BINARY=<path>
|
||||
Defaults to "/usr/bin/optipng".
|
||||
|
||||
|
||||
.. _configuration-docker:
|
||||
|
||||
Docker-specific options
|
||||
#######################
|
||||
|
||||
These options don't have any effect in ``paperless.conf``. These options adjust
|
||||
the behavior of the docker container. Configure these in `docker-compose.env`.
|
||||
|
||||
PAPERLESS_WEBSERVER_WORKERS=<num>
|
||||
The number of worker processes the webserver should spawn. More worker processes
|
||||
usually result in the front end to load data much quicker. However, each worker process
|
||||
also loads the entire application into memory separately, so increasing this value
|
||||
will increase RAM usage.
|
||||
|
||||
Consider configuring this to 1 on low power devices with limited amount of RAM.
|
||||
|
||||
Defaults to 2.
|
||||
|
||||
PAPERLESS_PORT=<port>
|
||||
The port number the webserver will listen on inside the container. There are
|
||||
special setups where you may need this to avoid collisions with other
|
||||
services (like using podman with multiple containers in one pod).
|
||||
|
||||
Don't change this when using Docker. To change the port the webserver is
|
||||
reachable outside of the container, instead refer to the "ports" key in
|
||||
``docker-compose.yml``.
|
||||
|
||||
Defaults to 8000.
|
||||
|
||||
USERMAP_UID=<uid>
|
||||
The ID of the paperless user in the container. Set this to your actual user ID on the
|
||||
host system, which you can get by executing
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ id -u
|
||||
|
||||
Paperless will change ownership on its folders to this user, so you need to get this right
|
||||
in order to be able to write to the consumption directory.
|
||||
|
||||
Defaults to 1000.
|
||||
|
||||
USERMAP_GID=<gid>
|
||||
The ID of the paperless Group in the container. Set this to your actual group ID on the
|
||||
host system, which you can get by executing
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ id -g
|
||||
|
||||
Paperless will change ownership on its folders to this group, so you need to get this right
|
||||
in order to be able to write to the consumption directory.
|
||||
|
||||
Defaults to 1000.
|
||||
|
||||
PAPERLESS_OCR_LANGUAGES=<list>
|
||||
Additional OCR languages to install. By default, paperless comes with
|
||||
English, German, Italian, Spanish and French. If your language is not in this list, install
|
||||
additional languages with this configuration option:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
PAPERLESS_OCR_LANGUAGES=tur ces
|
||||
|
||||
To actually use these languages, also set the default OCR language of paperless:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
PAPERLESS_OCR_LANGUAGE=tur
|
||||
|
||||
Defaults to none, which does not install any additional languages.
|
||||
|
@@ -5,8 +5,8 @@ Contributing to Paperless
|
||||
|
||||
.. warning::
|
||||
|
||||
This section is not updated to paperless-ng yet.
|
||||
|
||||
This section is not updated to paperless-ngx yet.
|
||||
|
||||
Maybe you've been using Paperless for a while and want to add a feature or two,
|
||||
or maybe you've come across a bug that you have some ideas how to solve. The
|
||||
beauty of Free software is that you can see what's wrong and help to get it
|
||||
|
@@ -3,30 +3,86 @@
|
||||
Paperless development
|
||||
#####################
|
||||
|
||||
This section describes the steps you need to take to start development on paperless-ng.
|
||||
This section describes the steps you need to take to start development on paperless-ngx.
|
||||
|
||||
1. Check out the source from github. The repository is organized in the following way:
|
||||
Check out the source from github. The repository is organized in the following way:
|
||||
|
||||
* ``master`` always represents the latest release and will only see changes
|
||||
when a new release is made.
|
||||
* ``dev`` contains the code that will be in the next release.
|
||||
* ``feature-X`` contain bigger changes that will be in some release, but not
|
||||
necessarily the next one.
|
||||
|
||||
Apart from that, the folder structure is as follows:
|
||||
* ``master`` always represents the latest release and will only see changes
|
||||
when a new release is made.
|
||||
* ``dev`` contains the code that will be in the next release.
|
||||
* ``feature-X`` contain bigger changes that will be in some release, but not
|
||||
necessarily the next one.
|
||||
|
||||
* ``docs/`` - Documentation.
|
||||
* ``src-ui/`` - Code of the front end.
|
||||
* ``src/`` - Code of the back end.
|
||||
* ``scripts/`` - Various scripts that help with different parts of development.
|
||||
* ``docker/`` - Files required to build the docker image.
|
||||
When making functional changes to paperless, *always* make your changes on the ``dev`` branch.
|
||||
|
||||
2. Install some dependencies.
|
||||
Apart from that, the folder structure is as follows:
|
||||
|
||||
* Python 3.6.
|
||||
* All dependencies listed in the :ref:`Bare metal route <setup-bare_metal>`
|
||||
* redis. You can either install redis or use the included scritps/start-redis.sh
|
||||
to use docker to fire up a redis instance.
|
||||
* ``docs/`` - Documentation.
|
||||
* ``src-ui/`` - Code of the front end.
|
||||
* ``src/`` - Code of the back end.
|
||||
* ``scripts/`` - Various scripts that help with different parts of development.
|
||||
* ``docker/`` - Files required to build the docker image.
|
||||
|
||||
Initial setup and first start
|
||||
=============================
|
||||
|
||||
After you forked and cloned the code from github you need to perform a first-time setup.
|
||||
To do the setup you need to perform the steps from the following chapters in a certain order:
|
||||
|
||||
1. Install prerequisites + pipenv as mentioned in :ref:`Bare metal route <setup-bare_metal>`
|
||||
2. Copy ``paperless.conf.example`` to ``paperless.conf`` and enable debug mode.
|
||||
3. Install the Angular CLI interface:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ npm install -g @angular/cli
|
||||
|
||||
4. Create ``consume`` and ``media`` folders in the cloned root folder.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
mkdir -p consume media
|
||||
|
||||
5. You can now either ...
|
||||
|
||||
* install redis or
|
||||
* use the included scripts/start-services.sh to use docker to fire up a redis instance (and some other services such as tika, gotenberg and a postgresql server) or
|
||||
* spin up a bare redis container
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
docker run -d -p 6379:6379 --restart unless-stopped redis:latest
|
||||
|
||||
6. Install the python dependencies by performing in the src/ directory.
|
||||
.. code:: shell-session
|
||||
|
||||
pipenv install --dev
|
||||
|
||||
* Make sure you're using python 3.9.x or lower. Otherwise you might get issues with building dependencies. You can use `pyenv <https://github.com/pyenv/pyenv>`_ to install a specific python version.
|
||||
|
||||
7. Generate the static UI so you can perform a login to get session that is required for frontend development (this needs to be done one time only). From src-ui directory:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
npm install .
|
||||
./node_modules/.bin/ng build --configuration production
|
||||
|
||||
8. Apply migrations and create a superuser for your dev instance:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
python3 manage.py migrate
|
||||
python3 manage.py createsuperuser
|
||||
|
||||
9. Now spin up the dev backend. Depending on which part of paperless you're developing for, you need to have some or all of them running.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
python3 manage.py runserver & python3 manage.py document_consumer & python3 manage.py qcluster
|
||||
|
||||
10. Login with the superuser credentials provided in step 8 at ``http://localhost:8000`` to create a session that enables you to use the backend.
|
||||
|
||||
Backend development environment is now ready, to start Frontend development go to ``/src-ui`` and run ``ng serve``. From there you can use ``http://localhost:4200`` for a preview.
|
||||
|
||||
Back end development
|
||||
====================
|
||||
@@ -34,34 +90,32 @@ Back end development
|
||||
The backend is a django application. I use PyCharm for development, but you can use whatever
|
||||
you want.
|
||||
|
||||
Install the python dependencies by performing ``pipenv install --dev`` in the src/ directory.
|
||||
This will also create a virtual environment, which you can enter with ``pipenv shell`` or
|
||||
execute one-shot commands in with ``pipenv run``.
|
||||
|
||||
In ``src/paperless.conf``, enable debug mode.
|
||||
|
||||
Configure the IDE to use the src/ folder as the base source folder. Configure the following
|
||||
launch configurations in your IDE:
|
||||
|
||||
* python3 manage.py runserver
|
||||
* python3 manage.py qcluster
|
||||
* python3 manage.py consumer
|
||||
* python3 manage.py document_consumer
|
||||
|
||||
Depending on which part of paperless you're developing for, you need to have some or all of
|
||||
them running.
|
||||
To start them all:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
python3 manage.py runserver & python3 manage.py document_consumer & python3 manage.py qcluster
|
||||
|
||||
Testing and code style:
|
||||
|
||||
* Run ``pytest`` in the src/ directory to execute all tests. This also generates a HTML coverage
|
||||
report. When runnings test, paperless.conf is loaded as well. However: the tests rely on the default
|
||||
configuration. This is not ideal. But for now, make sure no settings except for DEBUG are overridden when testing.
|
||||
* Run ``black`` to format your code.
|
||||
* Run ``pycodestyle`` to test your code for issues with the configured code style settings.
|
||||
|
||||
.. note::
|
||||
|
||||
The line length rule E501 is generally useful for getting multiple source files
|
||||
next to each other on the screen. However, in some cases, its just not possible
|
||||
to make some lines fit, especially complicated IF cases. Append `` # NOQA: E501``
|
||||
to make some lines fit, especially complicated IF cases. Append ``# NOQA: E501``
|
||||
to disable this check for certain lines.
|
||||
|
||||
Front end development
|
||||
@@ -102,18 +156,130 @@ In order to build the front end and serve it as part of django, execute
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ ng build --prod --output-path ../src/documents/static/frontend/
|
||||
$ ng build --prod
|
||||
|
||||
This will build the front end and put it in a location from which the Django server will serve
|
||||
it as static content. This way, you can verify that authentication is working.
|
||||
|
||||
Making a release
|
||||
================
|
||||
|
||||
Execute the ``make-release.sh <ver>`` script.
|
||||
Localization
|
||||
============
|
||||
|
||||
This will test and assemble everything and also build and tag a docker image.
|
||||
Paperless is available in many different languages. Since paperless consists both of a django
|
||||
application and an Angular front end, both these parts have to be translated separately.
|
||||
|
||||
Front end localization
|
||||
----------------------
|
||||
|
||||
* The Angular front end does localization according to the `Angular documentation <https://angular.io/guide/i18n>`_.
|
||||
* The source language of the project is "en_US".
|
||||
* The source strings end up in the file "src-ui/messages.xlf".
|
||||
* The translated strings need to be placed in the "src-ui/src/locale/" folder.
|
||||
* In order to extract added or changed strings from the source files, call ``ng xi18n --ivy``.
|
||||
|
||||
Adding new languages requires adding the translated files in the "src-ui/src/locale/" folder and adjusting a couple files.
|
||||
|
||||
1. Adjust "src-ui/angular.json":
|
||||
|
||||
.. code:: json
|
||||
|
||||
"i18n": {
|
||||
"sourceLocale": "en-US",
|
||||
"locales": {
|
||||
"de": "src/locale/messages.de.xlf",
|
||||
"nl-NL": "src/locale/messages.nl_NL.xlf",
|
||||
"fr": "src/locale/messages.fr.xlf",
|
||||
"en-GB": "src/locale/messages.en_GB.xlf",
|
||||
"pt-BR": "src/locale/messages.pt_BR.xlf",
|
||||
"language-code": "language-file"
|
||||
}
|
||||
}
|
||||
|
||||
2. Add the language to the available options in "src-ui/src/app/services/settings.service.ts":
|
||||
|
||||
.. code:: typescript
|
||||
|
||||
getLanguageOptions(): LanguageOption[] {
|
||||
return [
|
||||
{code: "en-us", name: $localize`English (US)`, englishName: "English (US)", dateInputFormat: "mm/dd/yyyy"},
|
||||
{code: "en-gb", name: $localize`English (GB)`, englishName: "English (GB)", dateInputFormat: "dd/mm/yyyy"},
|
||||
{code: "de", name: $localize`German`, englishName: "German", dateInputFormat: "dd.mm.yyyy"},
|
||||
{code: "nl", name: $localize`Dutch`, englishName: "Dutch", dateInputFormat: "dd-mm-yyyy"},
|
||||
{code: "fr", name: $localize`French`, englishName: "French", dateInputFormat: "dd/mm/yyyy"},
|
||||
{code: "pt-br", name: $localize`Portuguese (Brazil)`, englishName: "Portuguese (Brazil)", dateInputFormat: "dd/mm/yyyy"}
|
||||
// Add your new language here
|
||||
]
|
||||
}
|
||||
|
||||
``dateInputFormat`` is a special string that defines the behavior of the date input fields and absolutely needs to contain "dd", "mm" and "yyyy".
|
||||
|
||||
3. Import and register the Angular data for this locale in "src-ui/src/app/app.module.ts":
|
||||
|
||||
.. code:: typescript
|
||||
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
registerLocaleData(localeDe)
|
||||
|
||||
Back end localization
|
||||
---------------------
|
||||
|
||||
A majority of the strings that appear in the back end appear only when the admin is used. However,
|
||||
some of these are still shown on the front end (such as error messages).
|
||||
|
||||
* The django application does localization according to the `django documentation <https://docs.djangoproject.com/en/3.1/topics/i18n/translation/>`_.
|
||||
* The source language of the project is "en_US".
|
||||
* Localization files end up in the folder "src/locale/".
|
||||
* In order to extract strings from the application, call ``python3 manage.py makemessages -l en_US``. This is important after making changes to translatable strings.
|
||||
* The message files need to be compiled for them to show up in the application. Call ``python3 manage.py compilemessages`` to do this. The generated files don't get
|
||||
committed into git, since these are derived artifacts. The build pipeline takes care of executing this command.
|
||||
|
||||
Adding new languages requires adding the translated files in the "src/locale/" folder and adjusting the file "src/paperless/settings.py" to include the new language:
|
||||
|
||||
.. code:: python
|
||||
|
||||
LANGUAGES = [
|
||||
("en-us", _("English (US)")),
|
||||
("en-gb", _("English (GB)")),
|
||||
("de", _("German")),
|
||||
("nl-nl", _("Dutch")),
|
||||
("fr", _("French")),
|
||||
("pt-br", _("Portuguese (Brazil)")),
|
||||
# Add language here.
|
||||
]
|
||||
|
||||
|
||||
Building the documentation
|
||||
==========================
|
||||
|
||||
The documentation is built using sphinx. I've configured ReadTheDocs to automatically build
|
||||
the documentation when changes are pushed. If you want to build the documentation locally,
|
||||
this is how you do it:
|
||||
|
||||
1. Install python dependencies.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ pipenv install --dev
|
||||
|
||||
2. Build the documentation
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/docs
|
||||
$ pipenv run make clean html
|
||||
|
||||
This will build the HTML documentation, and put the resulting files in the ``_build/html``
|
||||
directory.
|
||||
|
||||
Building the Docker image
|
||||
=========================
|
||||
|
||||
Building the docker image from source:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
docker build . -t <your-tag>
|
||||
|
||||
Extending Paperless
|
||||
===================
|
||||
@@ -149,7 +315,7 @@ methods ``parse`` and ``get_thumbnail``. You can provide your own implementation
|
||||
|
||||
# The content of the document.
|
||||
self.text = "content"
|
||||
|
||||
|
||||
# Optional: path to a PDF document that you created from the original.
|
||||
self.archive_path = os.path.join(self.tempdir, "archived.pdf")
|
||||
|
||||
|
74
docs/faq.rst
@@ -3,17 +3,13 @@
|
||||
Frequently asked questions
|
||||
**************************
|
||||
|
||||
**Q:** *What's the general plan for Paperless-ng?*
|
||||
**Q:** *What's the general plan for Paperless-ngx?*
|
||||
|
||||
**A:** Paperless-ng is already almost feature-complete. This project will remain
|
||||
as simple as it is right now. It will see improvements to features that are already there.
|
||||
If you need advanced features such as document versions,
|
||||
workflows or multi-user with customizable access to individual files, this is
|
||||
not the tool for you.
|
||||
|
||||
Features that *are* planned are some more quality of life extensions for the searching
|
||||
(i.e., search for similar documents, group results by correspondents with "more from this"
|
||||
links, etc), bulk editing and hierarchical tags.
|
||||
**A:** While Paperless-ngx is already considered largely "feature-complete" it is a community-driven
|
||||
project and development will be guided in this way. New features can be submitted via
|
||||
GitHub discussions and "up-voted" by the community but this is not a garauntee the feature
|
||||
will be implemented. This project will always be open to collaboration in the form of PRs,
|
||||
ideas etc.
|
||||
|
||||
**Q:** *I'm using docker. Where are my documents?*
|
||||
|
||||
@@ -33,50 +29,57 @@ is
|
||||
files around manually. This folder is meant to be entirely managed by docker
|
||||
and paperless.
|
||||
|
||||
**Q:** *Let's say you don't support this project anymore in a year. Can I easily move to other systems?*
|
||||
**Q:** *Let's say I want to switch tools in a year. Can I easily move to other systems?*
|
||||
|
||||
**A:** Your documents are stored as plain files inside the media folder. You can always drag those files
|
||||
out of that folder to use them elsewhere. Here are a couple notes about that.
|
||||
|
||||
* Paperless never modifies your original documents. It keeps checksums of all documents and uses a
|
||||
* Paperless-ngx never modifies your original documents. It keeps checksums of all documents and uses a
|
||||
scheduled sanity checker to check that they remain the same.
|
||||
* By default, paperless uses the internal ID of each document as its filename. This might not be very
|
||||
convenient for export. However, you can adjust the way files are stored in paperless by
|
||||
:ref:`configuring the filename format <advanced-file_name_handling>`.
|
||||
* :ref:`The exporter <utilities-exporter>` is another easy way to get your files out of paperless with reasonable file names.
|
||||
|
||||
**Q:** *What file types does paperless-ng support?*
|
||||
**Q:** *What file types does paperless-ngx support?*
|
||||
|
||||
**A:** Currently, the following files are supported:
|
||||
|
||||
* PDF documents, PNG images, JPEG images, TIFF images and GIF images are processed with OCR and converted into PDF documents.
|
||||
* Plain text documents are supported as well and are added verbatim
|
||||
to paperless.
|
||||
* With the optional Tika integration enabled (see :ref:`Configuration <configuration-tika>`), Paperless also supports various
|
||||
Office documents (.docx, .doc, odt, .ppt, .pptx, .odp, .xls, .xlsx, .ods).
|
||||
|
||||
Paperless determines the type of a file by inspecting its content. The
|
||||
Paperless-ngx determines the type of a file by inspecting its content. The
|
||||
file extensions do not matter.
|
||||
|
||||
**Q:** *Will paperless-ng run on Raspberry Pi?*
|
||||
**Q:** *Will paperless-ngx run on Raspberry Pi?*
|
||||
|
||||
**A:** The short answer is yes. I've tested it on a Raspberry Pi 3 B.
|
||||
The long answer is that certain parts of
|
||||
Paperless will run very slow, such as the tesseract OCR. On Raspberry Pi,
|
||||
Paperless will run very slow, such as the OCR. On Raspberry Pi,
|
||||
try to OCR documents before feeding them into paperless so that paperless can
|
||||
reuse the text. The web interface should be a lot snappier, since it runs
|
||||
reuse the text. The web interface is a lot snappier, since it runs
|
||||
in your browser and paperless has to do much less work to serve the data.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
You can adjust some of the settings so that paperless uses less processing
|
||||
power. See :ref:`setup-less_powerful_devices` for details.
|
||||
|
||||
|
||||
**Q:** *How do I install paperless-ng on Raspberry Pi?*
|
||||
|
||||
**A:** There is no docker image for ARM available. If you know how to build
|
||||
that automatically, I'm all ears. For now, you have to grab the latest release
|
||||
archive from the project page and build the image yourself. The release comes
|
||||
with the front end already compiled, so you don't have to do this on the Pi.
|
||||
**Q:** *How do I install paperless-ngx on Raspberry Pi?*
|
||||
|
||||
**A:** Docker images are available for arm and arm64 hardware, so just follow
|
||||
the docker-compose instructions. Apart from more required disk space compared to
|
||||
a bare metal installation, docker comes with close to zero overhead, even on
|
||||
Raspberry Pi.
|
||||
|
||||
If you decide to got with the bare metal route, be aware that some of the
|
||||
python requirements do not have precompiled packages for ARM / ARM64. Installation
|
||||
of these will require additional development libraries and compilation will take
|
||||
a long time.
|
||||
|
||||
**Q:** *How do I run this on unRaid?*
|
||||
|
||||
@@ -95,12 +98,21 @@ occasionally build the image on and see if it works.
|
||||
|
||||
**Q:** *How do I proxy this with NGINX?*
|
||||
|
||||
.. code::
|
||||
**A:** See :ref:`here <setup-nginx>`.
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8000/
|
||||
}
|
||||
.. _faq-mod_wsgi:
|
||||
|
||||
And that's about it. Paperless serves everything, including static files by itself
|
||||
when running the docker image. If you want to do anything fancy, you have to
|
||||
install paperless bare metal.
|
||||
**Q:** *How do I get WebSocket support with Apache mod_wsgi*?
|
||||
|
||||
**A:** ``mod_wsgi`` by itself does not support ASGI. Paperless will continue
|
||||
to work with WSGI, but certain features such as status notifications about
|
||||
document consumption won't be available.
|
||||
|
||||
If you want to continue using ``mod_wsgi``, you will have to run an ASGI-enabled
|
||||
web server as well that processes WebSocket connections, and configure Apache to
|
||||
redirect WebSocket connections to this server. Multiple options for ASGI servers
|
||||
exist:
|
||||
|
||||
* ``gunicorn`` with ``uvicorn`` as the worker implementation (the default of paperless)
|
||||
* ``daphne`` as a standalone server, which is the reference implementation for ASGI.
|
||||
* ``uvicorn`` as a standalone server
|
||||
|
@@ -22,19 +22,21 @@ finding stuff again. I feed documents right from the post box into the scanner
|
||||
and then shred them. Perhaps you might find it useful too.
|
||||
|
||||
|
||||
Paperless-ng
|
||||
============
|
||||
Paperless-ngx
|
||||
=============
|
||||
|
||||
Paperless-ng is a fork of the original paperless project. It changes many
|
||||
things both on the surface and under the hood. Paperless-ng was created
|
||||
because I feel that these changes are too big to be pushed into the main
|
||||
repository right away.
|
||||
Paperless-ngx is a document management system that transforms your physical
|
||||
documents into a searchable online archive so you can keep, well, *less paper*.
|
||||
|
||||
Paperless-ngx forked from paperless-ng to continue the great work and
|
||||
distribute responsibility of supporting and advancing the project among a team
|
||||
of people.
|
||||
|
||||
NG stands for both Angular (the framework used for the
|
||||
Frontend) and next-gen. Publishing this project under a different name also
|
||||
avoids confusion between paperless and paperless-ng.
|
||||
avoids confusion between paperless and paperless-ngx.
|
||||
|
||||
If you want to learn about what's different in paperless-ng, check out these
|
||||
If you want to learn about what's different in paperless-ngx from Paperless, check out these
|
||||
resources in the documentation:
|
||||
|
||||
* :ref:`Some screenshots <screenshots>` of the new UI are available.
|
||||
@@ -46,16 +48,12 @@ resources in the documentation:
|
||||
the consumption directory. This means that you can select text in
|
||||
image-only documents coming from your scanner.
|
||||
* See :ref:`this note <utilities-encyption>` about GnuPG encryption in
|
||||
paperless-ng.
|
||||
paperless-ngx.
|
||||
* Paperless is now integrated with a
|
||||
:ref:`task processing queue <setup-task_processor>` that tells you
|
||||
at a glance when and why something is not working.
|
||||
at a glance when and why something is not working.
|
||||
* The :ref:`changelog <paperless_changelog>` contains a detailed list of all changes
|
||||
in paperless-ng.
|
||||
|
||||
It would be great if this project could eventually merge back into the main
|
||||
repository, but it needs a lot more work before that can happen.
|
||||
|
||||
in paperless-ngx.
|
||||
|
||||
Contents
|
||||
========
|
||||
@@ -70,8 +68,8 @@ Contents
|
||||
configuration
|
||||
api
|
||||
faq
|
||||
extending
|
||||
troubleshooting
|
||||
extending
|
||||
contributing
|
||||
scanners
|
||||
screenshots
|
||||
|
@@ -10,38 +10,105 @@ scanner you use, but sometimes finding a scanner that will write to an FTP,
|
||||
NFS, or SMB server can be difficult. This page is here to help you find one
|
||||
that works right for you based on recommendations from other Paperless users.
|
||||
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
| 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`_|
|
||||
+---------+----------------+-----+-----+-----+----------------+
|
||||
Physical scanners
|
||||
=================
|
||||
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brand | Model | Supports | Recommended By |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| | | FTP | NFS | SMB | SMTP | API [1]_ | |
|
||||
+=========+================+=====+=====+=====+======+==========+================+
|
||||
| Brother | `ADS-1700W`_ | yes | | yes | yes | |`holzhannes`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `ADS-1600W`_ | yes | | yes | yes | |`holzhannes`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `ADS-1500W`_ | yes | | yes | yes | |`danielquinn`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `ADS-1100W`_ | yes | | | | |`ytzelf`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `ADS-2800W`_ | yes | yes | | yes | yes |`philpagel`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-J6930DW`_ | yes | | | | |`ayounggun`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-L5850DW`_ | yes | | | yes | |`holzhannes`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-L2750DW`_ | yes | | yes | yes | |`muued`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-J5910DW`_ | yes | | | | |`bmsleight`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-8950DW`_ | yes | | | yes | yes |`philpagel`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Brother | `MFC-9142CDN`_ | yes | | yes | | |`REOLDEV`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Fujitsu | `ix500`_ | yes | | yes | | |`eonist`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Epson | `ES-580W`_ | yes | | yes | yes | |`fignew`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Epson | `WF-7710DWF`_ | yes | | yes | | |`Skylinar`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Fujitsu | `S1300i`_ | yes | | yes | | |`jonaswinkler`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
| Doxie | `Q2`_ | | | | | yes |`Unkn0wnCat`_ |
|
||||
+---------+----------------+-----+-----+-----+------+----------+----------------+
|
||||
|
||||
.. _MFC-L5850DW: https://www.brother-usa.com/products/mfcl5850dw
|
||||
.. _MFC-L2750DW: https://www.brother.de/drucker/laserdrucker/mfc-l2750dw
|
||||
.. _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
|
||||
.. _ADS-1100W: https://support.brother.com/g/b/downloadtop.aspx?c=fr&lang=fr&prod=ads1100w_eu_as_cn
|
||||
.. _ADS-2800W: https://www.brother-usa.com/products/ads2800w
|
||||
.. _MFC-J6930DW: https://www.brother.ca/en/p/MFCJ6930DW
|
||||
.. _MFC-J5910DW: https://www.brother.co.uk/printers/inkjet-printers/mfcj5910dw
|
||||
.. _MFC-8950DW: https://www.brother-usa.com/products/mfc8950dw
|
||||
.. _MFC-9142CDN: https://www.brother.co.uk/printers/laser-printers/mfc9140cdn
|
||||
.. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/
|
||||
.. _ES-580W: https://epson.com/Support/Scanners/ES-Series/Epson-WorkForce-ES-580W/s/SPT_B11B258201
|
||||
.. _WF-7710DWF: https://www.epson.de/en/products/printers/inkjet-printers/for-home/workforce-wf-7710dwf
|
||||
.. _ix500: http://www.fujitsu.com/us/products/computing/peripheral/scanners/scansnap/ix500/
|
||||
.. _S1300i: https://www.fujitsu.com/global/products/computing/peripheral/scanners/soho/s1300i/
|
||||
.. _Q2: https://www.getdoxie.com/product/doxie-q/
|
||||
|
||||
.. _danielquinn: https://github.com/danielquinn
|
||||
.. _ayounggun: https://github.com/ayounggun
|
||||
.. _bmsleight: https://github.com/bmsleight
|
||||
.. _danielquinn: https://github.com/danielquinn
|
||||
.. _eonist: https://github.com/eonist
|
||||
.. _fignew: https://github.com/fignew
|
||||
.. _holzhannes: https://github.com/holzhannes
|
||||
.. _jonaswinkler: https://github.com/jonaswinkler
|
||||
.. _REOLDEV: https://github.com/REOLDEV
|
||||
.. _Skylinar: https://github.com/Skylinar
|
||||
.. _jonaswinkler: https://github.com/jonaswinkler
|
||||
.. _ytzelf: https://github.com/ytzelf
|
||||
.. _Unkn0wnCat: https://github.com/Unkn0wnCat
|
||||
.. _muued: https://github.com/muued
|
||||
.. _philpagel: https://github.com/philpagel
|
||||
|
||||
.. [1] Scanners with API Integration allow to push scanned documents directly to :ref:`Paperless API <api-file_uploads>`, sometimes referred to as Webhook or Document POST.
|
||||
|
||||
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`_ |
|
||||
+-----------------------------+----------------+-----+-----+-----+-------+--------+------------------+
|
||||
| `OpenScan`_ | Android | no | no | no | no | no | `benjaminfrank`_ |
|
||||
+-----------------------------+----------------+-----+-----+-----+-------+--------+------------------+
|
||||
| `OCR Scanner - QuickScan`_ | iOS | no | no | no | no | yes | `holzhannes`_ |
|
||||
+-----------------------------+----------------+-----+-----+-----+-------+--------+------------------+
|
||||
|
||||
On Android, you can use these applications in combination with one of the :ref:`Paperless-ngx compatible apps <usage-mobile_upload>` 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
|
||||
.. _OCR Scanner - QuickScan: 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
|
||||
|
@@ -4,7 +4,7 @@
|
||||
Screenshots
|
||||
***********
|
||||
|
||||
This is what paperless-ng looks like. You shouldn't use paperless to index
|
||||
This is what paperless-ngx looks like. You shouldn't use paperless to index
|
||||
research papers though, its a horrible tool for that job.
|
||||
|
||||
The dashboard shows customizable views on your document and allows document uploads:
|
||||
|
534
docs/setup.rst
@@ -3,39 +3,10 @@
|
||||
Setup
|
||||
*****
|
||||
|
||||
Download
|
||||
########
|
||||
Overview of Paperless-ngx
|
||||
#########################
|
||||
|
||||
Go to the project page on GitHub and download the
|
||||
`latest release <https://github.com/jonaswinkler/paperless-ng/releases>`_.
|
||||
There are multiple options available.
|
||||
|
||||
* Download the dockerfiles archive if you want to pull paperless from
|
||||
Docker Hub.
|
||||
|
||||
* Download the dist archive and extract it if you want to build the docker image
|
||||
yourself or want to install paperless without docker.
|
||||
|
||||
.. hint::
|
||||
|
||||
In contrast to paperless, the recommended way to get and update paperless-ng
|
||||
is not to pull the entire git repository. Paperless-ng includes artifacts
|
||||
that need to be compiled, and that's already done for you in the release.
|
||||
|
||||
.. admonition:: Want to try out paperless-ng before migrating?
|
||||
|
||||
The release contains a file ``.env`` which sets the docker-compose project
|
||||
name to "paperless", which is the same as before and instructs docker-compose
|
||||
to reuse and upgrade your paperless volumes.
|
||||
|
||||
Just rename the project name in that file to anything else and docker-compose
|
||||
will create fresh volumes for you!
|
||||
|
||||
|
||||
Overview of Paperless-ng
|
||||
########################
|
||||
|
||||
Compared to paperless, paperless-ng works a little different under the hood and has
|
||||
Compared to paperless, paperless-ngx works a little different under the hood and has
|
||||
more moving parts that work together. While this increases the complexity of
|
||||
the system, it also brings many benefits.
|
||||
|
||||
@@ -49,45 +20,45 @@ Paperless consists of the following components:
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/src/
|
||||
$ pipenv run gunicorn -c /usr/src/paperless/gunicorn.conf.py -b 0.0.0.0:8000 paperless.wsgi
|
||||
$ gunicorn -c ../gunicorn.conf.py paperless.wsgi
|
||||
|
||||
or by any other means such as Apache ``mod_wsgi``.
|
||||
|
||||
* **The consumer:** This is what watches your consumption folder for documents.
|
||||
However, the consumer itself does not consume really consume your documents anymore.
|
||||
It rather notifies a task processor that a new file is ready for consumption.
|
||||
However, the consumer itself does not really consume your documents.
|
||||
Now it notifies a task processor that a new file is ready for consumption.
|
||||
I suppose it should be named differently.
|
||||
This also used to check your emails, but that's now gone elsewhere as well.
|
||||
This was also used to check your emails, but that's now done elsewhere as well.
|
||||
|
||||
Start the consumer with the management command ``document_consumer``:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/src/
|
||||
$ pipenv run python3 manage.py document_consumer
|
||||
$ python3 manage.py document_consumer
|
||||
|
||||
.. _setup-task_processor:
|
||||
|
||||
* **The task processor:** Paperless relies on `Django Q <https://django-q.readthedocs.io/en/latest/>`_
|
||||
for doing much of the heavy lifting. This is a task queue that accepts tasks from
|
||||
multiple sources and processes tasks in parallel. It also comes with a scheduler that executes
|
||||
for doing most of the heavy lifting. This is a task queue that accepts tasks from
|
||||
multiple sources and processes these in parallel. It also comes with a scheduler that executes
|
||||
certain commands periodically.
|
||||
|
||||
This task processor is responsible for:
|
||||
|
||||
* Consuming documents. When the consumer finds new documents, it notifies the task processor to
|
||||
start a consumption task.
|
||||
* Consuming emails. It periodically checks your configured accounts for new mails and
|
||||
produces consumption tasks for any documents it finds.
|
||||
* The task processor also performs the consumption of any documents you upload through
|
||||
the web interface.
|
||||
* Maintain the search index and the automatic matching algorithm. These are things that paperless
|
||||
* Consuming emails. It periodically checks your configured accounts for new emails and
|
||||
notifies the task processor to consume the attachment of an email.
|
||||
* Maintaining the search index and the automatic matching algorithm. These are things that paperless
|
||||
needs to do from time to time in order to operate properly.
|
||||
|
||||
This allows paperless to process multiple documents from your consumption folder in parallel! On
|
||||
a modern multi core system, consumption with full ocr is blazing fast.
|
||||
a modern multi core system, this makes the consumption process with full OCR blazingly fast.
|
||||
|
||||
The task processor comes with a built-in admin interface that you can use to see whenever any of the
|
||||
The task processor comes with a built-in admin interface that you can use to check whenever any of the
|
||||
tasks fail and inspect the errors (i.e., wrong email credentials, errors during consuming a specific
|
||||
file, etc).
|
||||
|
||||
@@ -96,11 +67,11 @@ Paperless consists of the following components:
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless/src/
|
||||
$ pipenv run python3 manage.py qcluster
|
||||
$ python3 manage.py qcluster
|
||||
|
||||
* A `redis <https://redis.io/>`_ message broker: This is a really lightweight service that is responsible
|
||||
for getting the tasks from the webserver and consumer to the task scheduler. These run in different
|
||||
processes (maybe even on different machines!), and therefore, this is necessary.
|
||||
for getting the tasks from the webserver and the consumer to the task scheduler. These run in a different
|
||||
process (maybe even on different machines!), and therefore, this is necessary.
|
||||
|
||||
* Optional: A database server. Paperless supports both PostgreSQL and SQLite for storing its data.
|
||||
|
||||
@@ -108,50 +79,78 @@ Paperless consists of the following components:
|
||||
Installation
|
||||
############
|
||||
|
||||
You can go multiple routes with setting up and running Paperless:
|
||||
You can go multiple routes to setup and run Paperless:
|
||||
|
||||
* The `docker route`_
|
||||
* The `bare metal route`_
|
||||
* :ref:`Use the easy install docker script <setup-docker_script>`
|
||||
* :ref:`Pull the image from Docker Hub <setup-docker_hub>`
|
||||
* :ref:`Build the Docker image yourself <setup-docker_build>`
|
||||
* :ref:`Install Paperless directly on your system manually (bare metal) <setup-bare_metal>`
|
||||
|
||||
The `docker route`_ is quick & easy. This is the recommended route. This configures all the stuff
|
||||
from above automatically so that it just works and uses sensible defaults for all configuration options.
|
||||
The Docker routes are quick & easy. These are the recommended routes. This configures all the stuff
|
||||
from the above automatically so that it just works and uses sensible defaults for all configuration options.
|
||||
Here you find a cheat-sheet for docker beginners: `CLI Basics <https://www.sehn.tech/refs/devops-with-docker/>`_
|
||||
|
||||
The `bare metal route`_ is more complicated to setup but makes it easier
|
||||
The bare metal route is complicated to setup but makes it easier
|
||||
should you want to contribute some code back. You need to configure and
|
||||
run the above mentioned components yourself.
|
||||
|
||||
.. _setup-docker_route:
|
||||
.. _CLI Basics: https://www.sehn.tech/refs/devops-with-docker/
|
||||
|
||||
Docker Route
|
||||
============
|
||||
.. _setup-docker_script:
|
||||
|
||||
1. Install `Docker`_ and `docker-compose`_. [#compose]_
|
||||
Install Paperless from Docker Hub using the installation script
|
||||
===============================================================
|
||||
|
||||
.. caution::
|
||||
Paperless provides an interactive installation script. This script will ask you
|
||||
for a couple configuration options, download and create the necessary configuration files, pull the docker image, start paperless and create your user account. This script essentially
|
||||
performs all the steps described in :ref:`setup-docker_hub` automatically.
|
||||
|
||||
If you want to use the included ``docker-compose.*.yml`` file, you
|
||||
need to have at least Docker version **17.09.0** and docker-compose
|
||||
version **1.17.0**.
|
||||
1. Make sure that docker and docker-compose are installed.
|
||||
2. Download and run the installation script:
|
||||
|
||||
See the `Docker installation guide`_ on how to install the current
|
||||
version of Docker for your operating system or Linux distribution of
|
||||
choice. To get an up-to-date version of docker-compose, follow the
|
||||
`docker-compose installation guide`_ if your package repository doesn't
|
||||
include it.
|
||||
.. code:: shell-session
|
||||
|
||||
.. _Docker installation guide: https://docs.docker.com/engine/installation/
|
||||
.. _docker-compose installation guide: https://docs.docker.com/compose/install/
|
||||
$ bash -c "$(curl -L https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/master/install-paperless-ngx.sh)"
|
||||
|
||||
2. Copy either ``docker-compose.sqlite.yml`` or ``docker-compose.postgres.yml`` to
|
||||
``docker-compose.yml``, depending on which database backend you want to use.
|
||||
.. _setup-docker_hub:
|
||||
|
||||
Install Paperless from Docker Hub
|
||||
=================================
|
||||
|
||||
1. Login with your user and create a folder in your home-directory `mkdir -v ~/paperless-ngx` to have a place for your configuration files and consumption directory.
|
||||
|
||||
2. Go to the `/docker/compose directory on the project page <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`_
|
||||
and download one of the `docker-compose.*.yml` files, depending on which database backend you
|
||||
want to use. Rename this file to `docker-compose.yml`.
|
||||
If you want to enable optional support for Office documents, download a file with `-tika` in the file name.
|
||||
Download the ``docker-compose.env`` file and the ``.env`` file as well and store them
|
||||
in the same directory.
|
||||
|
||||
.. hint::
|
||||
|
||||
For new installations, it is recommended to use PostgreSQL as the database
|
||||
backend.
|
||||
|
||||
2. Modify ``docker-compose.yml`` to your preferences. You may want to change the path
|
||||
to the consumption directory in this file. Find the line that specifies where
|
||||
3. Install `Docker`_ and `docker-compose`_.
|
||||
|
||||
.. caution::
|
||||
|
||||
If you want to use the included ``docker-compose.*.yml`` file, you
|
||||
need to have at least Docker version **17.09.0** and docker-compose
|
||||
version **1.17.0**.
|
||||
To check do: `docker-compose -v` or `docker -v`
|
||||
|
||||
See the `Docker installation guide`_ on how to install the current
|
||||
version of Docker for your operating system or Linux distribution of
|
||||
choice. To get the latest version of docker-compose, follow the
|
||||
`docker-compose installation guide`_ if your package repository doesn't
|
||||
include it.
|
||||
|
||||
.. _Docker installation guide: https://docs.docker.com/engine/installation/
|
||||
.. _docker-compose installation guide: https://docs.docker.com/compose/install/
|
||||
|
||||
4. Modify ``docker-compose.yml`` to your preferences. You may want to change the path
|
||||
to the consumption directory. Find the line that specifies where
|
||||
to mount the consumption directory:
|
||||
|
||||
.. code::
|
||||
@@ -166,33 +165,53 @@ Docker Route
|
||||
|
||||
Don't change the part after the colon or paperless wont find your documents.
|
||||
|
||||
You may also need to change the default port that the webserver will use
|
||||
from the default (8000):
|
||||
|
||||
3. Modify ``docker-compose.env``, following the comments in the file. The
|
||||
.. code::
|
||||
|
||||
ports:
|
||||
- 8000:8000
|
||||
|
||||
Replace the part BEFORE the colon with a port of your choice:
|
||||
|
||||
.. code::
|
||||
|
||||
ports:
|
||||
- 8010:8000
|
||||
|
||||
Don't change the part after the colon or edit other lines that refer to
|
||||
port 8000. Modifying the part before the colon will map requests on another
|
||||
port to the webserver running on the default port.
|
||||
|
||||
5. Modify ``docker-compose.env``, following the comments in the file. The
|
||||
most important change is to set ``USERMAP_UID`` and ``USERMAP_GID``
|
||||
to the uid and gid of your user on the host system. This ensures that
|
||||
to the uid and gid of your user on the host system. Use ``id -u`` and
|
||||
``id -g`` to get these.
|
||||
|
||||
This ensures that
|
||||
both the docker container and you on the host machine have write access
|
||||
to the consumption directory. If your UID and GID on the host system is
|
||||
1000 (the default for the first normal user on most systems), it will
|
||||
work out of the box without any modifications.
|
||||
work out of the box without any modifications. `id "username"` to check.
|
||||
|
||||
.. note::
|
||||
|
||||
You can use any settings from the file ``paperless.conf`` in this file.
|
||||
Have a look at :ref:`configuration` to see whats available.
|
||||
|
||||
You can copy any setting from the file ``paperless.conf.example`` and paste it here.
|
||||
Have a look at :ref:`configuration` to see what's available.
|
||||
|
||||
.. caution::
|
||||
|
||||
Certain file systems such as NFS network shares don't support file system
|
||||
Some file systems such as NFS network shares don't support file system
|
||||
notifications with ``inotify``. When storing the consumption directory
|
||||
on such a file system, paperless will be unable to pick up new files
|
||||
on such a file system, paperless will not pick up new files
|
||||
with the default configuration. You will need to use ``PAPERLESS_CONSUMER_POLLING``,
|
||||
which will disable inotify. See :ref:`here <configuration-polling>`.
|
||||
|
||||
4. Run ``docker-compose up -d``. This will create and start the necessary
|
||||
containers. This will also build the image of paperless if you grabbed the
|
||||
source archive.
|
||||
6. Run ``docker-compose pull``, followed by ``docker-compose up -d``.
|
||||
This will pull the image, create and start the necessary containers.
|
||||
|
||||
5. To be able to login, you will need a super user. To create it, execute the
|
||||
7. To be able to login, you will need a super user. To create it, execute the
|
||||
following command:
|
||||
|
||||
.. code-block:: shell-session
|
||||
@@ -200,21 +219,57 @@ Docker Route
|
||||
$ docker-compose run --rm webserver createsuperuser
|
||||
|
||||
This will prompt you to set a username, an optional e-mail address and
|
||||
finally a password.
|
||||
finally a password (at least 8 characters).
|
||||
|
||||
6. The default ``docker-compose.yml`` exports the webserver on your local port
|
||||
8000. If you haven't adapted this, you should now be able to visit your
|
||||
Paperless instance at ``http://127.0.0.1:8000``. You can login with the
|
||||
user and password you just created.
|
||||
8. The default ``docker-compose.yml`` exports the webserver on your local port
|
||||
8000. If you did not change this, you should now be able to visit your
|
||||
Paperless instance at ``http://127.0.0.1:8000`` or your servers IP-Address:8000.
|
||||
Use the login credentials you have created with the previous step.
|
||||
|
||||
.. _Docker: https://www.docker.com/
|
||||
.. _docker-compose: https://docs.docker.com/compose/install/
|
||||
|
||||
.. [#compose] You of course don't have to use docker-compose, but it
|
||||
simplifies deployment immensely. If you know your way around Docker, feel
|
||||
free to tinker around without using compose!
|
||||
.. _setup-docker_build:
|
||||
|
||||
.. _`setup-bare_metal`:
|
||||
Build the Docker image yourself
|
||||
===============================
|
||||
|
||||
1. Clone the entire repository of paperless:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
git clone https://github.com/paperless-ngx/paperless-ngx
|
||||
|
||||
The master branch always reflects the latest stable version.
|
||||
|
||||
2. Copy one of the ``docker/compose/docker-compose.*.yml`` to ``docker-compose.yml`` in the root folder,
|
||||
depending on which database backend you want to use. Copy
|
||||
``docker-compose.env`` into the project root as well.
|
||||
|
||||
3. In the ``docker-compose.yml`` file, find the line that instructs docker-compose to pull the paperless image from Docker Hub:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
webserver:
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
|
||||
and replace it with a line that instructs docker-compose to build the image from the current working directory instead:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
webserver:
|
||||
build: .
|
||||
|
||||
4. Follow steps 3 to 8 of :ref:`setup-docker_hub`. When asked to run
|
||||
``docker-compose pull`` to pull the image, do
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker-compose build
|
||||
|
||||
instead to build the image.
|
||||
|
||||
.. _setup-bare_metal:
|
||||
|
||||
Bare Metal Route
|
||||
================
|
||||
@@ -225,17 +280,23 @@ writing. Windows is not and will never be supported.
|
||||
|
||||
1. Install dependencies. Paperless requires the following packages.
|
||||
|
||||
* ``python3`` 3.6, 3.7, 3.8 (3.9 is untested).
|
||||
* ``python3-pip``, optionally ``pipenv`` for package installation
|
||||
* ``python3`` 3.8, 3.9
|
||||
* ``python3-pip``
|
||||
* ``python3-dev``
|
||||
|
||||
* ``fonts-liberation`` for generating thumbnails for plain text files
|
||||
* ``imagemagick`` >= 6 for PDF conversion
|
||||
* ``optipng`` for optimizing thumbnails
|
||||
* ``gnupg`` for handling encrypted documents
|
||||
* ``libpoppler-cpp-dev`` for PDF to text conversion
|
||||
* ``libmagic-dev`` for mime type detection
|
||||
* ``libpq-dev`` for PostgreSQL
|
||||
* ``libmagic-dev`` for mime type detection
|
||||
* ``mime-support`` for mime type detection
|
||||
|
||||
Use this list for your preferred package management:
|
||||
|
||||
.. code::
|
||||
|
||||
python3 python3-pip python3-dev imagemagick fonts-liberation optipng gnupg libpq-dev libmagic-dev mime-support
|
||||
|
||||
These dependencies are required for OCRmyPDF, which is used for text recognition.
|
||||
|
||||
@@ -250,16 +311,28 @@ writing. Windows is not and will never be supported.
|
||||
* ``tesseract-ocr`` >= 4.0.0 for OCR
|
||||
* ``tesseract-ocr`` language packs (``tesseract-ocr-eng``, ``tesseract-ocr-deu``, etc)
|
||||
|
||||
Use this list for your preferred package management:
|
||||
|
||||
.. code::
|
||||
|
||||
unpaper ghostscript icc-profiles-free qpdf liblept5 libxml2 pngquant zlib1g tesseract-ocr
|
||||
|
||||
On Raspberry Pi, these libraries are required as well:
|
||||
|
||||
* ``libatlas-base-dev``
|
||||
* ``libxslt1-dev``
|
||||
|
||||
You will also need ``build-essential``, ``python3-setuptools`` and ``python3-wheel``
|
||||
for installing some of the python dependencies.
|
||||
|
||||
2. Install ``redis`` >= 5.0 and configure it to start automatically.
|
||||
|
||||
3. Optional. Install ``postgresql`` and configure a database, user and password for paperless. If you do not wish
|
||||
to use PostgreSQL, SQLite is avialable as well.
|
||||
to use PostgreSQL, SQLite is available as well.
|
||||
|
||||
4. Get the release archive. If you pull the git repo as it is, you also have to compile the front end by yourself.
|
||||
Extract the frontend to a place from where you wish to execute it, such as ``/opt/paperless``.
|
||||
4. Get the release archive from `<https://github.com/paperless-ngx/paperless-ngx/releases>`_.
|
||||
If you clone the git repo as it is, you also have to compile the front end by yourself.
|
||||
Extract the archive to a place from where you wish to execute it, such as ``/opt/paperless``.
|
||||
|
||||
5. Configure paperless. See :ref:`configuration` for details. Edit the included ``paperless.conf`` and adjust the
|
||||
settings to your needs. Required settings for getting paperless running are:
|
||||
@@ -272,61 +345,73 @@ writing. Windows is not and will never be supported.
|
||||
paperless stores its data. If you like, you can point both to the same directory.
|
||||
* ``PAPERLESS_SECRET_KEY`` should be a random sequence of characters. It's used for authentication. Failure
|
||||
to do so allows third parties to forge authentication credentials.
|
||||
|
||||
|
||||
Many more adjustments can be made to paperless, especially the OCR part. The following options are recommended
|
||||
for everyone:
|
||||
|
||||
* Set ``PAPERLESS_OCR_LANGUAGE`` to the language most of your documents are written in.
|
||||
* Set ``PAPERLESS_TIME_ZONE`` to your local time zone.
|
||||
|
||||
6. Setup permissions. Create a system users under which you wish to run paperless. Ensure that these directories exist
|
||||
and that the user has write permissions to the following directories
|
||||
|
||||
6. Create a system user under which you wish to run paperless.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
adduser paperless --system --home /opt/paperless --group
|
||||
|
||||
7. Ensure that these directories exist
|
||||
and that the paperless user has write permissions to the following directories:
|
||||
|
||||
* ``/opt/paperless/media``
|
||||
* ``/opt/paperless/data``
|
||||
* ``/opt/paperless/consume``
|
||||
|
||||
Adjust as necessary if you configured different folders.
|
||||
|
||||
7. Install python requirements. Paperless comes with both Pipfiles for ``pipenv`` as well as with a ``requirements.txt``.
|
||||
Both will install exactly the same requirements. It is up to you if you wish to use a virtual environment or not.
|
||||
8. Install python requirements from the ``requirements.txt`` file.
|
||||
It is up to you if you wish to use a virtual environment or not. First you should update your pip, so it gets the actual packages.
|
||||
|
||||
8. Go to ``/opt/paperless/src``, and execute the following commands:
|
||||
.. code:: shell-session
|
||||
|
||||
sudo -Hu paperless pip3 install --upgrade pip
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
sudo -Hu paperless pip3 install -r requirements.txt
|
||||
|
||||
This will install all python dependencies in the home directory of
|
||||
the new paperless user.
|
||||
|
||||
9. Go to ``/opt/paperless/src``, and execute the following commands:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# This collects static files from paperless and django.
|
||||
python3 manage.py collectstatic --clear --no-input
|
||||
|
||||
# This creates the database schema.
|
||||
python3 manage.py migrate
|
||||
|
||||
# This creates the translation files for paperless.
|
||||
python3 manage.py compilemessages
|
||||
sudo -Hu paperless python3 manage.py migrate
|
||||
|
||||
# This creates your first paperless user
|
||||
python3 manage.py createsuperuser
|
||||
sudo -Hu paperless python3 manage.py createsuperuser
|
||||
|
||||
9. Optional: Test that paperless is working by executing
|
||||
10. Optional: Test that paperless is working by executing
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# This collects static files from paperless and django.
|
||||
python3 manage.py runserver
|
||||
|
||||
sudo -Hu paperless python3 manage.py runserver
|
||||
|
||||
and pointing your browser to http://localhost:8000/.
|
||||
|
||||
.. warning::
|
||||
|
||||
This is a development server which should not be used in
|
||||
production.
|
||||
production. It is not audited for security and performance
|
||||
is inferior to production ready web servers.
|
||||
|
||||
.. hint::
|
||||
|
||||
This will not start the consumer. Paperless does this in a
|
||||
separate process.
|
||||
|
||||
10. Setup systemd services to run paperless automatically. You may
|
||||
11. Setup systemd services to run paperless automatically. You may
|
||||
use the service definition files included in the ``scripts`` folder
|
||||
as a starting point.
|
||||
|
||||
@@ -334,17 +419,19 @@ writing. Windows is not and will never be supported.
|
||||
``consumer`` script to watch the input folder, and the ``scheduler``
|
||||
script to run tasks such as email checking and document consumption.
|
||||
|
||||
The ``socket`` script enables ``gunicorn`` to run on port 80 without
|
||||
root privileges. For this you need to uncomment the ``Require=paperless-webserver.socket``
|
||||
in the ``webserver`` script and configure ``gunicorn`` to listen on port 80 (see ``paperless/gunicorn.conf.py``).
|
||||
|
||||
You may need to adjust the path to the ``gunicorn`` executable. This
|
||||
will be installed as part of the python dependencies, and is either located
|
||||
in the ``bin`` folder of your virtual environment, or in ``~/.local/bin/`` if
|
||||
no virtual environment is used.
|
||||
|
||||
These services rely on redis and optionally the database server, but
|
||||
don't need to be started in any particular order. The example files
|
||||
depend on redis being started. If you use a database server, you should
|
||||
add additinal dependencies.
|
||||
|
||||
.. hint::
|
||||
|
||||
You may optionally set up your preferred web server to serve
|
||||
paperless as a wsgi application directly instead of running the
|
||||
``webserver`` service. The module containing the wsgi application
|
||||
is named ``paperless.wsgi``.
|
||||
add additional dependencies.
|
||||
|
||||
.. caution::
|
||||
|
||||
@@ -353,10 +440,13 @@ writing. Windows is not and will never be supported.
|
||||
however, the documentation of GUnicorn states that you should
|
||||
use a proxy server in front of gunicorn instead.
|
||||
|
||||
11. Optional: Install a samba server and make the consumption folder
|
||||
For instructions on how to use nginx for that,
|
||||
:ref:`see the instructions below <setup-nginx>`.
|
||||
|
||||
12. Optional: Install a samba server and make the consumption folder
|
||||
available as a network share.
|
||||
|
||||
12. Configure ImageMagick to allow processing of PDF documents. Most distributions have
|
||||
13. Configure ImageMagick to allow processing of PDF documents. Most distributions have
|
||||
this disabled by default, since PDF documents can contain malware. If
|
||||
you don't do this, paperless will fall back to ghostscript for certain steps
|
||||
such as thumbnail generation.
|
||||
@@ -366,19 +456,58 @@ writing. Windows is not and will never be supported.
|
||||
.. code::
|
||||
|
||||
<policy domain="coder" rights="none" pattern="PDF" />
|
||||
|
||||
|
||||
to
|
||||
|
||||
.. code::
|
||||
|
||||
<policy domain="coder" rights="read|write" pattern="PDF" />
|
||||
|
||||
Migration to paperless-ng
|
||||
#########################
|
||||
14. Optional: Install the `jbig2enc <https://ocrmypdf.readthedocs.io/en/latest/jbig2.html>`_
|
||||
encoder. This will reduce the size of generated PDF documents. You'll most likely need
|
||||
to compile this by yourself, because this software has been patented until around 2017 and
|
||||
binary packages are not available for most distributions.
|
||||
|
||||
At its core, paperless-ng is still paperless and fully compatible. However, some
|
||||
Migrating to Paperless-ngx
|
||||
##########################
|
||||
|
||||
Migration is possible both from Paperless-ng or directly from the 'original' Paperless.
|
||||
|
||||
Migrating from Paperless-ng
|
||||
===========================
|
||||
|
||||
Paperless-ngx is meant to be a drop-in replacement for Paperless-ng and thus upgrading should be
|
||||
trivial for most users, especially when using docker. However, as with any major change, it is
|
||||
recommended to take a full backup first. Once you are ready, simply change the docker image to
|
||||
point to the new source. E.g. if using Docker Compose, edit ``docker-compose.yml`` and change:
|
||||
|
||||
.. code::
|
||||
|
||||
image: jonaswinkler/paperless-ng:latest
|
||||
|
||||
to
|
||||
|
||||
.. code::
|
||||
|
||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||
|
||||
and then run ``docker-compose up -d`` which will pull the new image recreate the container.
|
||||
That's it!
|
||||
|
||||
Users who installed with the bare-metal route should also update their Git clone to point to
|
||||
``https://github.com/paperless-ngx/paperless-ngx``, e.g. using the command
|
||||
``git remote set-url origin https://github.com/paperless-ngx/paperless-ngx`` and then pull the
|
||||
lastest version.
|
||||
|
||||
Migrating from Paperless
|
||||
========================
|
||||
|
||||
At its core, paperless-ngx is still paperless and fully compatible. However, some
|
||||
things have changed under the hood, so you need to adapt your setup depending on
|
||||
how you installed paperless. The important things to keep in mind are as follows.
|
||||
how you installed paperless.
|
||||
|
||||
This setup describes how to update an existing paperless Docker installation.
|
||||
The important things to keep in mind are as follows:
|
||||
|
||||
* Read the :ref:`changelog <paperless_changelog>` and take note of breaking changes.
|
||||
* You should decide if you want to stick with SQLite or want to migrate your database
|
||||
@@ -389,10 +518,10 @@ how you installed paperless. The important things to keep in mind are as follows
|
||||
such as email checking and maintenance, requires a `redis`_ message broker
|
||||
instance. The docker-compose route takes care of that.
|
||||
* The layout of the folder structure for your documents and data remains the
|
||||
same, so you can just plug your old docker volumes into paperless-ng and
|
||||
same, so you can just plug your old docker volumes into paperless-ngx and
|
||||
expect it to find everything where it should be.
|
||||
|
||||
Migration to paperless-ng is then performed in a few simple steps:
|
||||
Migration to paperless-ngx is then performed in a few simple steps:
|
||||
|
||||
1. Stop paperless.
|
||||
|
||||
@@ -402,36 +531,38 @@ Migration to paperless-ng is then performed in a few simple steps:
|
||||
$ docker-compose down
|
||||
|
||||
2. Do a backup for two purposes: If something goes wrong, you still have your
|
||||
data. Second, if you don't like paperless-ng, you can switch back to
|
||||
data. Second, if you don't like paperless-ngx, you can switch back to
|
||||
paperless.
|
||||
|
||||
3. Download the latest release of paperless-ng. You can either go with the
|
||||
docker-compose files or use the archive to build the image yourself.
|
||||
You can either replace your current paperless folder or put paperless-ng
|
||||
3. Download the latest release of paperless-ngx. You can either go with the
|
||||
docker-compose files from `here <https://github.com/paperless-ngx/paperless-ngx/tree/master/docker/compose>`__
|
||||
or clone the repository to build the image yourself (see :ref:`above <setup-docker_build>`).
|
||||
You can either replace your current paperless folder or put paperless-ngx
|
||||
in a different location.
|
||||
|
||||
.. caution::
|
||||
|
||||
The release include a ``.env`` file. This will set the
|
||||
project name for docker compose to ``paperless`` so that paperless-ng will
|
||||
automatically reuse your existing paperless volumes. When you start it, it
|
||||
will migrate your existing data. After that, your old paperless installation
|
||||
will be incompatible with the migrated volumes.
|
||||
Paperless-ngx includes a ``.env`` file. This will set the
|
||||
project name for docker compose to ``paperless``, which will also define the name
|
||||
of the volumes by paperless-ngx. However, if you experience that paperless-ngx
|
||||
is not using your old paperless volumes, verify the names of your volumes with
|
||||
|
||||
4. Copy the ``docker-compose.sqlite.yml`` file to ``docker-compose.yml``.
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker volume ls | grep _data
|
||||
|
||||
and adjust the project name in the ``.env`` file so that it matches the name
|
||||
of the volumes before the ``_data`` part.
|
||||
|
||||
|
||||
4. Download the ``docker-compose.sqlite.yml`` file to ``docker-compose.yml``.
|
||||
If you want to switch to PostgreSQL, do that after you migrated your existing
|
||||
SQLite database.
|
||||
|
||||
5. Adjust ``docker-compose.yml`` and
|
||||
``docker-compose.env`` to your needs.
|
||||
See `docker route`_ for details on which edits are advised.
|
||||
5. Adjust ``docker-compose.yml`` and ``docker-compose.env`` to your needs.
|
||||
See :ref:`setup-docker_hub` for details on which edits are advised.
|
||||
|
||||
6. Since ``docker-compose`` would just use the the old paperless image, we need to
|
||||
manually build a new image:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker-compose build
|
||||
6. :ref:`Update paperless. <administration-updating>`
|
||||
|
||||
7. In order to find your existing documents with the new search feature, you need
|
||||
to invoke a one-time operation that will create the search index:
|
||||
@@ -439,11 +570,11 @@ Migration to paperless-ng is then performed in a few simple steps:
|
||||
.. code:: shell-session
|
||||
|
||||
$ docker-compose run --rm webserver document_index reindex
|
||||
|
||||
|
||||
This will migrate your database and create the search index. After that,
|
||||
paperless will take care of maintaining the index by itself.
|
||||
|
||||
8. Start paperless-ng.
|
||||
8. Start paperless-ngx.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
@@ -452,7 +583,7 @@ Migration to paperless-ng is then performed in a few simple steps:
|
||||
This will run paperless in the background and automatically start it on system boot.
|
||||
|
||||
9. Paperless installed a permanent redirect to ``admin/`` in your browser. This
|
||||
redirect is still in place and prevents access to the new UI. Clear
|
||||
redirect is still in place and prevents access to the new UI. Clear your
|
||||
browsing cache in order to fix this.
|
||||
|
||||
10. Optionally, follow the instructions below to migrate your existing data to PostgreSQL.
|
||||
@@ -500,19 +631,17 @@ management commands as below.
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ docker-compose run --rm webserver /bin/bash
|
||||
|
||||
|
||||
This will launch the container and initialize the PostgreSQL database.
|
||||
|
||||
b) Without docker, open a shell in your virtual environment, switch to
|
||||
|
||||
b) Without docker, remember to activate any virtual environment, switch to
|
||||
the ``src`` directory and create the database schema:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ cd /path/to/paperless
|
||||
$ pipenv shell
|
||||
$ cd src
|
||||
$ cd /path/to/paperless/src
|
||||
$ python3 manage.py migrate
|
||||
|
||||
|
||||
This will not copy any data yet.
|
||||
|
||||
4. Dump your data from SQLite:
|
||||
@@ -520,14 +649,14 @@ management commands as below.
|
||||
.. code:: shell-session
|
||||
|
||||
$ python3 manage.py dumpdata --database=sqlite --exclude=contenttypes --exclude=auth.Permission > data.json
|
||||
|
||||
|
||||
5. Load your data into PostgreSQL:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
$ python3 manage.py loaddata data.json
|
||||
|
||||
6. Exit the shell.
|
||||
6. If operating inside Docker, you may exit the shell now.
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
@@ -536,14 +665,14 @@ management commands as below.
|
||||
7. Start paperless.
|
||||
|
||||
|
||||
Moving back to paperless
|
||||
Moving back to Paperless
|
||||
========================
|
||||
|
||||
Lets say you migrated to Paperless-ng and used it for a while, but decided that
|
||||
Lets say you migrated to Paperless-ngx and used it for a while, but decided that
|
||||
you don't like it and want to move back (If you do, send me a mail about what
|
||||
part you didn't like!), you can totally do that with a few simple steps.
|
||||
|
||||
Paperless-ng modified the database schema slightly, however, these changes can
|
||||
Paperless-ngx modified the database schema slightly, however, these changes can
|
||||
be reverted while keeping your current data, so that your current data will
|
||||
be compatible with original Paperless.
|
||||
|
||||
@@ -561,7 +690,7 @@ Or without docker:
|
||||
$ cd /path/to/paperless/src
|
||||
$ python3 manage.py migrate documents 0023
|
||||
|
||||
After that, you need to clear your cookies (Paperless-ng comes with updated
|
||||
After that, you need to clear your cookies (Paperless-ngx comes with updated
|
||||
dependencies that do cookie-processing differently) and probably your cache
|
||||
as well.
|
||||
|
||||
@@ -571,12 +700,13 @@ as well.
|
||||
Considerations for less powerful devices
|
||||
########################################
|
||||
|
||||
Paperless runs on Raspberry Pi. However, some things are rather slow on the Pi and
|
||||
Paperless runs on Raspberry Pi. However, some things are rather slow on the Pi and
|
||||
configuring some options in paperless can help improve performance immensely:
|
||||
|
||||
* Stick with SQLite to save some resources.
|
||||
* Consider setting ``PAPERLESS_OCR_PAGES`` to 1, so that paperless will only OCR
|
||||
the first page of your documents.
|
||||
the first page of your documents. In most cases, this page contains enough
|
||||
information to be able to find it.
|
||||
* ``PAPERLESS_TASK_WORKERS`` and ``PAPERLESS_THREADS_PER_WORKER`` are configured
|
||||
to use all cores. The Raspberry Pi models 3 and up have 4 cores, meaning that
|
||||
paperless will use 2 workers and 2 threads per worker. This may result in
|
||||
@@ -587,23 +717,69 @@ configuring some options in paperless can help improve performance immensely:
|
||||
your documents before feeding them into paperless. Some scanners are able to
|
||||
do this! You might want to even specify ``skip_noarchive`` to skip archive
|
||||
file generation for already ocr'ed documents entirely.
|
||||
* If you want to perform OCR on the device, consider using ``PAPERLESS_OCR_CLEAN=none``.
|
||||
This will speed up OCR times and use less memory at the expense of slightly worse
|
||||
OCR results.
|
||||
* Set ``PAPERLESS_OPTIMIZE_THUMBNAILS`` to 'false' if you want faster consumption
|
||||
times. Thumbnails will be about 20% larger.
|
||||
* If using docker, consider setting ``PAPERLESS_WEBSERVER_WORKERS`` to
|
||||
1. This will save some memory.
|
||||
|
||||
For details, refer to :ref:`configuration`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
Updating the :ref:`automatic matching algorithm <advanced-automatic_matching>`
|
||||
takes quite a bit of time. However, the update mechanism checks if your
|
||||
data has changed before doing the heavy lifting. If you experience the
|
||||
data has changed before doing the heavy lifting. If you experience the
|
||||
algorithm taking too much cpu time, consider changing the schedule in the
|
||||
admin interface to daily. You can also manually invoke the task
|
||||
by changing the date and time of the next run to today/now.
|
||||
|
||||
The actual matching of the algorithm is fast and works on Raspberry Pi as
|
||||
The actual matching of the algorithm is fast and works on Raspberry Pi as
|
||||
well as on any other device.
|
||||
|
||||
|
||||
|
||||
.. _redis: https://redis.io/
|
||||
|
||||
|
||||
.. _setup-nginx:
|
||||
|
||||
Using nginx as a reverse proxy
|
||||
##############################
|
||||
|
||||
If you want to expose paperless to the internet, you should hide it behind a
|
||||
reverse proxy with SSL enabled.
|
||||
|
||||
In addition to the usual configuration for SSL,
|
||||
the following configuration is required for paperless to operate:
|
||||
|
||||
.. code:: nginx
|
||||
|
||||
http {
|
||||
|
||||
# Adjust as required. This is the maximum size for file uploads.
|
||||
# The default value 1M might be a little too small.
|
||||
client_max_body_size 10M;
|
||||
|
||||
server {
|
||||
|
||||
location / {
|
||||
|
||||
# Adjust host and port as required.
|
||||
proxy_pass http://localhost:8000/;
|
||||
|
||||
# These configuration options are required for WebSockets to work.
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Also read `this <https://channels.readthedocs.io/en/stable/deploying.html#nginx-supervisor-ubuntu>`__, towards the end of the section.
|
||||
|
@@ -30,13 +30,22 @@ Consumer fails to pickup any new files
|
||||
######################################
|
||||
|
||||
If you notice that the consumer will only pickup files in the consumption
|
||||
directory at startup, but won't find any other files added later, check out
|
||||
the configuration file and enable filesystem polling with the setting
|
||||
``PAPERLESS_CONSUMER_POLLING``.
|
||||
directory at startup, but won't find any other files added later, you will need to
|
||||
enable filesystem polling with the configuration option
|
||||
``PAPERLESS_CONSUMER_POLLING``, see :ref:`here <configuration-polling>`.
|
||||
|
||||
This will disable listening to filesystem changes with inotify and paperless will
|
||||
manually check the consumption directory for changes instead.
|
||||
|
||||
|
||||
Paperless always redirects to /admin
|
||||
####################################
|
||||
|
||||
You probably had the old paperless installed at some point. Paperless installed
|
||||
a permanent redirect to /admin in your browser, and you need to clear your
|
||||
browsing data / cache to fix that.
|
||||
|
||||
|
||||
Operation not permitted
|
||||
#######################
|
||||
|
||||
@@ -51,7 +60,8 @@ required so that the user running paperless inside docker has write permissions
|
||||
to these folders. This happens when pointing these directories to NFS shares,
|
||||
for example.
|
||||
|
||||
Ensure that `chown` is possible on these directories.
|
||||
Ensure that ``chown`` is possible on these directories.
|
||||
|
||||
|
||||
Classifier error: No training data available
|
||||
############################################
|
||||
@@ -64,6 +74,50 @@ This may have two reasons:
|
||||
with Inbox tags. Verify that there are documents in your archive without inbox tags.
|
||||
The algorithm will only learn from documents not in your inbox.
|
||||
|
||||
|
||||
UserWarning in sklearn on every single document
|
||||
###############################################
|
||||
|
||||
You may encounter warnings like this:
|
||||
|
||||
.. code::
|
||||
|
||||
/usr/local/lib/python3.7/site-packages/sklearn/base.py:315:
|
||||
UserWarning: Trying to unpickle estimator CountVectorizer from version 0.23.2 when using version 0.24.0.
|
||||
This might lead to breaking code or invalid results. Use at your own risk.
|
||||
|
||||
This happens when certain dependencies of paperless that are responsible for the auto matching algorithm are
|
||||
updated. After updating these, your current training data *might* not be compatible anymore. This can be ignored
|
||||
in most cases. This warning will disappear automatically when paperless updates the training data.
|
||||
|
||||
If you want to get rid of the warning or actually experience issues with automatic matching, delete
|
||||
the file ``classification_model.pickle`` in the data directory and let paperless recreate it.
|
||||
|
||||
|
||||
504 Server Error: Gateway Timeout when adding Office documents
|
||||
##############################################################
|
||||
|
||||
You may experience these errors when using the optional TIKA integration:
|
||||
|
||||
.. code::
|
||||
|
||||
requests.exceptions.HTTPError: 504 Server Error: Gateway Timeout for url: http://gotenberg:3000/forms/libreoffice/convert
|
||||
|
||||
Gotenberg is a server that converts Office documents into PDF documents and has a default timeout of 30 seconds.
|
||||
When conversion takes longer, Gotenberg raises this error.
|
||||
|
||||
You can increase the timeout by configuring an environment variable for Gotenberg (see also `here <https://gotenberg.dev/docs/modules/api#properties>`__).
|
||||
If using docker-compose, this is achieved by the following configuration change in the ``docker-compose.yml`` file:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
gotenberg:
|
||||
image: gotenberg/gotenberg:7
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CHROMIUM_DISABLE_ROUTES: 1
|
||||
API_PROCESS_TIMEOUT: 60
|
||||
|
||||
Permission denied errors in the consumption directory
|
||||
#####################################################
|
||||
|
||||
@@ -75,6 +129,95 @@ You might encounter errors such as:
|
||||
|
||||
This happens when paperless does not have permission to delete files inside the consumption directory.
|
||||
Ensure that ``USERMAP_UID`` and ``USERMAP_GID`` are set to the user id and group id you use on the host operating system, if these are
|
||||
different from ``1000``. See :ref:`setup-docker_route`.
|
||||
different from ``1000``. See :ref:`setup-docker_hub`.
|
||||
|
||||
Also ensure that you are able to read and write to the consumption directory on the host.
|
||||
|
||||
|
||||
OSError: [Errno 19] No such device when consuming files
|
||||
#######################################################
|
||||
|
||||
If you experience errors such as:
|
||||
|
||||
.. code:: shell-session
|
||||
|
||||
File "/usr/local/lib/python3.7/site-packages/whoosh/codec/base.py", line 570, in open_compound_file
|
||||
return CompoundStorage(dbfile, use_mmap=storage.supports_mmap)
|
||||
File "/usr/local/lib/python3.7/site-packages/whoosh/filedb/compound.py", line 75, in __init__
|
||||
self._source = mmap.mmap(fileno, 0, access=mmap.ACCESS_READ)
|
||||
OSError: [Errno 19] No such device
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.7/site-packages/django_q/cluster.py", line 436, in worker
|
||||
res = f(*task["args"], **task["kwargs"])
|
||||
File "/usr/src/paperless/src/documents/tasks.py", line 73, in consume_file
|
||||
override_tag_ids=override_tag_ids)
|
||||
File "/usr/src/paperless/src/documents/consumer.py", line 271, in try_consume_file
|
||||
raise ConsumerError(e)
|
||||
|
||||
Paperless uses a search index to provide better and faster full text searching. This search index is stored inside
|
||||
the ``data`` folder. The search index uses memory-mapped files (mmap). The above error indicates that paperless
|
||||
was unable to create and open these files.
|
||||
|
||||
This happens when you're trying to store the data directory on certain file systems (mostly network shares)
|
||||
that don't support memory-mapped files.
|
||||
|
||||
|
||||
Web-UI stuck at "Loading..."
|
||||
############################
|
||||
|
||||
This might have multiple reasons.
|
||||
|
||||
|
||||
1. If you built the docker image yourself or deployed using the bare metal route,
|
||||
make sure that there are files in ``<paperless-root>/static/frontend/<lang-code>/``.
|
||||
If there are no files, make sure that you executed ``collectstatic`` successfully, either
|
||||
manually or as part of the docker image build.
|
||||
|
||||
If the front end is still missing, make sure that the front end is compiled (files present in
|
||||
``src/documents/static/frontend``). If it is not, you need to compile the front end yourself
|
||||
or download the release archive instead of cloning the repository.
|
||||
|
||||
2. Check the output of the web server. You might see errors like this:
|
||||
|
||||
|
||||
.. code::
|
||||
|
||||
[2021-01-25 10:08:04 +0000] [40] [ERROR] Socket error processing request.
|
||||
Traceback (most recent call last):
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 134, in handle
|
||||
self.handle_request(listener, req, client, addr)
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 190, in handle_request
|
||||
util.reraise(*sys.exc_info())
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/util.py", line 625, in reraise
|
||||
raise value
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 178, in handle_request
|
||||
resp.write_file(respiter)
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 396, in write_file
|
||||
if not self.sendfile(respiter):
|
||||
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/wsgi.py", line 386, in sendfile
|
||||
sent += os.sendfile(sockno, fileno, offset + sent, count)
|
||||
OSError: [Errno 22] Invalid argument
|
||||
|
||||
To fix this issue, add
|
||||
|
||||
.. code::
|
||||
|
||||
SENDFILE=0
|
||||
|
||||
to your `docker-compose.env` file.
|
||||
|
||||
Error while reading metadata
|
||||
############################
|
||||
|
||||
You might find messages like these in your log files:
|
||||
|
||||
.. code::
|
||||
|
||||
[WARNING] [paperless.parsing.tesseract] Error while reading metadata
|
||||
|
||||
This indicates that paperless failed to read PDF metadata from one of your documents. This happens when you
|
||||
open the affected documents in paperless for editing. Paperless will continue to work, and will simply not
|
||||
show the invalid metadata.
|
||||
|
@@ -24,7 +24,7 @@ Each document has a couple of fields that you can assign to them:
|
||||
* A *Document* is a piece of paper that sometimes contains valuable
|
||||
information.
|
||||
* The *correspondent* of a document is the person, institution or company that
|
||||
a document either originates form, or is sent to.
|
||||
a document either originates from, or is sent to.
|
||||
* A *tag* is a label that you can assign to documents. Think of labels as more
|
||||
powerful folders: Multiple documents can be grouped together with a single
|
||||
tag, however, a single document can also have multiple tags. This is not
|
||||
@@ -71,7 +71,7 @@ your documents:
|
||||
|
||||
This process can be configured to fit your needs. If you don't want paperless
|
||||
to create archived versions for digital documents, you can configure that by
|
||||
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
|
||||
configuring ``PAPERLESS_OCR_MODE=skip_noarchive``. Please read the
|
||||
:ref:`relevant section in the documentation <configuration-ocr>`.
|
||||
|
||||
.. note::
|
||||
@@ -86,10 +86,9 @@ The consumption directory
|
||||
=========================
|
||||
|
||||
The primary method of getting documents into your database is by putting them in
|
||||
the consumption directory. The consumer runs in an infinite
|
||||
loop looking for new additions to this directory and when it finds them, it goes
|
||||
about the process of parsing them with the OCR, indexing what it finds, and storing
|
||||
it in the media directory.
|
||||
the consumption directory. The consumer runs in an infinite loop, looking for new
|
||||
additions to this directory. When it finds them, the consumer goes about the process
|
||||
of parsing them with the OCR, indexing what it finds, and storing it in the media directory.
|
||||
|
||||
Getting stuff into this directory is up to you. If you're running Paperless
|
||||
on your local computer, you might just want to drag and drop files there, but if
|
||||
@@ -110,6 +109,8 @@ The dashboard has a file drop field to upload documents to paperless. Simply dra
|
||||
onto this field or select a file with the file dialog. Multiple files are supported.
|
||||
|
||||
|
||||
.. _usage-mobile_upload:
|
||||
|
||||
Mobile upload
|
||||
=============
|
||||
|
||||
@@ -118,14 +119,14 @@ to share any documents with paperless. This can be combined with any of the mobi
|
||||
scanning apps out there, such as Office Lens.
|
||||
|
||||
Furthermore, there is the `Paperless App <https://github.com/bauerj/paperless_app>`_ as well,
|
||||
which no only has document upload, but also document editing and browsing.
|
||||
which not only has document upload, but also document browsing and download features.
|
||||
|
||||
.. _usage-email:
|
||||
|
||||
IMAP (Email)
|
||||
============
|
||||
|
||||
You can tell paperless-ng to consume documents from your email accounts.
|
||||
You can tell paperless-ngx to consume documents from your email accounts.
|
||||
This is a very flexible and powerful feature, if you regularly received documents
|
||||
via mail that you need to archive. The mail consumer can be configured by using the
|
||||
admin interface in the following manner:
|
||||
@@ -253,6 +254,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
|
||||
#########
|
||||
|
||||
@@ -285,7 +288,7 @@ Matching specific tags, correspondents or types:
|
||||
Matching dates:
|
||||
|
||||
.. code::
|
||||
|
||||
|
||||
created:[2005 to 2009]
|
||||
added:yesterday
|
||||
modified:today
|
||||
@@ -302,11 +305,11 @@ Matching inexact words:
|
||||
auto complete and query correction.
|
||||
|
||||
All of these constructs can be combined as you see fit.
|
||||
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
|
||||
If you want to learn more about the query language used by paperless, paperless uses Whoosh's default query language.
|
||||
Head over to `Whoosh query language <https://whoosh.readthedocs.io/en/latest/querylang.html>`_.
|
||||
For details on what date parsing utilities are available, see
|
||||
`Date parsing <https://whoosh.readthedocs.io/en/latest/dates.html#parsing-date-queries>`_.
|
||||
|
||||
|
||||
|
||||
.. _usage-recommended_workflow:
|
||||
|
||||
@@ -381,7 +384,7 @@ Once you have scanned in a document, proceed in paperless as follows.
|
||||
6. Remove inbox tags from the documents.
|
||||
|
||||
.. hint::
|
||||
|
||||
|
||||
You can setup manual matching rules for your correspondents and tags and
|
||||
paperless will assign them automatically. After consuming a couple documents,
|
||||
you can even ask paperless to *learn* when to assign tags and correspondents
|
||||
@@ -392,7 +395,7 @@ Task management
|
||||
|
||||
Some documents require attention and require you to act on the document. You
|
||||
may take two different approaches to handle these documents based on how
|
||||
regularly you intent to use paperless and scan documents.
|
||||
regularly you intend to scan documents and use paperless.
|
||||
|
||||
* If you scan and process your documents in paperless regularly, assign a
|
||||
TODO tag to all scanned documents that you need to process. Create a saved
|
||||
|
@@ -1,48 +1,39 @@
|
||||
bind = '0.0.0.0:8000'
|
||||
backlog = 2048
|
||||
workers = 3
|
||||
worker_class = 'sync'
|
||||
worker_connections = 1000
|
||||
timeout = 20
|
||||
keepalive = 2
|
||||
spew = False
|
||||
daemon = False
|
||||
pidfile = None
|
||||
umask = 0
|
||||
user = None
|
||||
group = None
|
||||
tmp_upload_dir = None
|
||||
loglevel = 'info'
|
||||
errorlog = '-'
|
||||
accesslog = '-'
|
||||
proc_name = None
|
||||
import os
|
||||
|
||||
bind = f'0.0.0.0:{os.getenv("PAPERLESS_PORT", 8000)}'
|
||||
workers = int(os.getenv("PAPERLESS_WEBSERVER_WORKERS", 2))
|
||||
worker_class = "paperless.workers.ConfigurableWorker"
|
||||
timeout = 120
|
||||
|
||||
|
||||
def pre_fork(server, worker):
|
||||
pass
|
||||
|
||||
|
||||
def pre_exec(server):
|
||||
server.log.info("Forked child, re-executing.")
|
||||
|
||||
|
||||
def when_ready(server):
|
||||
server.log.info("Server is ready. Spawning workers")
|
||||
|
||||
|
||||
def worker_int(worker):
|
||||
worker.log.info("worker received INT or QUIT signal")
|
||||
|
||||
## get traceback info
|
||||
import threading, sys, traceback
|
||||
|
||||
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""),
|
||||
threadId))
|
||||
code.append("\n# Thread: %s(%d)" % (id2name.get(threadId, ""), threadId))
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('File: "%s", line %d, in %s' % (filename,
|
||||
lineno, name))
|
||||
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
worker.log.debug("\n".join(code))
|
||||
|
||||
|
||||
def worker_abort(worker):
|
||||
worker.log.info("worker received SIGABRT signal")
|
||||
|
346
install-paperless-ngx.sh
Executable file
@@ -0,0 +1,346 @@
|
||||
#!/bin/bash
|
||||
|
||||
ask() {
|
||||
while true ; do
|
||||
if [[ -z $3 ]] ; then
|
||||
read -p "$1 [$2]: " result
|
||||
else
|
||||
read -p "$1 ($3) [$2]: " result
|
||||
fi
|
||||
if [[ -z $result ]]; then
|
||||
ask_result=$2
|
||||
return
|
||||
fi
|
||||
array=$3
|
||||
if [[ -z $3 || " ${array[@]} " =~ " ${result} " ]]; then
|
||||
ask_result=$result
|
||||
return
|
||||
else
|
||||
echo "Invalid option: $result"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
ask_docker_folder() {
|
||||
while true ; do
|
||||
|
||||
read -p "$1 [$2]: " result
|
||||
|
||||
if [[ -z $result ]]; then
|
||||
ask_result=$2
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ $result == /* || $result == ./* ]]; then
|
||||
ask_result=$result
|
||||
return
|
||||
else
|
||||
echo "Invalid folder: $result"
|
||||
fi
|
||||
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
if [[ $(id -u) == "0" ]] ; then
|
||||
echo "Do not run this script as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which wget) ]] ; then
|
||||
echo "wget executable not found. Is wget installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which docker) ]] ; then
|
||||
echo "docker executable not found. Is docker installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $(which docker-compose) ]] ; then
|
||||
echo "docker-compose executable not found. Is docker-compose installed?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if user has permissions to run Docker by trying to get the status of Docker (docker status).
|
||||
# If this fails, the user probably does not have permissions for Docker.
|
||||
docker stats --no-stream 2>/dev/null 1>&2
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo ""
|
||||
echo "WARN: It look like the current user does not have Docker permissions."
|
||||
echo "WARN: Use 'sudo usermod -aG docker $USER' to assign Docker permissions to the user."
|
||||
echo ""
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
default_time_zone=$(timedatectl show -p Timezone --value)
|
||||
|
||||
set -e
|
||||
|
||||
echo ""
|
||||
echo "#############################################"
|
||||
echo "### paperless-ngx docker installation ###"
|
||||
echo "#############################################"
|
||||
echo ""
|
||||
echo "This script will download, configure and start paperless-ngx."
|
||||
|
||||
echo ""
|
||||
echo "1. Application configuration"
|
||||
echo "============================"
|
||||
|
||||
echo ""
|
||||
echo "The port on which the paperless webserver will listen for incoming"
|
||||
echo "connections."
|
||||
echo ""
|
||||
|
||||
ask "Port" "8000"
|
||||
PORT=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Paperless requires you to configure the current time zone correctly."
|
||||
echo "Otherwise, the dates of your documents may appear off by one day,"
|
||||
echo "depending on where you are on earth."
|
||||
echo ""
|
||||
|
||||
ask "Current time zone" "$default_time_zone"
|
||||
TIME_ZONE=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Database backend: PostgreSQL and SQLite are available. Use PostgreSQL"
|
||||
echo "if unsure. If you're running on a low-power device such as Raspberry"
|
||||
echo "Pi, use SQLite to save resources."
|
||||
echo ""
|
||||
|
||||
ask "Database backend" "postgres" "postgres sqlite"
|
||||
DATABASE_BACKEND=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Paperless is able to use Apache Tika to support Office documents such as"
|
||||
echo "Word, Excel, Powerpoint, and Libreoffice equivalents. This feature"
|
||||
echo "requires more resources due to the required services."
|
||||
echo ""
|
||||
|
||||
ask "Enable Apache Tika?" "no" "yes no"
|
||||
TIKA_ENABLED=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Specify the default language that most of your documents are written in."
|
||||
echo "Use ISO 639-2, (T) variant language codes: "
|
||||
echo "https://www.loc.gov/standards/iso639-2/php/code_list.php"
|
||||
echo "Common values: eng (English) deu (German) nld (Dutch) fra (French)"
|
||||
echo "This can be a combination of multiple languages such as deu+eng"
|
||||
echo ""
|
||||
|
||||
ask "OCR language" "eng"
|
||||
OCR_LANGUAGE=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Specify the user id and group id you wish to run paperless as."
|
||||
echo "Paperless will also change ownership on the data, media and consume"
|
||||
echo "folder to the specified values, so it's a good idea to supply the user id"
|
||||
echo "and group id of your unix user account."
|
||||
echo "If unsure, leave default."
|
||||
echo ""
|
||||
|
||||
ask "User ID" "$(id -u)"
|
||||
USERMAP_UID=$ask_result
|
||||
|
||||
ask "Group ID" "$(id -g)"
|
||||
USERMAP_GID=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "2. Folder configuration"
|
||||
echo "======================="
|
||||
echo ""
|
||||
echo "The target folder is used to store the configuration files of "
|
||||
echo "paperless. You can move this folder around after installing paperless."
|
||||
echo "You will need this folder whenever you want to start, stop, update or "
|
||||
echo "maintain your paperless instance."
|
||||
echo ""
|
||||
|
||||
ask "Target folder" "$(pwd)/paperless-ngx"
|
||||
TARGET_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The consume folder is where paperles will search for new documents."
|
||||
echo "Point this to a folder where your scanner is able to put your scanned"
|
||||
echo "documents."
|
||||
echo ""
|
||||
echo "CAUTION: You must specify an absolute path starting with / or a relative "
|
||||
echo "path starting with ./ here. Examples:"
|
||||
echo " /mnt/consume"
|
||||
echo " ./consume"
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Consume folder" "$TARGET_FOLDER/consume"
|
||||
CONSUME_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The media folder is where paperless stores your documents."
|
||||
echo "Leave empty and docker will manage this folder for you."
|
||||
echo "Docker usually stores managed folders in /var/lib/docker/volumes."
|
||||
echo ""
|
||||
echo "CAUTION: If specified, you must specify an absolute path starting with /"
|
||||
echo "or a relative path starting with ./ here."
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Media folder" ""
|
||||
MEDIA_FOLDER=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "The data folder is where paperless stores other data, such as your"
|
||||
if [[ "$DATABASE_BACKEND" == "sqlite" ]] ; then
|
||||
echo -n "SQLite database, the "
|
||||
fi
|
||||
echo "search index and other data."
|
||||
echo "As with the media folder, leave empty to have this managed by docker."
|
||||
echo ""
|
||||
echo "CAUTION: If specified, you must specify an absolute path starting with /"
|
||||
echo "or a relative path starting with ./ here."
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Data folder" ""
|
||||
DATA_FOLDER=$ask_result
|
||||
|
||||
if [[ "$DATABASE_BACKEND" == "postgres" ]] ; then
|
||||
echo ""
|
||||
echo "The database folder, where postgres stores its data."
|
||||
echo "Leave empty to have this managed by docker."
|
||||
echo ""
|
||||
echo "CAUTION: If specified, you must specify an absolute path starting with /"
|
||||
echo "or a relative path starting with ./ here."
|
||||
echo ""
|
||||
|
||||
ask_docker_folder "Database folder" ""
|
||||
POSTGRES_FOLDER=$ask_result
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "3. Login credentials"
|
||||
echo "===================="
|
||||
echo ""
|
||||
echo "Specify initial login credentials. You can change these later."
|
||||
echo "A mail address is required, however it is not used in paperless. You don't"
|
||||
echo "need to provide an actual mail address."
|
||||
echo ""
|
||||
|
||||
ask "Paperless username" "$(whoami)"
|
||||
USERNAME=$ask_result
|
||||
|
||||
while true; do
|
||||
read -sp "Paperless password: " PASSWORD
|
||||
echo ""
|
||||
|
||||
if [[ -z $PASSWORD ]] ; then
|
||||
echo "Password cannot be empty."
|
||||
continue
|
||||
fi
|
||||
|
||||
read -sp "Paperless password (again): " PASSWORD_REPEAT
|
||||
echo ""
|
||||
|
||||
if [[ ! "$PASSWORD" == "$PASSWORD_REPEAT" ]] ; then
|
||||
echo "Passwords did not match"
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
ask "Email" "$USERNAME@localhost"
|
||||
EMAIL=$ask_result
|
||||
|
||||
echo ""
|
||||
echo "Summary"
|
||||
echo "======="
|
||||
echo ""
|
||||
|
||||
echo "Target folder: $TARGET_FOLDER"
|
||||
echo "Consume folder: $CONSUME_FOLDER"
|
||||
if [[ -z $MEDIA_FOLDER ]] ; then
|
||||
echo "Media folder: Managed by docker"
|
||||
else
|
||||
echo "Media folder: $MEDIA_FOLDER"
|
||||
fi
|
||||
if [[ -z $DATA_FOLDER ]] ; then
|
||||
echo "Data folder: Managed by docker"
|
||||
else
|
||||
echo "Data folder: $DATA_FOLDER"
|
||||
fi
|
||||
if [[ "$DATABASE_BACKEND" == "postgres" ]] ; then
|
||||
if [[ -z $POSTGRES_FOLDER ]] ; then
|
||||
echo "Database (postgres) folder: Managed by docker"
|
||||
else
|
||||
echo "Database (postgres) folder: $POSTGRES_FOLDER"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
echo "Port: $PORT"
|
||||
echo "Database: $DATABASE_BACKEND"
|
||||
echo "Tika enabled: $TIKA_ENABLED"
|
||||
echo "OCR language: $OCR_LANGUAGE"
|
||||
echo "User id: $USERMAP_UID"
|
||||
echo "Group id: $USERMAP_GID"
|
||||
echo ""
|
||||
echo "Paperless username: $USERNAME"
|
||||
echo "Paperless email: $EMAIL"
|
||||
|
||||
echo ""
|
||||
read -p "Press any key to install."
|
||||
|
||||
echo ""
|
||||
echo "Installing paperless..."
|
||||
echo ""
|
||||
|
||||
mkdir -p "$TARGET_FOLDER"
|
||||
|
||||
cd "$TARGET_FOLDER"
|
||||
|
||||
DOCKER_COMPOSE_VERSION=$DATABASE_BACKEND
|
||||
|
||||
if [[ $TIKA_ENABLED == "yes" ]] ; then
|
||||
DOCKER_COMPOSE_VERSION="$DOCKER_COMPOSE_VERSION-tika"
|
||||
fi
|
||||
|
||||
wget "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/master/docker/compose/docker-compose.$DOCKER_COMPOSE_VERSION.yml" -O docker-compose.yml
|
||||
wget "https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/master/docker/compose/.env" -O .env
|
||||
|
||||
SECRET_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1)
|
||||
|
||||
DEFAULT_LANGUAGES="deu eng fra ita spa"
|
||||
|
||||
{
|
||||
if [[ ! $USERMAP_UID == "1000" ]] ; then
|
||||
echo "USERMAP_UID=$USERMAP_UID"
|
||||
fi
|
||||
if [[ ! $USERMAP_GID == "1000" ]] ; then
|
||||
echo "USERMAP_GID=$USERMAP_GID"
|
||||
fi
|
||||
echo "PAPERLESS_TIME_ZONE=$TIME_ZONE"
|
||||
echo "PAPERLESS_OCR_LANGUAGE=$OCR_LANGUAGE"
|
||||
echo "PAPERLESS_SECRET_KEY=$SECRET_KEY"
|
||||
if [[ ! " ${DEFAULT_LANGUAGES[@]} " =~ " ${OCR_LANGUAGE} " ]] ; then
|
||||
echo "PAPERLESS_OCR_LANGUAGES=$OCR_LANGUAGE"
|
||||
fi
|
||||
} > docker-compose.env
|
||||
|
||||
sed -i "s/- 8000:8000/- $PORT:8000/g" docker-compose.yml
|
||||
|
||||
sed -i "s#- \./consume:/usr/src/paperless/consume#- $CONSUME_FOLDER:/usr/src/paperless/consume#g" docker-compose.yml
|
||||
|
||||
if [[ -n $MEDIA_FOLDER ]] ; then
|
||||
sed -i "s#- media:/usr/src/paperless/media#- $MEDIA_FOLDER:/usr/src/paperless/media#g" docker-compose.yml
|
||||
fi
|
||||
|
||||
if [[ -n $DATA_FOLDER ]] ; then
|
||||
sed -i "s#- data:/usr/src/paperless/data#- $DATA_FOLDER:/usr/src/paperless/data#g" docker-compose.yml
|
||||
fi
|
||||
|
||||
if [[ -n $POSTGRES_FOLDER ]] ; then
|
||||
sed -i "s#- pgdata:/var/lib/postgresql/data#- $POSTGRES_FOLDER:/var/lib/postgresql/data#g" docker-compose.yml
|
||||
fi
|
||||
|
||||
docker-compose pull
|
||||
|
||||
docker-compose run --rm -e DJANGO_SUPERUSER_PASSWORD="$PASSWORD" webserver createsuperuser --noinput --username "$USERNAME" --email "$EMAIL"
|
||||
|
||||
docker-compose up -d
|
@@ -1,5 +1,5 @@
|
||||
# Have a look at the docs for documentation.
|
||||
# https://paperless-ng.readthedocs.io/en/latest/configuration.html
|
||||
# https://paperless-ngx.readthedocs.io/en/latest/configuration.html
|
||||
|
||||
# Debug. Only enable this for development.
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
#PAPERLESS_DBNAME=paperless
|
||||
#PAPERLESS_DBUSER=paperless
|
||||
#PAPERLESS_DBPASS=paperless
|
||||
#PAPERLESS_DBSSLMODE=prefer
|
||||
|
||||
# Paths and folders
|
||||
|
||||
#PAPERLESS_CONSUMPTION_DIR=../consume
|
||||
#PAPERLESS_DATA_DIR=../data
|
||||
#PAPERLESS_TRASH_DIR=
|
||||
#PAPERLESS_MEDIA_ROOT=../media
|
||||
#PAPERLESS_STATICDIR=../static
|
||||
#PAPERLESS_FILENAME_FORMAT=
|
||||
@@ -26,7 +28,7 @@
|
||||
|
||||
#PAPERLESS_SECRET_KEY=change-me
|
||||
#PAPERLESS_ALLOWED_HOSTS=example.com,www.example.com
|
||||
#PAPERLESS_CORS_ALLOWED_HOSTS=localhost:8080,example.com,localhost:8000
|
||||
#PAPERLESS_CORS_ALLOWED_HOSTS=http://example.com,http://localhost:8000
|
||||
#PAPERLESS_FORCE_SCRIPT_NAME=
|
||||
#PAPERLESS_STATIC_URL=/static/
|
||||
#PAPERLESS_AUTO_LOGIN_USERNAME=
|
||||
@@ -40,6 +42,10 @@
|
||||
#PAPERLESS_OCR_OUTPUT_TYPE=pdfa
|
||||
#PAPERLESS_OCR_PAGES=1
|
||||
#PAPERLESS_OCR_IMAGE_DPI=300
|
||||
#PAPERLESS_OCR_CLEAN=clean
|
||||
#PAPERLESS_OCR_DESKEW=true
|
||||
#PAPERLESS_OCR_ROTATE_PAGES=true
|
||||
#PAPERLESS_OCR_ROTATE_PAGES_THRESHOLD=12.0
|
||||
#PAPERLESS_OCR_USER_ARGS={}
|
||||
#PAPERLESS_CONVERT_MEMORY_LIMIT=0
|
||||
#PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless
|
||||
@@ -52,8 +58,10 @@
|
||||
#PAPERLESS_CONSUMER_POLLING=10
|
||||
#PAPERLESS_CONSUMER_DELETE_DUPLICATES=false
|
||||
#PAPERLESS_CONSUMER_RECURSIVE=false
|
||||
#PAPERLESS_CONSUMER_IGNORE_PATTERNS=[".DS_STORE/*", "._*", ".stfolder/*"]
|
||||
#PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS=false
|
||||
#PAPERLESS_OPTIMIZE_THUMBNAILS=true
|
||||
#PAPERLESS_PRE_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
#PAPERLESS_POST_CONSUME_SCRIPT=/path/to/an/arbitrary/script.sh
|
||||
#PAPERLESS_FILENAME_DATE_ORDER=YMD
|
||||
#PAPERLESS_FILENAME_PARSE_TRANSFORMS=[]
|
||||
|
109
requirements.txt
Normal file
@@ -0,0 +1,109 @@
|
||||
#
|
||||
# These requirements were autogenerated by pipenv
|
||||
# To regenerate from the project's Pipfile, run:
|
||||
#
|
||||
# pipenv lock --requirements
|
||||
#
|
||||
|
||||
-i https://pypi.python.org/simple
|
||||
--extra-index-url https://www.piwheels.org/simple
|
||||
aioredis==1.3.1
|
||||
arrow==1.2.2; python_version >= '3.6'
|
||||
asgiref==3.5.0; python_version >= '3.7'
|
||||
async-timeout==4.0.2; python_version >= '3.6'
|
||||
attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
autobahn==22.2.2; python_version >= '3.7'
|
||||
automat==20.2.0
|
||||
backports.zoneinfo==0.2.1
|
||||
blessed==1.19.1; python_version >= '2.7'
|
||||
certifi==2021.10.8
|
||||
cffi==1.15.0
|
||||
channels-redis==3.3.1
|
||||
channels==3.0.4
|
||||
chardet==4.0.0; python_version >= '3.1'
|
||||
charset-normalizer==2.0.12; python_version >= '3'
|
||||
click==8.0.4; python_version >= '3.6'
|
||||
coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
concurrent-log-handler==0.9.20
|
||||
constantly==15.1.0
|
||||
cryptography==36.0.1
|
||||
daphne==3.0.2; python_version >= '3.6'
|
||||
dateparser==1.1.0
|
||||
django-cors-headers==3.11.0
|
||||
django-extensions==3.1.5
|
||||
django-filter==21.1
|
||||
django-picklefield==3.0.1; python_version >= '3'
|
||||
django-q==1.3.9
|
||||
django==3.2.12
|
||||
djangorestframework==3.13.1
|
||||
filelock==3.6.0
|
||||
fuzzywuzzy[speedup]==0.18.0
|
||||
gunicorn==20.1.0
|
||||
h11==0.13.0; python_version >= '3.6'
|
||||
hiredis==2.0.0; python_version >= '3.6'
|
||||
httptools==0.3.0
|
||||
humanfriendly==10.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
hyperlink==21.0.0
|
||||
idna==3.3; python_version >= '3.5'
|
||||
imap-tools==0.51.1
|
||||
img2pdf==0.4.3
|
||||
importlib-resources==5.4.0; python_version < '3.9'
|
||||
incremental==21.3.0
|
||||
inotify-simple==1.3.5; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
inotifyrecursive==0.3.5
|
||||
joblib==1.1.0; python_version >= '3.6'
|
||||
langdetect==1.0.9
|
||||
lxml==4.8.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
msgpack==1.0.3
|
||||
numpy==1.22.2
|
||||
ocrmypdf==13.4.0
|
||||
packaging==21.3; python_version >= '3.6'
|
||||
pathvalidate==2.5.0
|
||||
pdfminer.six==20211012
|
||||
pikepdf==5.0.1
|
||||
pillow==9.0.1
|
||||
pluggy==1.0.0; python_version >= '3.6'
|
||||
portalocker==2.4.0; python_version >= '3'
|
||||
psycopg2-binary==2.9.3
|
||||
pyasn1-modules==0.2.8
|
||||
pyasn1==0.4.8
|
||||
pycparser==2.21; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
pyopenssl==22.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
pyparsing==3.0.7; python_version >= '3.6'
|
||||
python-dateutil==2.8.2
|
||||
python-dotenv==0.19.2
|
||||
python-gnupg==0.4.8
|
||||
python-levenshtein==0.12.2
|
||||
python-magic==0.4.25
|
||||
pytz-deprecation-shim==0.1.0.post0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
|
||||
pytz==2021.3
|
||||
pyyaml==6.0
|
||||
redis==3.5.3
|
||||
regex==2022.1.18
|
||||
reportlab==3.6.7; python_version >= '3.6' and python_version < '4'
|
||||
requests==2.27.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
|
||||
scikit-learn==0.24.0
|
||||
scipy==1.8.0; python_version < '3.11' and python_version >= '3.8'
|
||||
service-identity==21.1.0
|
||||
setuptools==60.9.3; python_version >= '3.7'
|
||||
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
sqlparse==0.4.2; python_version >= '3.5'
|
||||
threadpoolctl==3.1.0; python_version >= '3.6'
|
||||
tika==1.24
|
||||
tqdm==4.62.3
|
||||
twisted[tls]==22.1.0; python_full_version >= '3.6.7'
|
||||
txaio==22.2.1; python_version >= '3.6'
|
||||
typing-extensions==4.1.1; python_version >= '3.6'
|
||||
tzdata==2021.5; python_version >= '3.6'
|
||||
tzlocal==4.1; python_version >= '3.6'
|
||||
urllib3==1.26.8; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'
|
||||
uvicorn[standard]==0.17.5
|
||||
uvloop==0.16.0
|
||||
watchdog==2.1.6
|
||||
watchgod==0.7
|
||||
wcwidth==0.2.5
|
||||
websockets==10.2
|
||||
whitenoise==6.0.0
|
||||
whoosh==2.7.4
|
||||
zipp==3.7.0; python_version < '3.10'
|
||||
zope.interface==5.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
16
resources/logo.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
9w
|
||||
{@@N
|
||||
Q@@@@H
|
||||
G@@@@@@@\
|
||||
SilN@@@@@@@
|
||||
*Q *@@@@@@@@S /= = = = = = = = = = = = = = = = = =\
|
||||
*@ B@@@@@@@@N || ||
|
||||
N R$ A@@@@@@@@@@ || PAPERLESS-NGX ||
|
||||
x@@ $U B@@@@@@@@@R || ||
|
||||
N@@N^ @ N@@@@@@@@@* \= = = = = = = = = = = = = = = = = =/
|
||||
|@@@u @ E@@@@@@@@l
|
||||
Q@@@ \ Px@@@@@@P
|
||||
1@@S` @@@o'
|
||||
z$ ;
|
||||
v
|
||||
/
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.5 KiB |
@@ -1,125 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Release checklist
|
||||
# - wait for travis build.
|
||||
# adjust src/paperless/version.py
|
||||
# changelog in the documentation
|
||||
# adjust versions in docker/hub/*
|
||||
# adjust version in src-ui/src/environments/prod
|
||||
# If docker-compose was modified: all compose files are the same.
|
||||
|
||||
# Steps:
|
||||
# run release script "dev", push
|
||||
# if it works: new tag, merge into master
|
||||
# on master: make release "lastest", push
|
||||
# on master: make release "version-tag", push
|
||||
# publish release files
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if [ -z "$VERSION" ]
|
||||
then
|
||||
echo "Need a version string."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# source root directory of paperless
|
||||
PAPERLESS_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# output directory
|
||||
PAPERLESS_DIST="$PAPERLESS_ROOT/dist"
|
||||
PAPERLESS_DIST_APP="$PAPERLESS_DIST/paperless-ng"
|
||||
PAPERLESS_DIST_DOCKERFILES="$PAPERLESS_DIST/paperless-ng-dockerfiles"
|
||||
|
||||
if [ -d "$PAPERLESS_DIST" ]
|
||||
then
|
||||
echo "Removing $PAPERLESS_DIST"
|
||||
rm "$PAPERLESS_DIST" -r
|
||||
fi
|
||||
|
||||
mkdir "$PAPERLESS_DIST"
|
||||
mkdir "$PAPERLESS_DIST_APP"
|
||||
mkdir "$PAPERLESS_DIST_APP/docker"
|
||||
mkdir "$PAPERLESS_DIST_APP/scripts"
|
||||
mkdir "$PAPERLESS_DIST_DOCKERFILES"
|
||||
|
||||
# setup dependencies.
|
||||
|
||||
cd "$PAPERLESS_ROOT"
|
||||
|
||||
pipenv clean
|
||||
pipenv install --dev
|
||||
pipenv lock --keep-outdated -r > "$PAPERLESS_DIST_APP/requirements.txt"
|
||||
|
||||
# test if the application works.
|
||||
|
||||
cd "$PAPERLESS_ROOT/src"
|
||||
#pipenv run pytest --cov
|
||||
#pipenv run pycodestyle
|
||||
|
||||
# make the documentation.
|
||||
|
||||
cd "$PAPERLESS_ROOT/docs"
|
||||
make clean html
|
||||
|
||||
# copy stuff into place
|
||||
|
||||
# the application itself
|
||||
|
||||
cp "$PAPERLESS_ROOT/.env" \
|
||||
"$PAPERLESS_ROOT/.dockerignore" \
|
||||
"$PAPERLESS_ROOT/CONTRIBUTING.md" \
|
||||
"$PAPERLESS_ROOT/LICENSE" \
|
||||
"$PAPERLESS_ROOT/Pipfile" \
|
||||
"$PAPERLESS_ROOT/Pipfile.lock" \
|
||||
"$PAPERLESS_ROOT/README.md" "$PAPERLESS_DIST_APP"
|
||||
|
||||
cp "$PAPERLESS_ROOT/paperless.conf.example" "$PAPERLESS_DIST_APP/paperless.conf"
|
||||
|
||||
# copy python source, templates and static files.
|
||||
cd "$PAPERLESS_ROOT"
|
||||
find src -name '*.po' -o -wholename '*/templates/*' -o -wholename '*/static/*' -o -name '*.py' | cpio -pdm "$PAPERLESS_DIST_APP"
|
||||
|
||||
# build the front end.
|
||||
|
||||
cd "$PAPERLESS_ROOT/src-ui"
|
||||
ng build --prod --output-hashing none --sourceMap=false --output-path "$PAPERLESS_DIST_APP/src/documents/static/frontend"
|
||||
|
||||
# documentation
|
||||
cp "$PAPERLESS_ROOT/docs/_build/html/" "$PAPERLESS_DIST_APP/docs" -r
|
||||
|
||||
# docker files for building the image yourself
|
||||
cp "$PAPERLESS_ROOT/docker/local/"* "$PAPERLESS_DIST_APP"
|
||||
cp "$PAPERLESS_ROOT/docker/docker-compose.env" "$PAPERLESS_DIST_APP"
|
||||
|
||||
# docker files for pulling from docker hub
|
||||
cp "$PAPERLESS_ROOT/docker/hub/"* "$PAPERLESS_DIST_DOCKERFILES"
|
||||
cp "$PAPERLESS_ROOT/.env" "$PAPERLESS_DIST_DOCKERFILES"
|
||||
cp "$PAPERLESS_ROOT/docker/docker-compose.env" "$PAPERLESS_DIST_DOCKERFILES"
|
||||
|
||||
# auxiliary files required for the docker image
|
||||
cp "$PAPERLESS_ROOT/docker/docker-entrypoint.sh" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/gunicorn.conf.py" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/imagemagick-policy.xml" "$PAPERLESS_DIST_APP/docker/"
|
||||
cp "$PAPERLESS_ROOT/docker/supervisord.conf" "$PAPERLESS_DIST_APP/docker/"
|
||||
|
||||
# auxiliary files for bare metal installs
|
||||
cp "$PAPERLESS_ROOT/scripts/paperless-webserver.service" "$PAPERLESS_DIST_APP/scripts/"
|
||||
cp "$PAPERLESS_ROOT/scripts/paperless-consumer.service" "$PAPERLESS_DIST_APP/scripts/"
|
||||
cp "$PAPERLESS_ROOT/scripts/paperless-scheduler.service" "$PAPERLESS_DIST_APP/scripts/"
|
||||
|
||||
# try to make the docker build.
|
||||
|
||||
cd "$PAPERLESS_DIST_APP"
|
||||
|
||||
docker build . -t "jonaswinkler/paperless-ng:$VERSION"
|
||||
|
||||
# works. package the app!
|
||||
|
||||
cd "$PAPERLESS_DIST"
|
||||
|
||||
tar -cJf "paperless-ng-$VERSION.tar.xz" paperless-ng/
|
||||
tar -cJf "paperless-ng-$VERSION-dockerfiles.tar.xz" paperless-ng-dockerfiles/
|
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Paperless consumer
|
||||
Description=Paperless scheduler
|
||||
Requires=redis.service
|
||||
|
||||
[Service]
|
||||
|
@@ -3,12 +3,13 @@ Description=Paperless webserver
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
Requires=redis.service
|
||||
#Requires=paperless-webserver.socket
|
||||
|
||||
[Service]
|
||||
User=paperless
|
||||
Group=paperless
|
||||
WorkingDirectory=/opt/paperless/src
|
||||
ExecStart=/opt/paperless/.local/bin/gunicorn paperless.wsgi -w 2 -b 0.0.0.0:8000
|
||||
ExecStart=/opt/paperless/.local/bin/gunicorn -c /opt/paperless/gunicorn.conf.py paperless.asgi:application
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
9
scripts/paperless-webserver.socket
Normal file
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Paperless Webserver Socket
|
||||
|
||||
[Socket]
|
||||
ListenStream=80
|
||||
NoDelay=true
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
@@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
VERSION=$1
|
||||
|
||||
if [ -z "$VERSION" ]
|
||||
then
|
||||
echo "Need a version string."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# source root directory of paperless
|
||||
PAPERLESS_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# output directory
|
||||
PAPERLESS_DIST="$PAPERLESS_ROOT/dist"
|
||||
PAPERLESS_DIST_APP="$PAPERLESS_DIST/paperless-ng"
|
||||
|
||||
cd "$PAPERLESS_DIST_APP"
|
||||
|
||||
docker push "jonaswinkler/paperless-ng:$VERSION"
|
@@ -1,4 +1,4 @@
|
||||
docker run -p 5432:5432 -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13
|
||||
docker run -p 5432:5432 -e POSTGRES_PASSWORD=password -v paperless_pgdata:/var/lib/postgresql/data -d postgres:13
|
||||
docker run -d -p 6379:6379 redis:latest
|
||||
docker run -p 3000:3000 -d thecodingmachine/gotenberg
|
||||
docker run -p 3000:3000 -d gotenberg/gotenberg:7
|
||||
docker run -p 9998:9998 -d apache/tika
|
||||
|
1
src-ui/.gitignore
vendored
@@ -32,6 +32,7 @@ speed-measure-plugin*.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.angular/cache
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
|
@@ -16,10 +16,22 @@
|
||||
"i18n": {
|
||||
"sourceLocale": "en-US",
|
||||
"locales": {
|
||||
"de": "src/locale/messages.de.xlf",
|
||||
"cs-CZ": "src/locale/messages.cs_CZ.xlf",
|
||||
"da-DK": "src/locale/messages.da_DK.xlf",
|
||||
"de-DE": "src/locale/messages.de_DE.xlf",
|
||||
"en-GB": "src/locale/messages.en_GB.xlf",
|
||||
"es-ES": "src/locale/messages.es_ES.xlf",
|
||||
"fr-FR": "src/locale/messages.fr_FR.xlf",
|
||||
"it-IT": "src/locale/messages.it_IT.xlf",
|
||||
"lb-LU": "src/locale/messages.lb_LU.xlf",
|
||||
"nl-NL": "src/locale/messages.nl_NL.xlf",
|
||||
"fr": "src/locale/messages.fr.xlf"
|
||||
}
|
||||
"pl-PL": "src/locale/messages.pl_PL.xlf",
|
||||
"pt-BR": "src/locale/messages.pt_BR.xlf",
|
||||
"pt-PT": "src/locale/messages.pt_PT.xlf",
|
||||
"ro-RO": "src/locale/messages.ro_RO.xlf",
|
||||
"ru-RU": "src/locale/messages.ru_RU.xlf",
|
||||
"sv-SE": "src/locale/messages.sv_SE.xlf"
|
||||
}
|
||||
},
|
||||
"architect": {
|
||||
"build": {
|
||||
@@ -32,9 +44,9 @@
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"localize": true,
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/apple-touch-icon.png",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest", {
|
||||
"glob": "pdf.worker.min.js",
|
||||
@@ -48,7 +60,13 @@
|
||||
"scripts": [],
|
||||
"allowedCommonJsDependencies": [
|
||||
"ng2-pdf-viewer"
|
||||
]
|
||||
],
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"buildOptimizer": false,
|
||||
"sourceMap": true,
|
||||
"optimization": false,
|
||||
"namedChunks": true
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
@@ -58,10 +76,10 @@
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"outputPath": "../src/documents/static/frontend/",
|
||||
"optimization": true,
|
||||
"outputHashing": "none",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
@@ -82,7 +100,8 @@
|
||||
"en-US": {
|
||||
"localize": ["en-US"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": ""
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
@@ -110,6 +129,7 @@
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/apple-touch-icon.png",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
@@ -119,19 +139,6 @@
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
|
@@ -33,4 +33,4 @@ exports.config = {
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
3665
src-ui/messages.xlf
26276
src-ui/package-lock.json
generated
@@ -11,46 +11,49 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~10.1.5",
|
||||
"@angular/common": "~10.1.5",
|
||||
"@angular/compiler": "~10.1.5",
|
||||
"@angular/core": "~10.1.5",
|
||||
"@angular/forms": "~10.1.5",
|
||||
"@angular/localize": "~10.1.5",
|
||||
"@angular/platform-browser": "~10.1.5",
|
||||
"@angular/platform-browser-dynamic": "~10.1.5",
|
||||
"@angular/router": "~10.1.5",
|
||||
"@ng-bootstrap/ng-bootstrap": "^8.0.0",
|
||||
"@ng-select/ng-select": "^5.0.9",
|
||||
"bootstrap": "^4.5.0",
|
||||
"ng-bootstrap": "^1.6.3",
|
||||
"ng2-pdf-viewer": "^6.3.2",
|
||||
"ngx-cookie-service": "^10.1.1",
|
||||
"ngx-file-drop": "^10.0.0",
|
||||
"ngx-infinite-scroll": "^9.1.0",
|
||||
"rxjs": "~6.6.0",
|
||||
"tslib": "^2.0.0",
|
||||
"@angular/animations": "~13.2.4",
|
||||
"@angular/common": "~13.2.4",
|
||||
"@angular/compiler": "~13.2.4",
|
||||
"@angular/core": "~13.2.4",
|
||||
"@angular/forms": "~13.2.4",
|
||||
"@angular/localize": "~13.2.4",
|
||||
"@angular/platform-browser": "~13.2.4",
|
||||
"@angular/platform-browser-dynamic": "~13.2.4",
|
||||
"@angular/router": "~13.2.4",
|
||||
"@ng-bootstrap/ng-bootstrap": "^12.0.0",
|
||||
"@ng-select/ng-select": "^8.1.1",
|
||||
"@ngneat/dirty-check-forms": "^1.1.0",
|
||||
"@popperjs/core": "^2.11.2",
|
||||
"bootstrap": "^5.1.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"ng2-pdf-viewer": "^8.0.1",
|
||||
"ngx-color": "^7.3.3",
|
||||
"ngx-cookie-service": "^13.1.2",
|
||||
"ngx-file-drop": "^13.0.0",
|
||||
"ngx-infinite-scroll": "^10.0.1",
|
||||
"rxjs": "~6.6.7",
|
||||
"tslib": "^2.3.1",
|
||||
"uuid": "^8.3.1",
|
||||
"zone.js": "~0.10.2"
|
||||
"zone.js": "~0.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.1002.0",
|
||||
"@angular/cli": "~10.1.5",
|
||||
"@angular/compiler-cli": "~10.1.5",
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/node": "^12.11.1",
|
||||
"codelyzer": "^6.0.0",
|
||||
"jasmine-core": "~3.6.0",
|
||||
"jasmine-spec-reporter": "~5.0.0",
|
||||
"karma": "~5.0.0",
|
||||
"@angular-devkit/build-angular": "~13.2.5",
|
||||
"@angular/cli": "~13.2.5",
|
||||
"@angular/compiler-cli": "~13.2.4",
|
||||
"@types/jasmine": "~3.10.3",
|
||||
"@types/jasminewd2": "~2.0.10",
|
||||
"@types/node": "^17.0.21",
|
||||
"codelyzer": "^6.0.2",
|
||||
"jasmine-core": "~4.0.1",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"karma": "~6.3.16",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "~3.0.2",
|
||||
"karma-jasmine": "~4.0.0",
|
||||
"karma-jasmine-html-reporter": "^1.5.0",
|
||||
"karma-coverage-istanbul-reporter": "~3.0.3",
|
||||
"karma-jasmine": "~4.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.7.0",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~6.1.0",
|
||||
"typescript": "~4.0.2"
|
||||
"ts-node": "~10.5.0",
|
||||
"tslint": "~6.1.3",
|
||||
"typescript": "~4.5.5"
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,8 @@ 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";
|
||||
import { DirtyFormGuard } from './guards/dirty-form.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{path: '', redirectTo: 'dashboard', pathMatch: 'full'},
|
||||
@@ -18,22 +19,21 @@ 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: 'settings', component: SettingsComponent, canDeactivate: [DirtyFormGuard] },
|
||||
]},
|
||||
|
||||
{path: '404', component: NotFoundComponent},
|
||||
{path: '**', redirectTo: '/404', pathMatch: 'full'}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
|
@@ -1,3 +1,3 @@
|
||||
<app-toasts></app-toasts>
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
<router-outlet></router-outlet>
|
||||
|
@@ -1,17 +1,70 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SettingsService } from './services/settings.service';
|
||||
import { SettingsService, SETTINGS_KEYS } from './services/settings.service';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ConsumerStatusService } from './services/consumer-status.service';
|
||||
import { ToastService } from './services/toast.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor (private settings: SettingsService) {
|
||||
newDocumentSubscription: Subscription;
|
||||
successSubscription: Subscription;
|
||||
failedSubscription: Subscription;
|
||||
|
||||
constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) {
|
||||
let anyWindow = (window as any)
|
||||
anyWindow.pdfWorkerSrc = '/assets/js/pdf.worker.min.js';
|
||||
anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js';
|
||||
this.settings.updateDarkModeSettings()
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.consumerStatusService.disconnect()
|
||||
if (this.successSubscription) {
|
||||
this.successSubscription.unsubscribe()
|
||||
}
|
||||
if (this.failedSubscription) {
|
||||
this.failedSubscription.unsubscribe()
|
||||
}
|
||||
if (this.newDocumentSubscription) {
|
||||
this.newDocumentSubscription.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
private showNotification(key) {
|
||||
if (this.router.url == '/dashboard' && this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD)) {
|
||||
return false
|
||||
}
|
||||
return this.settings.get(key)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.consumerStatusService.connect()
|
||||
|
||||
|
||||
this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)) {
|
||||
this.toastService.show({title: $localize`Document added`, delay: 10000, content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => {
|
||||
this.router.navigate(['documents', status.documentId])
|
||||
}})
|
||||
}
|
||||
})
|
||||
|
||||
this.failedSubscription = this.consumerStatusService.onDocumentConsumptionFailed().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED)) {
|
||||
this.toastService.showError($localize`Could not add ${status.filename}\: ${status.message}`)
|
||||
}
|
||||
})
|
||||
|
||||
this.newDocumentSubscription = this.consumerStatusService.onDocumentDetected().subscribe(status => {
|
||||
if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT)) {
|
||||
this.toastService.show({title: $localize`New document detected`, delay: 5000, content: $localize`Document ${status.filename} is being processed by paperless.`})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgbDateAdapter, NgbDateParserFormatter, NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { DocumentListComponent } from './components/document-list/document-list.component';
|
||||
import { DocumentDetailComponent } from './components/document-detail/document-detail.component';
|
||||
@@ -13,7 +13,7 @@ import { DocumentTypeListComponent } from './components/manage/document-type-lis
|
||||
import { LogsComponent } from './components/manage/logs/logs.component';
|
||||
import { SettingsComponent } from './components/manage/settings/settings.component';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { DatePipe, registerLocaleData } from '@angular/common';
|
||||
import { NotFoundComponent } from './components/not-found/not-found.component';
|
||||
import { CorrespondentListComponent } from './components/manage/correspondent-list/correspondent-list.component';
|
||||
import { ConfirmDialogComponent } from './components/common/confirm-dialog/confirm-dialog.component';
|
||||
@@ -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';
|
||||
@@ -39,7 +37,6 @@ import { SelectComponent } from './components/common/input/select/select.compone
|
||||
import { CheckComponent } from './components/common/input/check/check.component';
|
||||
import { SaveViewConfigDialogComponent } from './components/document-list/save-view-config-dialog/save-view-config-dialog.component';
|
||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||
import { DateTimeComponent } from './components/common/input/date-time/date-time.component';
|
||||
import { TagsComponent } from './components/common/input/tags/tags.component';
|
||||
import { SortableDirective } from './directives/sortable.directive';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
@@ -58,6 +55,47 @@ import { MetadataCollapseComponent } from './components/document-detail/metadata
|
||||
import { SelectDialogComponent } from './components/common/select-dialog/select-dialog.component';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { NumberComponent } from './components/common/input/number/number.component';
|
||||
import { SafePipe } from './pipes/safe.pipe';
|
||||
import { CustomDatePipe } from './pipes/custom-date.pipe';
|
||||
import { DateComponent } from './components/common/input/date/date.component';
|
||||
import { ISODateTimeAdapter } from './utils/ngb-iso-date-time-adapter';
|
||||
import { LocalizedDateParserFormatter } from './utils/ngb-date-parser-formatter';
|
||||
import { ApiVersionInterceptor } from './interceptors/api-version.interceptor';
|
||||
import { ColorSliderModule } from 'ngx-color/slider';
|
||||
import { ColorComponent } from './components/common/input/color/color.component';
|
||||
import { DocumentAsnComponent } from './components/document-asn/document-asn.component';
|
||||
|
||||
import localeCs from '@angular/common/locales/cs';
|
||||
import localeDa from '@angular/common/locales/da';
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeEnGb from '@angular/common/locales/en-GB';
|
||||
import localeEs from '@angular/common/locales/es';
|
||||
import localeFr from '@angular/common/locales/fr';
|
||||
import localeIt from '@angular/common/locales/it';
|
||||
import localeLb from '@angular/common/locales/lb';
|
||||
import localeNl from '@angular/common/locales/nl';
|
||||
import localePl from '@angular/common/locales/pl';
|
||||
import localePt from '@angular/common/locales/pt';
|
||||
import localeSv from '@angular/common/locales/sv';
|
||||
import localeRo from '@angular/common/locales/ro';
|
||||
import localeRu from '@angular/common/locales/ru';
|
||||
|
||||
|
||||
registerLocaleData(localeCs)
|
||||
registerLocaleData(localeDa)
|
||||
registerLocaleData(localeDe)
|
||||
registerLocaleData(localeEnGb)
|
||||
registerLocaleData(localeEs)
|
||||
registerLocaleData(localeFr)
|
||||
registerLocaleData(localeIt)
|
||||
registerLocaleData(localeLb)
|
||||
registerLocaleData(localeNl)
|
||||
registerLocaleData(localePl)
|
||||
registerLocaleData(localePt, "pt-BR")
|
||||
registerLocaleData(localePt, "pt-PT")
|
||||
registerLocaleData(localeRo)
|
||||
registerLocaleData(localeRu)
|
||||
registerLocaleData(localeSv)
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -76,8 +114,6 @@ import { NumberComponent } from './components/common/input/number/number.compone
|
||||
TagEditDialogComponent,
|
||||
DocumentTypeEditDialogComponent,
|
||||
TagComponent,
|
||||
SearchComponent,
|
||||
ResultHighlightComponent,
|
||||
PageHeaderComponent,
|
||||
AppFrameComponent,
|
||||
ToastsComponent,
|
||||
@@ -92,7 +128,6 @@ import { NumberComponent } from './components/common/input/number/number.compone
|
||||
SelectComponent,
|
||||
CheckComponent,
|
||||
SaveViewConfigDialogComponent,
|
||||
DateTimeComponent,
|
||||
TagsComponent,
|
||||
SortableDirective,
|
||||
SavedViewWidgetComponent,
|
||||
@@ -106,7 +141,12 @@ import { NumberComponent } from './components/common/input/number/number.compone
|
||||
DocumentTitlePipe,
|
||||
MetadataCollapseComponent,
|
||||
SelectDialogComponent,
|
||||
NumberComponent
|
||||
NumberComponent,
|
||||
SafePipe,
|
||||
CustomDatePipe,
|
||||
DateComponent,
|
||||
ColorComponent,
|
||||
DocumentAsnComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@@ -118,7 +158,8 @@ import { NumberComponent } from './components/common/input/number/number.compone
|
||||
NgxFileDropModule,
|
||||
InfiniteScrollModule,
|
||||
PdfViewerModule,
|
||||
NgSelectModule
|
||||
NgSelectModule,
|
||||
ColorSliderModule
|
||||
],
|
||||
providers: [
|
||||
DatePipe,
|
||||
@@ -126,9 +167,15 @@ import { NumberComponent } from './components/common/input/number/number.compone
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: CsrfInterceptor,
|
||||
multi: true
|
||||
},{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: ApiVersionInterceptor,
|
||||
multi: true
|
||||
},
|
||||
FilterPipe,
|
||||
DocumentTitlePipe
|
||||
DocumentTitlePipe,
|
||||
{provide: NgbDateAdapter, useClass: ISODateTimeAdapter},
|
||||
{provide: NgbDateParserFormatter, useClass: LocalizedDateParserFormatter}
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
@@ -4,43 +4,43 @@
|
||||
(click)="isMenuCollapsed = !isMenuCollapsed">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand col-auto col-md-3 col-lg-2 mr-0 px-3 py-3 order-sm-0" routerLink="/dashboard">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1rem" class="mr-2" fill="currentColor">
|
||||
<a class="navbar-brand col-auto col-md-3 col-lg-2 me-0 px-3 py-3 order-sm-0" routerLink="/dashboard">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 198.43 238.91" width="1em" class="me-2" fill="currentColor">
|
||||
<path d="M194.7,0C164.22,70.94,17.64,79.74,64.55,194.06c.58,1.47-10.85,17-18.47,29.9-1.76-6.45-3.81-13.48-3.52-14.07,38.11-45.14-27.26-70.65-30.78-107.58C-4.64,131.62-10.5,182.92,39,212.53c.3,0,2.64,11.14,3.81,16.71a58.55,58.55,0,0,0-2.93,6.45c-1.17,2.93,7.62,2.64,7.62,3.22.88-.29,21.7-36.93,22.28-37.23C187.67,174.72,208.48,68.6,194.7,0ZM134.61,74.75C79.5,124,70.12,160.64,71.88,178.53,53.41,134.85,107.64,86.77,134.61,74.75ZM28.2,145.11c10.55,9.67,28.14,39.28,13.19,56.57C44.91,193.77,46.08,175.89,28.2,145.11Z" transform="translate(0 0)"/>
|
||||
</svg>
|
||||
<ng-container i18n="app title">Paperless-ng</ng-container>
|
||||
<ng-container i18n="app title">Paperless-ngx</ng-container>
|
||||
</a>
|
||||
<div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 pl-md-4 mr-sm-auto order-3 order-sm-1">
|
||||
<div class="search-form-container flex-grow-1 py-2 pb-3 pb-sm-2 px-3 ps-md-4 me-sm-auto order-3 order-sm-1">
|
||||
<form (ngSubmit)="search()" class="form-inline flex-grow-1">
|
||||
<input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search"
|
||||
[formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)" i18n-placeholder>
|
||||
<svg width="1em" height="1em">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#search"/>
|
||||
</svg>
|
||||
<input class="form-control form-control-sm" type="text" placeholder="Search documents" aria-label="Search"
|
||||
[formControl]="searchField" [ngbTypeahead]="searchAutoComplete" (selectItem)="itemSelected($event)" i18n-placeholder>
|
||||
</form>
|
||||
</div>
|
||||
<ul ngbNav class="order-sm-3">
|
||||
<li ngbDropdown class="nav-item dropdown">
|
||||
<button class="btn text-light" id="userDropdown" ngbDropdownToggle>
|
||||
<span *ngIf="displayName" class="navbar-text small mr-2 text-light d-none d-sm-inline">
|
||||
<span *ngIf="displayName" class="navbar-text small me-2 text-light d-none d-sm-inline">
|
||||
{{displayName}}
|
||||
</span>
|
||||
<svg width="1.3em" height="1.3em">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#person-circle"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div ngbDropdownMenu class="dropdown-menu-right shadow mr-2" aria-labelledby="userDropdown">
|
||||
<div ngbDropdownMenu class="dropdown-menu-end shadow me-2" aria-labelledby="userDropdown">
|
||||
<div *ngIf="displayName" class="d-sm-none">
|
||||
<p class="small mb-0 px-3" i18n>Logged in as {{displayName}}</p>
|
||||
<p class="small mb-0 px-3 text-muted" i18n>Logged in as {{displayName}}</p>
|
||||
<div class="dropdown-divider"></div>
|
||||
</div>
|
||||
<a ngbDropdownItem class="nav-link" routerLink="settings" (click)="closeMenu()">
|
||||
<svg class="sidebaricon mr-2" fill="currentColor">
|
||||
<svg class="sidebaricon me-2" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#gear"/>
|
||||
</svg><ng-container i18n>Settings</ng-container>
|
||||
</a>
|
||||
<a ngbDropdownItem class="nav-link" href="accounts/logout/">
|
||||
<svg class="sidebaricon mr-2" fill="currentColor">
|
||||
<svg class="sidebaricon me-2" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#door-open"/>
|
||||
</svg><ng-container i18n>Logout</ng-container>
|
||||
</a>
|
||||
@@ -52,12 +52,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse" [ngbCollapse]="isMenuCollapsed">
|
||||
|
||||
<div style="position: absolute; bottom: 0; left: 0;" class="text-muted p-1">
|
||||
{{versionString}}
|
||||
</div>
|
||||
|
||||
<div class="sidebar-sticky pt-3">
|
||||
<div class="sidebar-sticky pt-3 d-flex flex-column justify-space-around">
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLink="dashboard" routerLinkActive="active" (click)="closeMenu()">
|
||||
@@ -75,7 +70,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted" *ngIf='savedViewService.sidebarViews.length > 0'>
|
||||
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted" *ngIf='savedViewService.sidebarViews.length > 0'>
|
||||
<ng-container i18n>Saved views</ng-container>
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
@@ -88,7 +83,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted" *ngIf='openDocuments.length > 0'>
|
||||
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted" *ngIf='openDocuments.length > 0'>
|
||||
<ng-container i18n>Open documents</ng-container>
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
@@ -97,10 +92,15 @@
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-text"/>
|
||||
</svg> {{d.title | documentTitle}}
|
||||
<span class="close bg-light" (click)="closeDocument(d); $event.preventDefault()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item w-100" *ngIf="openDocuments.length > 1">
|
||||
<a class="nav-link text-truncate" [routerLink]="" (click)="closeAll()">
|
||||
<li class="nav-item w-100" *ngIf="openDocuments.length >= 1">
|
||||
<a class="nav-link text-truncate" [routerLink]="[]" (click)="closeAll()">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x"/>
|
||||
</svg> <ng-container i18n>Close all</ng-container>
|
||||
@@ -108,7 +108,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted">
|
||||
<ng-container i18n>Manage</ng-container>
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
@@ -156,29 +156,42 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
|
||||
<ng-container i18n>Misc</ng-container>
|
||||
<h6 class="sidebar-heading px-3 mt-auto pt-4 mb-1 text-muted">
|
||||
<ng-container i18n>Info</ng-container>
|
||||
</h6>
|
||||
<ul class="nav flex-column mb-2">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://paperless-ng.readthedocs.io/en/latest/">
|
||||
<a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://paperless-ngx.readthedocs.io/en/latest/">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#question-circle"/>
|
||||
</svg> <ng-container i18n>Documentation</ng-container>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" target="_blank" rel="noopener noreferrer" href="https://github.com/jonaswinkler/paperless-ng">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#link"/>
|
||||
</svg> <ng-container i18n>GitHub</ng-container>
|
||||
</a>
|
||||
<div class="d-flex w-100 flex-wrap">
|
||||
<a class="nav-link pe-0 pb-0" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="sidebaricon bi bi-github" viewBox="0 0 16 16">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||
</svg> <ng-container i18n>GitHub</ng-container>
|
||||
</a>
|
||||
<a class="nav-link-additional small text-muted ms-3" target="_blank" rel="noopener noreferrer" href="https://github.com/paperless-ngx/paperless-ngx/discussions/categories/feature-requests" title="Suggest an idea">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" fill="currentColor" class="bi bi-lightbulb pe-1" viewBox="0 0 16 16">
|
||||
<path d="M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13a.5.5 0 0 1 0 1 .5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1 0-1 .5.5 0 0 1 0-1 .5.5 0 0 1-.46-.302l-.761-1.77a1.964 1.964 0 0 0-.453-.618A5.984 5.984 0 0 1 2 6zm6-5a5 5 0 0 0-3.479 8.592c.263.254.514.564.676.941L5.83 12h4.342l.632-1.467c.162-.377.413-.687.676-.941A5 5 0 0 0 8 1z"/>
|
||||
</svg>
|
||||
<ng-container i18n>Suggest an idea</ng-container>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item mt-2">
|
||||
<div class="px-3 py-2 text-muted small">
|
||||
{{versionString}}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-md-4">
|
||||
<main role="main" class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
</div>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100; /* Behind the navbar */
|
||||
z-index: 995; /* Behind the navbar */
|
||||
padding: 50px 0 0; /* Height of navbar */
|
||||
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
padding-top: 0.5rem;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
|
||||
min-height: min-content;
|
||||
}
|
||||
@supports ((position: -webkit-sticky) or (position: sticky)) {
|
||||
.sidebar-sticky {
|
||||
@@ -57,6 +58,54 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.nav {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
position: relative;
|
||||
|
||||
&:hover .close {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
top: 0;
|
||||
padding: .25rem .3rem 0;
|
||||
right: .4rem;
|
||||
width: 1.8rem;
|
||||
height: 100%;
|
||||
|
||||
svg {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-link-additional {
|
||||
margin-top: 0.1rem;
|
||||
margin-left: 0.25rem;
|
||||
padding-top: 0.5rem;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Navbar
|
||||
*/
|
||||
@@ -95,6 +144,7 @@
|
||||
svg {
|
||||
position: absolute;
|
||||
left: 0.6rem;
|
||||
top: 0.5rem;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
@@ -113,7 +163,7 @@
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
padding-left: 1.8rem;
|
||||
border-color: rgba(255, 255, 255, 0.2);
|
||||
transition: flex 0.3s ease;
|
||||
transition: all .3s ease, padding-left 0s ease, background-color 0s ease; // Safari requires all
|
||||
max-width: 600px;
|
||||
min-width: 300px; // 1/2 max
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { from, Observable, Subscription } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Router, Params } from '@angular/router';
|
||||
import { from, Observable, Subscription, BehaviorSubject } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged, map, switchMap, first } from 'rxjs/operators';
|
||||
import { PaperlessDocument } from 'src/app/data/paperless-document';
|
||||
import { OpenDocumentsService } from 'src/app/services/open-documents.service';
|
||||
import { SavedViewService } from 'src/app/services/rest/saved-view.service';
|
||||
@@ -10,13 +10,15 @@ 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',
|
||||
templateUrl: './app-frame.component.html',
|
||||
styleUrls: ['./app-frame.component.scss']
|
||||
})
|
||||
export class AppFrameComponent implements OnInit, OnDestroy {
|
||||
export class AppFrameComponent {
|
||||
|
||||
constructor (
|
||||
public router: Router,
|
||||
@@ -24,10 +26,9 @@ export class AppFrameComponent implements OnInit, OnDestroy {
|
||||
private openDocumentsService: OpenDocumentsService,
|
||||
private searchService: SearchService,
|
||||
public savedViewService: SavedViewService,
|
||||
private list: DocumentListViewService,
|
||||
private meta: Meta
|
||||
) {
|
||||
|
||||
}
|
||||
) { }
|
||||
|
||||
versionString = `${environment.appTitle} ${environment.version}`
|
||||
|
||||
@@ -39,9 +40,9 @@ export class AppFrameComponent implements OnInit, OnDestroy {
|
||||
|
||||
searchField = new FormControl('')
|
||||
|
||||
openDocuments: PaperlessDocument[] = []
|
||||
|
||||
openDocumentsSubscription: Subscription
|
||||
get openDocuments(): PaperlessDocument[] {
|
||||
return this.openDocumentsService.getOpenDocuments()
|
||||
}
|
||||
|
||||
searchAutoComplete = (text$: Observable<string>) =>
|
||||
text$.pipe(
|
||||
@@ -74,31 +75,40 @@ export class AppFrameComponent implements OnInit, OnDestroy {
|
||||
|
||||
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) {
|
||||
this.openDocumentsService.closeDocument(d).pipe(first()).subscribe(confirmed => {
|
||||
if (confirmed) {
|
||||
this.closeMenu()
|
||||
let route = this.activatedRoute.snapshot
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild
|
||||
}
|
||||
if (route.component == DocumentDetailComponent && route.params['id'] == d.id) {
|
||||
this.router.navigate([""])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
closeAll() {
|
||||
this.closeMenu()
|
||||
this.openDocumentsService.closeAll()
|
||||
// user may need to confirm losing unsaved changes
|
||||
this.openDocumentsService.closeAll().pipe(first()).subscribe(confirmed => {
|
||||
if (confirmed) {
|
||||
this.closeMenu()
|
||||
|
||||
// TODO: is there a better way to do this?
|
||||
let route = this.activatedRoute
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild
|
||||
}
|
||||
if (route.component == DocumentDetailComponent) {
|
||||
this.router.navigate([""])
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.openDocuments = this.openDocumentsService.getOpenDocuments()
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.openDocumentsSubscription) {
|
||||
this.openDocumentsSubscription.unsubscribe()
|
||||
}
|
||||
// TODO: is there a better way to do this?
|
||||
let route = this.activatedRoute
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild
|
||||
}
|
||||
if (route.component === DocumentDetailComponent) {
|
||||
this.router.navigate([""])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
get displayName() {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<button type="button" class="close" aria-label="Close" (click)="cancelClicked()">
|
||||
<span aria-hidden="true">×</span>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="cancel()">
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -9,8 +8,8 @@
|
||||
<p *ngIf="message">{{message}}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-dark" (click)="cancelClicked()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
|
||||
<button type="button" class="btn" [class]="btnClass" (click)="confirmClicked.emit()" [disabled]="!confirmButtonEnabled || !buttonsEnabled">
|
||||
<button type="button" class="btn btn-outline-dark" (click)="cancel()" [disabled]="!buttonsEnabled" i18n>Cancel</button>
|
||||
<button type="button" class="btn" [class]="btnClass" (click)="confirm()" [disabled]="!confirmButtonEnabled || !buttonsEnabled">
|
||||
{{btnCaption}}
|
||||
<span *ngIf="!confirmButtonEnabled"> ({{seconds}})</span>
|
||||
</button>
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-confirm-dialog',
|
||||
templateUrl: './confirm-dialog.component.html',
|
||||
styleUrls: ['./confirm-dialog.component.scss']
|
||||
})
|
||||
export class ConfirmDialogComponent implements OnInit {
|
||||
export class ConfirmDialogComponent {
|
||||
|
||||
constructor(public activeModal: NgbActiveModal) { }
|
||||
|
||||
@@ -30,10 +31,12 @@ export class ConfirmDialogComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
buttonsEnabled = true
|
||||
|
||||
|
||||
confirmButtonEnabled = true
|
||||
seconds = 0
|
||||
|
||||
confirmSubject: Subject<boolean>
|
||||
|
||||
delayConfirm(seconds: number) {
|
||||
this.confirmButtonEnabled = false
|
||||
this.seconds = seconds
|
||||
@@ -46,10 +49,15 @@ export class ConfirmDialogComponent implements OnInit {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
cancelClicked() {
|
||||
cancel() {
|
||||
this.confirmSubject?.next(false)
|
||||
this.confirmSubject?.complete()
|
||||
this.activeModal.close()
|
||||
}
|
||||
|
||||
confirm() {
|
||||
this.confirmClicked.emit()
|
||||
this.confirmSubject?.next(true)
|
||||
this.confirmSubject?.complete()
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<div class="btn-group" ngbDropdown role="group">
|
||||
<div class="btn-group w-100" ngbDropdown role="group">
|
||||
<button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="dateBefore || dateAfter ? 'btn-primary' : 'btn-outline-primary'">
|
||||
{{title}}
|
||||
</button>
|
||||
<div class="dropdown-menu date-dropdown shadow pt-0" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
|
||||
<div class="list-group list-group-flush">
|
||||
<button *ngFor="let qf of quickFilters" class="list-group-item small list-goup list-group-item-action d-flex p-2 pl-3" role="menuitem" (click)="setDateQuickFilter(qf.id)">
|
||||
<button *ngFor="let qf of quickFilters" class="list-group-item small list-goup list-group-item-action d-flex p-2 ps-3" role="menuitem" (click)="setDateQuickFilter(qf.id)">
|
||||
{{qf.name}}
|
||||
</button>
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
@@ -20,8 +20,15 @@
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="date" class="form-control" id="date_after" [(ngModel)]="dateAfter" (change)="onChangeDebounce()">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()"
|
||||
[(ngModel)]="dateAfter" ngbDatepicker #dateAfterPicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateAfterPicker.toggle()" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16">
|
||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="list-group-item d-flex flex-column align-items-start" role="menuitem">
|
||||
|
||||
@@ -36,8 +43,15 @@
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="date" class="form-control" id="date_before" [(ngModel)]="dateBefore" (change)="onChangeDebounce()">
|
||||
<input class="form-control" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()"
|
||||
[(ngModel)]="dateBefore" ngbDatepicker #dateBeforePicker="ngbDatepicker">
|
||||
<button class="btn btn-outline-secondary" (click)="dateBeforePicker.toggle()" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" class="bi bi-calendar" viewBox="0 0 16 16">
|
||||
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,7 +1,10 @@
|
||||
import { formatDate } from '@angular/common';
|
||||
import { Component, EventEmitter, Input, Output, OnInit, OnDestroy } from '@angular/core';
|
||||
import { NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { SettingsService } from 'src/app/services/settings.service';
|
||||
import { ISODateAdapter } from 'src/app/utils/ngb-iso-date-adapter';
|
||||
|
||||
export interface DateSelection {
|
||||
before?: string
|
||||
@@ -16,10 +19,17 @@ const LAST_YEAR = 3
|
||||
@Component({
|
||||
selector: 'app-date-dropdown',
|
||||
templateUrl: './date-dropdown.component.html',
|
||||
styleUrls: ['./date-dropdown.component.scss']
|
||||
styleUrls: ['./date-dropdown.component.scss'],
|
||||
providers: [
|
||||
{provide: NgbDateAdapter, useClass: ISODateAdapter},
|
||||
]
|
||||
})
|
||||
export class DateDropdownComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(settings: SettingsService) {
|
||||
this.datePlaceHolder = settings.getLocalizedDateInputFormat()
|
||||
}
|
||||
|
||||
quickFilters = [
|
||||
{id: LAST_7_DAYS, name: $localize`Last 7 days`},
|
||||
{id: LAST_MONTH, name: $localize`Last month`},
|
||||
@@ -27,6 +37,8 @@ export class DateDropdownComponent implements OnInit, OnDestroy {
|
||||
{id: LAST_YEAR, name: $localize`Last year`}
|
||||
]
|
||||
|
||||
datePlaceHolder: string
|
||||
|
||||
@Input()
|
||||
dateBefore: string
|
||||
|
||||
|
@@ -27,6 +27,8 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
|
||||
|
||||
networkActive = false
|
||||
|
||||
closeEnabled = false
|
||||
|
||||
error = null
|
||||
|
||||
abstract getForm(): FormGroup
|
||||
@@ -37,6 +39,11 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
|
||||
if (this.object != null) {
|
||||
this.objectForm.patchValue(this.object)
|
||||
}
|
||||
|
||||
// wait to enable close button so it doesnt steal focus from input since its the first clickable element in the DOM
|
||||
setTimeout(() => {
|
||||
this.closeEnabled = true
|
||||
});
|
||||
}
|
||||
|
||||
getCreateTitle() {
|
||||
|