mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Enhancement: implement document link custom field (#4799)
This commit is contained in:
		| @@ -343,6 +343,7 @@ The following custom field types are supported: | ||||
| - `Integer`: integer number e.g. 12 | ||||
| - `Number`: float number e.g. 12.3456 | ||||
| - `Monetary`: float number with exactly two decimals, e.g. 12.30 | ||||
| - `Document Link`: reference(s) to other document(s), displayed as links | ||||
|  | ||||
| ## Share Links | ||||
|  | ||||
|   | ||||
| @@ -294,7 +294,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">81</context> | ||||
|           <context context-type="linenumber">92</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1241348629231510663" datatype="html"> | ||||
| @@ -447,6 +447,10 @@ | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">30</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.html</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/permissions-dialog/permissions-dialog.component.html</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
| @@ -459,6 +463,10 @@ | ||||
|           <context context-type="sourcefile">src/app/components/dashboard/widgets/widget-frame/widget-frame.component.html</context> | ||||
|           <context context-type="linenumber">14</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">248</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
|           <context context-type="linenumber">95</context> | ||||
| @@ -766,7 +774,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">221</context> | ||||
|           <context context-type="linenumber">216</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -852,11 +860,11 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">46</context> | ||||
|           <context context-type="linenumber">47</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">65</context> | ||||
|           <context context-type="linenumber">66</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context> | ||||
| @@ -879,11 +887,11 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">54</context> | ||||
|           <context context-type="linenumber">55</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">73</context> | ||||
|           <context context-type="linenumber">74</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context> | ||||
| @@ -909,7 +917,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">79</context> | ||||
|           <context context-type="linenumber">80</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/permissions/permissions-form/permissions-form.component.html</context> | ||||
| @@ -1150,7 +1158,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">34</context> | ||||
|           <context context-type="linenumber">45</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -1217,7 +1225,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">11</context> | ||||
|           <context context-type="linenumber">22</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -1291,7 +1299,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">90</context> | ||||
|           <context context-type="linenumber">91</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> | ||||
| @@ -1335,7 +1343,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">93</context> | ||||
|           <context context-type="linenumber">104</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/save-view-config-dialog/save-view-config-dialog.component.html</context> | ||||
| @@ -1829,7 +1837,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">677</context> | ||||
|           <context context-type="linenumber">691</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> | ||||
| @@ -1868,7 +1876,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">679</context> | ||||
|           <context context-type="linenumber">693</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> | ||||
| @@ -2556,32 +2564,39 @@ | ||||
|           <context context-type="linenumber">37</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="475685412372379925" datatype="html"> | ||||
|         <source>Assign custom fields</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">38</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5057200219587080996" datatype="html"> | ||||
|         <source>Assign owner</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|           <context context-type="linenumber">41</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1749184201773078639" datatype="html"> | ||||
|         <source>Assign view permissions</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">42</context> | ||||
|           <context context-type="linenumber">43</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1744964187586405039" datatype="html"> | ||||
|         <source>Assign edit permissions</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">61</context> | ||||
|           <context context-type="linenumber">62</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1519954996184640001" datatype="html"> | ||||
|         <source>Error</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">88</context> | ||||
|           <context context-type="linenumber">89</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context> | ||||
| @@ -2596,7 +2611,7 @@ | ||||
|         <source>Cancel</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.html</context> | ||||
|           <context context-type="linenumber">89</context> | ||||
|           <context context-type="linenumber">90</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component.html</context> | ||||
| @@ -2659,35 +2674,35 @@ | ||||
|         <source>Consume Folder</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">25</context> | ||||
|           <context context-type="linenumber">27</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="526966086395145275" datatype="html"> | ||||
|         <source>API Upload</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">29</context> | ||||
|           <context context-type="linenumber">31</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7502272564743467653" datatype="html"> | ||||
|         <source>Mail Fetch</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">33</context> | ||||
|           <context context-type="linenumber">35</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2057608151109082984" datatype="html"> | ||||
|         <source>Create new consumption template</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">83</context> | ||||
|           <context context-type="linenumber">92</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3745279073747685988" datatype="html"> | ||||
|         <source>Edit consumption template</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/consumption-template-edit-dialog/consumption-template-edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">87</context> | ||||
|           <context context-type="linenumber">96</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8743659855412792665" datatype="html"> | ||||
| @@ -2807,14 +2822,14 @@ | ||||
|         <source>Create new item</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">109</context> | ||||
|           <context context-type="linenumber">111</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5324147361912094446" datatype="html"> | ||||
|         <source>Edit item</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/edit-dialog/edit-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">113</context> | ||||
|           <context context-type="linenumber">115</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7878445132438733225" datatype="html"> | ||||
| @@ -3468,6 +3483,10 @@ | ||||
|           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context> | ||||
|           <context context-type="linenumber">8</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.html</context> | ||||
|           <context context-type="linenumber">8</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/number/number.component.html</context> | ||||
|           <context context-type="linenumber">8</context> | ||||
| @@ -3518,6 +3537,13 @@ | ||||
|           <context context-type="linenumber">155</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6423278459497515329" datatype="html"> | ||||
|         <source>No documents found</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/input/document-link/document-link.component.ts</context> | ||||
|           <context context-type="linenumber">44</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5554528553553249088" datatype="html"> | ||||
|         <source>Show password</source> | ||||
|         <context-group purpose="location"> | ||||
| @@ -3627,7 +3653,7 @@ | ||||
|         <source>Note that permissions set here will override any existing permissions</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/common/permissions-dialog/permissions-dialog.component.ts</context> | ||||
|           <context context-type="linenumber">62</context> | ||||
|           <context context-type="linenumber">71</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5947558132119506443" datatype="html"> | ||||
| @@ -3971,7 +3997,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">103</context> | ||||
|           <context context-type="linenumber">114</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context> | ||||
| @@ -3994,7 +4020,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">107</context> | ||||
|           <context context-type="linenumber">118</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4028,7 +4054,7 @@ | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">18</context> | ||||
|           <context context-type="linenumber">29</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4215,7 +4241,7 @@ | ||||
|         <source>Page</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">3</context> | ||||
|           <context context-type="linenumber">4</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4226,21 +4252,35 @@ | ||||
|         <source>of <x id="INTERPOLATION" equiv-text="{{previewNumPages}}"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">5,6</context> | ||||
|           <context context-type="linenumber">6,7</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8590109102084543521" datatype="html"> | ||||
|         <source>-</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">9</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8479257185772414452" datatype="html"> | ||||
|         <source>+</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">15</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8659635229098859487" datatype="html"> | ||||
|         <source>Download original</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">24</context> | ||||
|           <context context-type="linenumber">35</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8312409092917397847" datatype="html"> | ||||
|         <source>Redo OCR</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|           <context context-type="linenumber">51</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4251,7 +4291,7 @@ | ||||
|         <source>More like this</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">46</context> | ||||
|           <context context-type="linenumber">57</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/document-card-large/document-card-large.component.html</context> | ||||
| @@ -4262,7 +4302,7 @@ | ||||
|         <source>Close</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">71</context> | ||||
|           <context context-type="linenumber">82</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context> | ||||
| @@ -4273,56 +4313,56 @@ | ||||
|         <source>Previous</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">76</context> | ||||
|           <context context-type="linenumber">87</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3823219296477075982" datatype="html"> | ||||
|         <source>Discard</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">89</context> | ||||
|           <context context-type="linenumber">100</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5129524307369213584" datatype="html"> | ||||
|         <source>Save & next</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">91</context> | ||||
|           <context context-type="linenumber">102</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4910102545766233758" datatype="html"> | ||||
|         <source>Save & close</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">92</context> | ||||
|           <context context-type="linenumber">103</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5028777105388019087" datatype="html"> | ||||
|         <source>Details</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">100</context> | ||||
|           <context context-type="linenumber">111</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1379170675585571971" datatype="html"> | ||||
|         <source>Archive serial number</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">104</context> | ||||
|           <context context-type="linenumber">115</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5114742157723900905" datatype="html"> | ||||
|         <source>Date created</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">105</context> | ||||
|           <context context-type="linenumber">116</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5066119607229701477" datatype="html"> | ||||
|         <source>Document type</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">109</context> | ||||
|           <context context-type="linenumber">120</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4345,7 +4385,7 @@ | ||||
|         <source>Storage path</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">111</context> | ||||
|           <context context-type="linenumber">122</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context> | ||||
| @@ -4364,21 +4404,21 @@ | ||||
|         <source>Default</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">112</context> | ||||
|           <context context-type="linenumber">123</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6205355627445317276" datatype="html"> | ||||
|         <source>Content</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">130</context> | ||||
|           <context context-type="linenumber">142</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="218403386307979629" datatype="html"> | ||||
|         <source>Metadata</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">139</context> | ||||
|           <context context-type="linenumber">151</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/metadata-collapse/metadata-collapse.component.ts</context> | ||||
| @@ -4389,152 +4429,152 @@ | ||||
|         <source>Date modified</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">145</context> | ||||
|           <context context-type="linenumber">157</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6392918669949841614" datatype="html"> | ||||
|         <source>Date added</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">149</context> | ||||
|           <context context-type="linenumber">161</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="146828917013192897" datatype="html"> | ||||
|         <source>Media filename</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">153</context> | ||||
|           <context context-type="linenumber">165</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4500855521601039868" datatype="html"> | ||||
|         <source>Original filename</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">157</context> | ||||
|           <context context-type="linenumber">169</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7985558498848210210" datatype="html"> | ||||
|         <source>Original MD5 checksum</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">161</context> | ||||
|           <context context-type="linenumber">173</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5888243105821763422" datatype="html"> | ||||
|         <source>Original file size</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">165</context> | ||||
|           <context context-type="linenumber">177</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2696647325713149563" datatype="html"> | ||||
|         <source>Original mime type</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">169</context> | ||||
|           <context context-type="linenumber">181</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="342875990758166588" datatype="html"> | ||||
|         <source>Archive MD5 checksum</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">173</context> | ||||
|           <context context-type="linenumber">185</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6033581412811562084" datatype="html"> | ||||
|         <source>Archive file size</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">177</context> | ||||
|           <context context-type="linenumber">189</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6992781481378431874" datatype="html"> | ||||
|         <source>Original document metadata</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">183</context> | ||||
|           <context context-type="linenumber">195</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2846565152091361585" datatype="html"> | ||||
|         <source>Archived document metadata</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">184</context> | ||||
|           <context context-type="linenumber">196</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="1295614462098694869" datatype="html"> | ||||
|         <source>Preview</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">190</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8191371354890763172" datatype="html"> | ||||
|         <source>Enter Password</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">206</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">249</context> | ||||
|           <context context-type="linenumber">202</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8460995830263484763" datatype="html"> | ||||
|         <source>Notes <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span *ngIf="document?.notes.length" class="badge text-bg-secondary ms-1">"/><x id="INTERPOLATION" equiv-text="ngth}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</a>"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">214,215</context> | ||||
|           <context context-type="linenumber">209,210</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8191371354890763172" datatype="html"> | ||||
|         <source>Enter Password</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">237</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context> | ||||
|           <context context-type="linenumber">275</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="2218903673684131427" datatype="html"> | ||||
|         <source>An error occurred loading content: <x id="PH" equiv-text="err.message ?? err.toString()"/></source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">265,267</context> | ||||
|           <context context-type="linenumber">279,281</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5758784066858623886" datatype="html"> | ||||
|         <source>Error retrieving metadata</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">413</context> | ||||
|           <context context-type="linenumber">427</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3456881259945295697" datatype="html"> | ||||
|         <source>Error retrieving suggestions.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">434</context> | ||||
|           <context context-type="linenumber">448</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8348337312757497317" datatype="html"> | ||||
|         <source>Document saved successfully.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">552</context> | ||||
|           <context context-type="linenumber">566</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">561</context> | ||||
|           <context context-type="linenumber">575</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="448882439049417053" datatype="html"> | ||||
|         <source>Error saving document</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">565</context> | ||||
|           <context context-type="linenumber">579</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">606</context> | ||||
|           <context context-type="linenumber">620</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="9021887951960049161" datatype="html"> | ||||
|         <source>Confirm delete</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">632</context> | ||||
|           <context context-type="linenumber">646</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context> | ||||
| @@ -4545,35 +4585,35 @@ | ||||
|         <source>Do you really want to delete document "<x id="PH" equiv-text="this.document.title"/>"?</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">633</context> | ||||
|           <context context-type="linenumber">647</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6691075929777935948" datatype="html"> | ||||
|         <source>The files for this document will be deleted permanently. This operation cannot be undone.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">634</context> | ||||
|           <context context-type="linenumber">648</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="719892092227206532" datatype="html"> | ||||
|         <source>Delete document</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">636</context> | ||||
|           <context context-type="linenumber">650</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7295637485862454066" datatype="html"> | ||||
|         <source>Error deleting document</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">655</context> | ||||
|           <context context-type="linenumber">669</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="7362691899087997122" datatype="html"> | ||||
|         <source>Redo OCR confirm</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">675</context> | ||||
|           <context context-type="linenumber">689</context> | ||||
|         </context-group> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context> | ||||
| @@ -4584,21 +4624,28 @@ | ||||
|         <source>This operation will permanently redo OCR for this document.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">676</context> | ||||
|           <context context-type="linenumber">690</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5729001209753056399" datatype="html"> | ||||
|         <source>Redo OCR operation will begin in the background. Close and re-open or reload this document after the operation has completed to see new content.</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">687</context> | ||||
|           <context context-type="linenumber">701</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4409560272830824468" datatype="html"> | ||||
|         <source>Error executing operation</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">698</context> | ||||
|           <context context-type="linenumber">712</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="4458954481601077369" datatype="html"> | ||||
|         <source>Page Fit</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context> | ||||
|           <context context-type="linenumber">781</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6857598786757174736" datatype="html"> | ||||
| @@ -5433,7 +5480,7 @@ | ||||
|         <source>Initiating upload...</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/components/file-drop/file-drop.component.ts</context> | ||||
|           <context context-type="linenumber">87</context> | ||||
|           <context context-type="linenumber">88</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3789574458951567089" datatype="html"> | ||||
| @@ -6105,49 +6152,56 @@ | ||||
|         <source>Boolean</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">16</context> | ||||
|           <context context-type="linenumber">17</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3973931101896534797" datatype="html"> | ||||
|         <source>Date</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">20</context> | ||||
|           <context context-type="linenumber">21</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="362956598863566327" datatype="html"> | ||||
|         <source>Integer</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">24</context> | ||||
|           <context context-type="linenumber">25</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6370642728789544052" datatype="html"> | ||||
|         <source>Number</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">28</context> | ||||
|           <context context-type="linenumber">29</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6430409302408843009" datatype="html"> | ||||
|         <source>Monetary</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">32</context> | ||||
|           <context context-type="linenumber">33</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="6162693758764653365" datatype="html"> | ||||
|         <source>Text</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">36</context> | ||||
|           <context context-type="linenumber">37</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="8308045076391224954" datatype="html"> | ||||
|         <source>Url</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">40</context> | ||||
|           <context context-type="linenumber">41</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="3650316326183661476" datatype="html"> | ||||
|         <source>Document Link</source> | ||||
|         <context-group purpose="location"> | ||||
|           <context context-type="sourcefile">src/app/data/paperless-custom-field.ts</context> | ||||
|           <context context-type="linenumber">45</context> | ||||
|         </context-group> | ||||
|       </trans-unit> | ||||
|       <trans-unit id="5948496158474272829" datatype="html"> | ||||
|   | ||||
| @@ -106,6 +106,7 @@ import { CustomFieldEditDialogComponent } from './components/common/edit-dialog/ | ||||
| import { CustomFieldsDropdownComponent } from './components/common/custom-fields-dropdown/custom-fields-dropdown.component' | ||||
| import { ProfileEditDialogComponent } from './components/common/profile-edit-dialog/profile-edit-dialog.component' | ||||
| import { PdfViewerComponent } from './components/common/pdf-viewer/pdf-viewer.component' | ||||
| import { DocumentLinkComponent } from './components/common/input/document-link/document-link.component' | ||||
|  | ||||
| import localeAf from '@angular/common/locales/af' | ||||
| import localeAr from '@angular/common/locales/ar' | ||||
| @@ -259,6 +260,7 @@ function initializeApp(settings: SettingsService) { | ||||
|     CustomFieldsDropdownComponent, | ||||
|     ProfileEditDialogComponent, | ||||
|     PdfViewerComponent, | ||||
|     DocumentLinkComponent, | ||||
|   ], | ||||
|   imports: [ | ||||
|     BrowserModule, | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| <form [formGroup]="objectForm" (ngSubmit)="save()" autocomplete="off"> | ||||
|     <div class="modal-header"> | ||||
|       <h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4> | ||||
|       <button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()"> | ||||
|       </button> | ||||
|     </div> | ||||
|     <div class="modal-body"> | ||||
|       <pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text> | ||||
|       <pngx-input-select i18n-title title="Data type" [items]="getDataTypes()" formControlName="data_type"></pngx-input-select> | ||||
|       <small class="d-block mt-n2" *ngIf="typeFieldDisabled" i18n>Data type cannot be changed after a field is created</small> | ||||
|     </div> | ||||
|     <div class="modal-footer"> | ||||
|       <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||
|       <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||
|     </div> | ||||
|   </form> | ||||
|   <div class="modal-header"> | ||||
|     <h4 class="modal-title" id="modal-basic-title">{{getTitle()}}</h4> | ||||
|     <button type="button" [disabled]="!closeEnabled" class="btn-close" aria-label="Close" (click)="cancel()"> | ||||
|     </button> | ||||
|   </div> | ||||
|   <div class="modal-body"> | ||||
|     <pngx-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></pngx-input-text> | ||||
|     <pngx-input-select i18n-title title="Data type" [items]="getDataTypes()" formControlName="data_type"></pngx-input-select> | ||||
|     <small class="d-block mt-n2" *ngIf="typeFieldDisabled" i18n>Data type cannot be changed after a field is created</small> | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <button type="button" class="btn btn-outline-secondary" (click)="cancel()" i18n [disabled]="networkActive">Cancel</button> | ||||
|     <button type="submit" class="btn btn-primary" i18n [disabled]="networkActive">Save</button> | ||||
|   </div> | ||||
| </form> | ||||
|   | ||||
| @@ -0,0 +1,50 @@ | ||||
| <div class="mb-3 paperless-input-select" [class.disabled]="disabled"> | ||||
|     <div class="row"> | ||||
|       <div class="d-flex align-items-center position-relative hidden-button-container" [class.col-md-3]="horizontal"> | ||||
|         <label *ngIf="title" class="form-label" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label> | ||||
|         <button type="button" *ngIf="removable" class="btn btn-sm btn-danger position-absolute left-0" (click)="removed.emit(this)"> | ||||
|           <svg class="sidebaricon" fill="currentColor"> | ||||
|             <use xlink:href="assets/bootstrap-icons.svg#x"/> | ||||
|           </svg> <ng-container i18n>Remove</ng-container> | ||||
|         </button> | ||||
|       </div> | ||||
|       <div [class.col-md-9]="horizontal"> | ||||
|         <div> | ||||
|           <ng-select name="inputId" [(ngModel)]="selectedDocuments" | ||||
|             [disabled]="disabled" | ||||
|             [items]="foundDocuments$ | async" | ||||
|             placeholder="Search for documents" | ||||
|             [notFoundText]="notFoundText" | ||||
|             [multiple]="true" | ||||
|             bindValue="id" | ||||
|             [compareWith]="compareDocuments" | ||||
|             [trackByFn]="trackByFn" | ||||
|             [minTermLength]="2" | ||||
|             [loading]="loading" | ||||
|             [typeahead]="documentsInput$" | ||||
|             (change)="onChange(selectedDocuments)"> | ||||
|                 <ng-template ng-label-tmp let-document="item"> | ||||
|                   <div class="d-flex align-items-center"> | ||||
|                     <svg class="sidebaricon" fill="currentColor" xmlns="http://www.w3.org/2000/svg" (click)="unselect(document)"> | ||||
|                       <use xlink:href="assets/bootstrap-icons.svg#x"/> | ||||
|                     </svg> | ||||
|                     <a routerLink="/documents/{{document.id}}" class="badge bg-light text-primary"> | ||||
|                       <svg class="sidebaricon-sm me-1" fill="currentColor"> | ||||
|                         <use xlink:href="assets/bootstrap-icons.svg#file-text"/> | ||||
|                       </svg><span>{{document.title}}</span> | ||||
|                     </a> | ||||
|                   </div> | ||||
|                 </ng-template> | ||||
|                 <ng-template ng-loadingspinner-tmp> | ||||
|                   <div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div> | ||||
|                   <div class="visually-hidden" i18n>Loading...</div> | ||||
|                 </ng-template> | ||||
|                 <ng-template ng-option-tmp let-document="item" let-index="index" let-search="searchTerm"> | ||||
|                   <div>{{document.title}} <small class="text-muted">({{document.created | customDate:'shortDate'}})</small></div> | ||||
|                 </ng-template> | ||||
|           </ng-select> | ||||
|         </div> | ||||
|         <small *ngIf="hint" class="form-text text-muted">{{hint}}</small> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| @@ -0,0 +1,14 @@ | ||||
| ::ng-deep .ng-select-container .ng-value-container .ng-value { | ||||
|     background-color: transparent !important; | ||||
|     border-color: transparent; | ||||
| } | ||||
|  | ||||
| .sidebaricon { | ||||
|     cursor: pointer; | ||||
| } | ||||
|  | ||||
| .badge { | ||||
|     font-size: .75rem; | ||||
|     // --bs-primary: var(--pngx-bg-alt); | ||||
|     // color: var(--pngx-primary-text-contrast); | ||||
| } | ||||
| @@ -0,0 +1,118 @@ | ||||
| import { HttpClientTestingModule } from '@angular/common/http/testing' | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing' | ||||
| import { | ||||
|   FormsModule, | ||||
|   NG_VALUE_ACCESSOR, | ||||
|   ReactiveFormsModule, | ||||
| } from '@angular/forms' | ||||
| import { NgSelectModule } from '@ng-select/ng-select' | ||||
| import { of, throwError } from 'rxjs' | ||||
| import { DocumentService } from 'src/app/services/rest/document.service' | ||||
| import { DocumentLinkComponent } from './document-link.component' | ||||
| import { FILTER_TITLE } from 'src/app/data/filter-rule-type' | ||||
|  | ||||
| const documents = [ | ||||
|   { | ||||
|     id: 1, | ||||
|     title: 'Document 1 foo', | ||||
|   }, | ||||
|   { | ||||
|     id: 12, | ||||
|     title: 'Document 12 bar', | ||||
|   }, | ||||
|   { | ||||
|     id: 23, | ||||
|     title: 'Document 23 bar', | ||||
|   }, | ||||
| ] | ||||
|  | ||||
| describe('DocumentLinkComponent', () => { | ||||
|   let component: DocumentLinkComponent | ||||
|   let fixture: ComponentFixture<DocumentLinkComponent> | ||||
|   let documentService: DocumentService | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [DocumentLinkComponent], | ||||
|       imports: [ | ||||
|         HttpClientTestingModule, | ||||
|         NgSelectModule, | ||||
|         FormsModule, | ||||
|         ReactiveFormsModule, | ||||
|       ], | ||||
|     }) | ||||
|     documentService = TestBed.inject(DocumentService) | ||||
|     fixture = TestBed.createComponent(DocumentLinkComponent) | ||||
|     fixture.debugElement.injector.get(NG_VALUE_ACCESSOR) | ||||
|     component = fixture.componentInstance | ||||
|     fixture.detectChanges() | ||||
|   }) | ||||
|  | ||||
|   it('should retrieve selected documents from APIs', () => { | ||||
|     const getSpy = jest.spyOn(documentService, 'getCachedMany') | ||||
|     getSpy.mockImplementation((ids) => { | ||||
|       return of(documents.filter((d) => ids.includes(d.id))) | ||||
|     }) | ||||
|     component.writeValue([1]) | ||||
|     expect(getSpy).toHaveBeenCalled() | ||||
|   }) | ||||
|  | ||||
|   it('should search API on select text input', () => { | ||||
|     const listSpy = jest.spyOn(documentService, 'listFiltered') | ||||
|     listSpy.mockImplementation( | ||||
|       (page, pageSize, sortField, sortReverse, filterRules, extraParams) => { | ||||
|         const docs = documents.filter((d) => | ||||
|           d.title.includes(filterRules[0].value) | ||||
|         ) | ||||
|         return of({ | ||||
|           count: docs.length, | ||||
|           results: docs, | ||||
|           all: docs.map((d) => d.id), | ||||
|         }) | ||||
|       } | ||||
|     ) | ||||
|     component.documentsInput$.next('bar') | ||||
|     expect(listSpy).toHaveBeenCalledWith( | ||||
|       1, | ||||
|       null, | ||||
|       'created', | ||||
|       true, | ||||
|       [{ rule_type: FILTER_TITLE, value: 'bar' }], | ||||
|       { truncate_content: true } | ||||
|     ) | ||||
|     listSpy.mockReturnValueOnce(throwError(() => new Error())) | ||||
|     component.documentsInput$.next('foo') | ||||
|   }) | ||||
|  | ||||
|   it('should load values correctly', () => { | ||||
|     jest.spyOn(documentService, 'getCachedMany').mockImplementation((ids) => { | ||||
|       return of(documents.filter((d) => ids.includes(d.id))) | ||||
|     }) | ||||
|     component.writeValue([12, 23]) | ||||
|     expect(component.value).toEqual([12, 23]) | ||||
|     expect(component.selectedDocuments).toEqual([documents[1], documents[2]]) | ||||
|     component.writeValue(null) | ||||
|     expect(component.value).toEqual([]) | ||||
|     expect(component.selectedDocuments).toEqual([]) | ||||
|     component.writeValue([]) | ||||
|     expect(component.value).toEqual([]) | ||||
|     expect(component.selectedDocuments).toEqual([]) | ||||
|   }) | ||||
|  | ||||
|   it('should support unselect', () => { | ||||
|     const getSpy = jest.spyOn(documentService, 'getCachedMany') | ||||
|     getSpy.mockImplementation((ids) => { | ||||
|       return of(documents.filter((d) => ids.includes(d.id))) | ||||
|     }) | ||||
|     component.writeValue([12, 23]) | ||||
|     component.unselect({ id: 23 }) | ||||
|     fixture.detectChanges() | ||||
|     expect(component.selectedDocuments).toEqual([documents[1]]) | ||||
|   }) | ||||
|  | ||||
|   it('should use correct compare, trackBy functions', () => { | ||||
|     expect(component.compareDocuments(documents[0], { id: 1 })).toBeTruthy() | ||||
|     expect(component.compareDocuments(documents[0], { id: 2 })).toBeFalsy() | ||||
|     expect(component.trackByFn(documents[1])).toEqual(12) | ||||
|   }) | ||||
| }) | ||||
| @@ -0,0 +1,120 @@ | ||||
| import { Component, forwardRef, OnInit, Input, OnDestroy } from '@angular/core' | ||||
| import { NG_VALUE_ACCESSOR } from '@angular/forms' | ||||
| import { | ||||
|   Subject, | ||||
|   Observable, | ||||
|   takeUntil, | ||||
|   concat, | ||||
|   of, | ||||
|   distinctUntilChanged, | ||||
|   tap, | ||||
|   switchMap, | ||||
|   map, | ||||
|   catchError, | ||||
| } from 'rxjs' | ||||
| import { FILTER_TITLE } from 'src/app/data/filter-rule-type' | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document' | ||||
| import { DocumentService } from 'src/app/services/rest/document.service' | ||||
| import { AbstractInputComponent } from '../abstract-input' | ||||
|  | ||||
| @Component({ | ||||
|   providers: [ | ||||
|     { | ||||
|       provide: NG_VALUE_ACCESSOR, | ||||
|       useExisting: forwardRef(() => DocumentLinkComponent), | ||||
|       multi: true, | ||||
|     }, | ||||
|   ], | ||||
|   selector: 'pngx-input-document-link', | ||||
|   templateUrl: './document-link.component.html', | ||||
|   styleUrls: ['./document-link.component.scss'], | ||||
| }) | ||||
| export class DocumentLinkComponent | ||||
|   extends AbstractInputComponent<any[]> | ||||
|   implements OnInit, OnDestroy | ||||
| { | ||||
|   documentsInput$ = new Subject<string>() | ||||
|   foundDocuments$: Observable<PaperlessDocument[]> | ||||
|   loading = false | ||||
|   selectedDocuments: PaperlessDocument[] = [] | ||||
|  | ||||
|   private unsubscribeNotifier: Subject<any> = new Subject() | ||||
|  | ||||
|   @Input() | ||||
|   notFoundText: string = $localize`No documents found` | ||||
|  | ||||
|   constructor(private documentsService: DocumentService) { | ||||
|     super() | ||||
|   } | ||||
|  | ||||
|   ngOnInit() { | ||||
|     this.loadDocs() | ||||
|   } | ||||
|  | ||||
|   writeValue(documentIDs: number[]): void { | ||||
|     if (!documentIDs || documentIDs.length === 0) { | ||||
|       this.selectedDocuments = [] | ||||
|       super.writeValue([]) | ||||
|     } else { | ||||
|       this.loading = true | ||||
|       this.documentsService | ||||
|         .getCachedMany(documentIDs) | ||||
|         .pipe(takeUntil(this.unsubscribeNotifier)) | ||||
|         .subscribe((documents) => { | ||||
|           this.loading = false | ||||
|           this.selectedDocuments = documents | ||||
|           super.writeValue(documentIDs) | ||||
|         }) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private loadDocs() { | ||||
|     this.foundDocuments$ = concat( | ||||
|       of([]), // default items | ||||
|       this.documentsInput$.pipe( | ||||
|         distinctUntilChanged(), | ||||
|         takeUntil(this.unsubscribeNotifier), | ||||
|         tap(() => (this.loading = true)), | ||||
|         switchMap((title) => | ||||
|           this.documentsService | ||||
|             .listFiltered( | ||||
|               1, | ||||
|               null, | ||||
|               'created', | ||||
|               true, | ||||
|               [{ rule_type: FILTER_TITLE, value: title }], | ||||
|               { truncate_content: true } | ||||
|             ) | ||||
|             .pipe( | ||||
|               map((results) => results.results), | ||||
|               catchError(() => of([])), // empty on error | ||||
|               tap(() => (this.loading = false)) | ||||
|             ) | ||||
|         ) | ||||
|       ) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   unselect(document: PaperlessDocument): void { | ||||
|     this.selectedDocuments = this.selectedDocuments.filter( | ||||
|       (d) => d.id !== document.id | ||||
|     ) | ||||
|     this.onChange(this.selectedDocuments.map((d) => d.id)) | ||||
|   } | ||||
|  | ||||
|   compareDocuments( | ||||
|     document: PaperlessDocument, | ||||
|     selectedDocument: PaperlessDocument | ||||
|   ) { | ||||
|     return document.id === selectedDocument.id | ||||
|   } | ||||
|  | ||||
|   trackByFn(item: PaperlessDocument) { | ||||
|     return item.id | ||||
|   } | ||||
|  | ||||
|   ngOnDestroy(): void { | ||||
|     this.unsubscribeNotifier.next(true) | ||||
|     this.unsubscribeNotifier.complete() | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| <div class="mb-3 paperless-input-select paperless-input-tags" [class.disabled]="disabled" [class.pb-3]="suggestions"> | ||||
| <div class="mb-3 paperless-input-select paperless-input-tags" [class.disabled]="disabled" [class.pb-3]="getSuggestions().length > 0"> | ||||
|   <div class="row"> | ||||
|     <div class="d-flex align-items-center" [class.col-md-3]="horizontal"> | ||||
|       <label class="form-label" [class.mb-md-0]="horizontal" for="tags" i18n>{{title}}</label> | ||||
|   | ||||
| @@ -131,6 +131,7 @@ | ||||
|                                     <pngx-input-number *ngSwitchCase="PaperlessCustomFieldDataType.Monetary" formControlName="value" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true" [showAdd]="false" [step]=".01" [error]="getCustomFieldError(i)"></pngx-input-number> | ||||
|                                     <pngx-input-check *ngSwitchCase="PaperlessCustomFieldDataType.Boolean" formControlName="value" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true"></pngx-input-check> | ||||
|                                     <pngx-input-url *ngSwitchCase="PaperlessCustomFieldDataType.Url" formControlName="value" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true" [error]="getCustomFieldError(i)"></pngx-input-url> | ||||
|                                     <pngx-input-document-link *ngSwitchCase="PaperlessCustomFieldDataType.DocumentLink" formControlName="value" [title]="getCustomFieldFromInstance(fieldInstance)?.name" [removable]="true" (removed)="removeField(fieldInstance)" [horizontal]="true" [error]="getCustomFieldError(i)"></pngx-input-document-link> | ||||
|                                 </div> | ||||
|                             </ng-container> | ||||
|                         </div> | ||||
|   | ||||
| @@ -8,6 +8,7 @@ export enum PaperlessCustomFieldDataType { | ||||
|   Integer = 'integer', | ||||
|   Float = 'float', | ||||
|   Monetary = 'monetary', | ||||
|   DocumentLink = 'documentlink', | ||||
| } | ||||
|  | ||||
| export const DATA_TYPE_LABELS = [ | ||||
| @@ -39,6 +40,10 @@ export const DATA_TYPE_LABELS = [ | ||||
|     id: PaperlessCustomFieldDataType.Url, | ||||
|     name: $localize`Url`, | ||||
|   }, | ||||
|   { | ||||
|     id: PaperlessCustomFieldDataType.DocumentLink, | ||||
|     name: $localize`Document Link`, | ||||
|   }, | ||||
| ] | ||||
|  | ||||
| export interface PaperlessCustomField extends ObjectWithId { | ||||
|   | ||||
| @@ -1,23 +0,0 @@ | ||||
| # Generated by Django 4.2.7 on 2023-11-30 17:44 | ||||
|  | ||||
| from django.db import migrations | ||||
| from django.db import models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ("documents", "1041_alter_consumptiontemplate_sources"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name="consumptiontemplate", | ||||
|             name="assign_custom_fields", | ||||
|             field=models.ManyToManyField( | ||||
|                 blank=True, | ||||
|                 related_name="+", | ||||
|                 to="documents.customfield", | ||||
|                 verbose_name="assign these custom fields", | ||||
|             ), | ||||
|         ), | ||||
|     ] | ||||
| @@ -0,0 +1,47 @@ | ||||
| # Generated by Django 4.2.7 on 2023-12-04 04:03 | ||||
|  | ||||
| from django.db import migrations | ||||
| from django.db import models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|     dependencies = [ | ||||
|         ("documents", "1041_alter_consumptiontemplate_sources"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name="consumptiontemplate", | ||||
|             name="assign_custom_fields", | ||||
|             field=models.ManyToManyField( | ||||
|                 blank=True, | ||||
|                 related_name="+", | ||||
|                 to="documents.customfield", | ||||
|                 verbose_name="assign these custom fields", | ||||
|             ), | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name="customfieldinstance", | ||||
|             name="value_document_ids", | ||||
|             field=models.JSONField(null=True), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name="customfield", | ||||
|             name="data_type", | ||||
|             field=models.CharField( | ||||
|                 choices=[ | ||||
|                     ("string", "String"), | ||||
|                     ("url", "URL"), | ||||
|                     ("date", "Date"), | ||||
|                     ("boolean", "Boolean"), | ||||
|                     ("integer", "Integer"), | ||||
|                     ("float", "Float"), | ||||
|                     ("monetary", "Monetary"), | ||||
|                     ("documentlink", "Document Link"), | ||||
|                 ], | ||||
|                 editable=False, | ||||
|                 max_length=50, | ||||
|                 verbose_name="data type", | ||||
|             ), | ||||
|         ), | ||||
|     ] | ||||
| @@ -756,6 +756,7 @@ class CustomField(models.Model): | ||||
|         INT = ("integer", _("Integer")) | ||||
|         FLOAT = ("float", _("Float")) | ||||
|         MONETARY = ("monetary", _("Monetary")) | ||||
|         DOCUMENTLINK = ("documentlink", _("Document Link")) | ||||
|  | ||||
|     created = models.DateTimeField( | ||||
|         _("created"), | ||||
| @@ -834,6 +835,8 @@ class CustomFieldInstance(models.Model): | ||||
|  | ||||
|     value_monetary = models.DecimalField(null=True, decimal_places=2, max_digits=12) | ||||
|  | ||||
|     value_document_ids = models.JSONField(null=True) | ||||
|  | ||||
|     class Meta: | ||||
|         ordering = ("created",) | ||||
|         verbose_name = _("custom field instance") | ||||
| @@ -868,6 +871,8 @@ class CustomFieldInstance(models.Model): | ||||
|             return self.value_float | ||||
|         elif self.field.data_type == CustomField.FieldDataType.MONETARY: | ||||
|             return self.value_monetary | ||||
|         elif self.field.data_type == CustomField.FieldDataType.DOCUMENTLINK: | ||||
|             return self.value_document_ids | ||||
|         raise NotImplementedError(self.field.data_type) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -440,6 +440,7 @@ class CustomFieldInstanceSerializer(serializers.ModelSerializer): | ||||
|             CustomField.FieldDataType.INT: "value_int", | ||||
|             CustomField.FieldDataType.FLOAT: "value_float", | ||||
|             CustomField.FieldDataType.MONETARY: "value_monetary", | ||||
|             CustomField.FieldDataType.DOCUMENTLINK: "value_document_ids", | ||||
|         } | ||||
|         # An instance is attached to a document | ||||
|         document: Document = validated_data["document"] | ||||
|   | ||||
| @@ -34,7 +34,9 @@ class TestCustomField(DirectoriesMixin, APITestCase): | ||||
|             ("date", "Invoiced Date"), | ||||
|             ("integer", "Invoice #"), | ||||
|             ("boolean", "Is Active"), | ||||
|             ("float", "Total Paid"), | ||||
|             ("float", "Average Value"), | ||||
|             ("monetary", "Total Paid"), | ||||
|             ("documentlink", "Related Documents"), | ||||
|         ]: | ||||
|             resp = self.client.post( | ||||
|                 self.ENDPOINT, | ||||
| @@ -96,6 +98,10 @@ class TestCustomField(DirectoriesMixin, APITestCase): | ||||
|             name="Test Custom Field Monetary", | ||||
|             data_type=CustomField.FieldDataType.MONETARY, | ||||
|         ) | ||||
|         custom_field_documentlink = CustomField.objects.create( | ||||
|             name="Test Custom Field Doc Link", | ||||
|             data_type=CustomField.FieldDataType.DOCUMENTLINK, | ||||
|         ) | ||||
|  | ||||
|         date_value = date.today() | ||||
|  | ||||
| @@ -131,6 +137,10 @@ class TestCustomField(DirectoriesMixin, APITestCase): | ||||
|                         "field": custom_field_monetary.id, | ||||
|                         "value": 11.10, | ||||
|                     }, | ||||
|                     { | ||||
|                         "field": custom_field_documentlink.id, | ||||
|                         "value": [1, 2, 3], | ||||
|                     }, | ||||
|                 ], | ||||
|             }, | ||||
|             format="json", | ||||
| @@ -150,11 +160,12 @@ class TestCustomField(DirectoriesMixin, APITestCase): | ||||
|                 {"field": custom_field_url.id, "value": "https://example.com"}, | ||||
|                 {"field": custom_field_float.id, "value": 12.3456}, | ||||
|                 {"field": custom_field_monetary.id, "value": 11.10}, | ||||
|                 {"field": custom_field_documentlink.id, "value": [1, 2, 3]}, | ||||
|             ], | ||||
|         ) | ||||
|  | ||||
|         doc.refresh_from_db() | ||||
|         self.assertEqual(len(doc.custom_fields.all()), 7) | ||||
|         self.assertEqual(len(doc.custom_fields.all()), 8) | ||||
|  | ||||
|     def test_change_custom_field_instance_value(self): | ||||
|         """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon