mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-15 10:13:15 -05:00
Enhancement: management list button improvements (#7848)
This commit is contained in:
parent
fc683e150a
commit
54293bedb1
@ -322,20 +322,24 @@
|
|||||||
<context context-type="linenumber">128</context>
|
<context context-type="linenumber">128</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
<context context-type="linenumber">90</context>
|
<context context-type="linenumber">54</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">90</context>
|
<context context-type="linenumber">101</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">90</context>
|
<context context-type="linenumber">101</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">90</context>
|
<context context-type="linenumber">101</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
|
<context context-type="linenumber">101</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4930506384627295710" datatype="html">
|
<trans-unit id="4930506384627295710" datatype="html">
|
||||||
@ -1493,7 +1497,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
<context context-type="linenumber">34</context>
|
<context context-type="linenumber">36</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
|
<context context-type="linenumber">48</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
||||||
@ -1529,35 +1537,35 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">83</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">83</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">83</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">84</context>
|
<context context-type="linenumber">83</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">96</context>
|
<context context-type="linenumber">95</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||||
@ -2219,7 +2227,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">73</context>
|
<context context-type="linenumber">80</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
||||||
@ -2418,7 +2426,11 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
<context context-type="linenumber">31</context>
|
<context context-type="linenumber">35</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
|
<context context-type="linenumber">45</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</context>
|
||||||
@ -2438,35 +2450,35 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">83</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">83</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">83</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">83</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">93</context>
|
<context context-type="linenumber">92</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">93</context>
|
<context context-type="linenumber">92</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">93</context>
|
<context context-type="linenumber">92</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">93</context>
|
<context context-type="linenumber">92</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.html</context>
|
||||||
@ -2570,7 +2582,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">75</context>
|
<context context-type="linenumber">82</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/mail/mail.component.ts</context>
|
||||||
@ -3286,7 +3298,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">56</context>
|
<context context-type="linenumber">63</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="1841172489943868696" datatype="html">
|
<trans-unit id="1841172489943868696" datatype="html">
|
||||||
@ -3297,7 +3309,7 @@
|
|||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">63</context>
|
<context context-type="linenumber">70</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4465085913683915434" datatype="html">
|
<trans-unit id="4465085913683915434" datatype="html">
|
||||||
@ -7475,39 +7487,62 @@
|
|||||||
<context context-type="linenumber">18</context>
|
<context context-type="linenumber">18</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="6209318295562170730" datatype="html">
|
||||||
|
<source>Filter Documents (<x id="INTERPOLATION" equiv-text="{{ field.document_count }}"/>)</source>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
|
<context context-type="linenumber">38</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
|
<context context-type="linenumber">85</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
|
<context context-type="linenumber">85</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
|
<context context-type="linenumber">85</context>
|
||||||
|
</context-group>
|
||||||
|
<context-group purpose="location">
|
||||||
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
|
<context context-type="linenumber">85</context>
|
||||||
|
</context-group>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="651372623796033489" datatype="html">
|
<trans-unit id="651372623796033489" datatype="html">
|
||||||
<source>No fields defined.</source>
|
<source>No fields defined.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
|
||||||
<context context-type="linenumber">42</context>
|
<context context-type="linenumber">63</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="3032792139967609806" datatype="html">
|
<trans-unit id="3032792139967609806" datatype="html">
|
||||||
<source>Confirm delete field</source>
|
<source>Confirm delete field</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">71</context>
|
<context context-type="linenumber">78</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="2939457975223185057" datatype="html">
|
<trans-unit id="2939457975223185057" datatype="html">
|
||||||
<source>This operation will permanently delete this field.</source>
|
<source>This operation will permanently delete this field.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">72</context>
|
<context context-type="linenumber">79</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5137089475515834162" datatype="html">
|
<trans-unit id="5137089475515834162" datatype="html">
|
||||||
<source>Deleted field</source>
|
<source>Deleted field</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">81</context>
|
<context context-type="linenumber">88</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6352403551920829405" datatype="html">
|
<trans-unit id="6352403551920829405" datatype="html">
|
||||||
<source>Error deleting field.</source>
|
<source>Error deleting field.</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.ts</context>
|
||||||
<context context-type="linenumber">86</context>
|
<context context-type="linenumber">93</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8084492669582894778" datatype="html">
|
<trans-unit id="8084492669582894778" datatype="html">
|
||||||
@ -7799,42 +7834,23 @@
|
|||||||
<context context-type="linenumber">39</context>
|
<context context-type="linenumber">39</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7376880254267897616" datatype="html">
|
|
||||||
<source>Filter Documents</source>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
|
||||||
<context context-type="linenumber">82</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
|
||||||
<context context-type="linenumber">82</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
|
||||||
<context context-type="linenumber">82</context>
|
|
||||||
</context-group>
|
|
||||||
<context-group purpose="location">
|
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
|
||||||
<context context-type="linenumber">82</context>
|
|
||||||
</context-group>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="8095412801504464756" datatype="html">
|
<trans-unit id="8095412801504464756" datatype="html">
|
||||||
<source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/>} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION_2"/>}}</source>
|
<source>{VAR_PLURAL, plural, =1 {One <x id="INTERPOLATION"/>} other {<x id="INTERPOLATION_1"/> total <x id="INTERPOLATION_2"/>}}</source>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">110</context>
|
<context context-type="linenumber">116</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">110</context>
|
<context context-type="linenumber">116</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">110</context>
|
<context context-type="linenumber">116</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
<context-group purpose="location">
|
<context-group purpose="location">
|
||||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.html</context>
|
||||||
<context context-type="linenumber">110</context>
|
<context context-type="linenumber">116</context>
|
||||||
</context-group>
|
</context-group>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="810888510148304696" datatype="html">
|
<trans-unit id="810888510148304696" datatype="html">
|
||||||
|
@ -26,7 +26,21 @@
|
|||||||
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editField(field)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.CustomField)">{{field.name}}</button></div>
|
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editField(field)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.CustomField)">{{field.name}}</button></div>
|
||||||
<div class="col d-flex align-items-center">{{getDataType(field)}}</div>
|
<div class="col d-flex align-items-center">{{getDataType(field)}}</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="btn-group">
|
<div class="btn-group d-block d-sm-none">
|
||||||
|
<div ngbDropdown container="body" class="d-inline-block">
|
||||||
|
<button type="button" class="btn btn-link" id="actionsMenuMobile" (click)="$event.stopPropagation()" ngbDropdownToggle>
|
||||||
|
<i-bs name="three-dots-vertical"></i-bs>
|
||||||
|
</button>
|
||||||
|
<div ngbDropdownMenu aria-labelledby="actionsMenuMobile">
|
||||||
|
<button (click)="editField(field)" *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.CustomField }" ngbDropdownItem i18n>Edit</button>
|
||||||
|
<button class="text-danger" (click)="deleteField(field)" *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.CustomField }" ngbDropdownItem i18n>Delete</button>
|
||||||
|
@if (field.document_count > 0) {
|
||||||
|
<button (click)="filterDocuments(field)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }" ngbDropdownItem i18n>Filter Documents ({{ field.document_count }})</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group d-none d-sm-inline-block">
|
||||||
<button *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.CustomField }" class="btn btn-sm btn-outline-secondary" type="button" (click)="editField(field)">
|
<button *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.CustomField }" class="btn btn-sm btn-outline-secondary" type="button" (click)="editField(field)">
|
||||||
<i-bs width="1em" height="1em" name="pencil"></i-bs> <ng-container i18n>Edit</ng-container>
|
<i-bs width="1em" height="1em" name="pencil"></i-bs> <ng-container i18n>Edit</ng-container>
|
||||||
</button>
|
</button>
|
||||||
@ -34,6 +48,13 @@
|
|||||||
<i-bs width="1em" height="1em" name="trash"></i-bs> <ng-container i18n>Delete</ng-container>
|
<i-bs width="1em" height="1em" name="trash"></i-bs> <ng-container i18n>Delete</ng-container>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@if (field.document_count > 0) {
|
||||||
|
<div class="btn-group d-none d-sm-inline-block ms-2">
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" type="button" (click)="filterDocuments(field)">
|
||||||
|
<i-bs width="1em" height="1em" name="filter"></i-bs> <ng-container i18n>Documents</ng-container><span class="badge bg-light text-secondary ms-2">{{ field.document_count }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
// hide caret on mobile dropdown
|
||||||
|
.d-block.d-sm-none .dropdown-toggle::after {
|
||||||
|
display: none;
|
||||||
|
}
|
@ -22,6 +22,12 @@ import { PageHeaderComponent } from '../../common/page-header/page-header.compon
|
|||||||
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
|
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
|
||||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||||
|
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||||
|
import { FILTER_CUSTOM_FIELDS_QUERY } from 'src/app/data/filter-rule-type'
|
||||||
|
import {
|
||||||
|
CustomFieldQueryLogicalOperator,
|
||||||
|
CustomFieldQueryOperator,
|
||||||
|
} from 'src/app/data/custom-field-query'
|
||||||
|
|
||||||
const fields: CustomField[] = [
|
const fields: CustomField[] = [
|
||||||
{
|
{
|
||||||
@ -42,6 +48,7 @@ describe('CustomFieldsComponent', () => {
|
|||||||
let customFieldsService: CustomFieldsService
|
let customFieldsService: CustomFieldsService
|
||||||
let modalService: NgbModal
|
let modalService: NgbModal
|
||||||
let toastService: ToastService
|
let toastService: ToastService
|
||||||
|
let listViewService: DocumentListViewService
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -83,6 +90,7 @@ describe('CustomFieldsComponent', () => {
|
|||||||
)
|
)
|
||||||
modalService = TestBed.inject(NgbModal)
|
modalService = TestBed.inject(NgbModal)
|
||||||
toastService = TestBed.inject(ToastService)
|
toastService = TestBed.inject(ToastService)
|
||||||
|
listViewService = TestBed.inject(DocumentListViewService)
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CustomFieldsComponent)
|
fixture = TestBed.createComponent(CustomFieldsComponent)
|
||||||
component = fixture.componentInstance
|
component = fixture.componentInstance
|
||||||
@ -145,7 +153,7 @@ describe('CustomFieldsComponent', () => {
|
|||||||
const deleteSpy = jest.spyOn(customFieldsService, 'delete')
|
const deleteSpy = jest.spyOn(customFieldsService, 'delete')
|
||||||
const reloadSpy = jest.spyOn(component, 'reload')
|
const reloadSpy = jest.spyOn(component, 'reload')
|
||||||
|
|
||||||
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[4]
|
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[5]
|
||||||
deleteButton.triggerEventHandler('click')
|
deleteButton.triggerEventHandler('click')
|
||||||
|
|
||||||
expect(modal).not.toBeUndefined()
|
expect(modal).not.toBeUndefined()
|
||||||
@ -162,4 +170,18 @@ describe('CustomFieldsComponent', () => {
|
|||||||
editDialog.confirmClicked.emit()
|
editDialog.confirmClicked.emit()
|
||||||
expect(reloadSpy).toHaveBeenCalled()
|
expect(reloadSpy).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should support filter documents', () => {
|
||||||
|
const filterSpy = jest.spyOn(listViewService, 'quickFilter')
|
||||||
|
component.filterDocuments(fields[0])
|
||||||
|
expect(filterSpy).toHaveBeenCalledWith([
|
||||||
|
{
|
||||||
|
rule_type: FILTER_CUSTOM_FIELDS_QUERY,
|
||||||
|
value: JSON.stringify([
|
||||||
|
CustomFieldQueryLogicalOperator.Or,
|
||||||
|
[[fields[0].id, CustomFieldQueryOperator.Exists, true]],
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -9,6 +9,12 @@ import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dial
|
|||||||
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
|
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
|
||||||
import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component'
|
import { EditDialogMode } from '../../common/edit-dialog/edit-dialog.component'
|
||||||
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
|
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
|
||||||
|
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||||
|
import { FILTER_CUSTOM_FIELDS_QUERY } from 'src/app/data/filter-rule-type'
|
||||||
|
import {
|
||||||
|
CustomFieldQueryLogicalOperator,
|
||||||
|
CustomFieldQueryOperator,
|
||||||
|
} from 'src/app/data/custom-field-query'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pngx-custom-fields',
|
selector: 'pngx-custom-fields',
|
||||||
@ -26,7 +32,8 @@ export class CustomFieldsComponent
|
|||||||
private customFieldsService: CustomFieldsService,
|
private customFieldsService: CustomFieldsService,
|
||||||
public permissionsService: PermissionsService,
|
public permissionsService: PermissionsService,
|
||||||
private modalService: NgbModal,
|
private modalService: NgbModal,
|
||||||
private toastService: ToastService
|
private toastService: ToastService,
|
||||||
|
private documentListViewService: DocumentListViewService
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@ -92,4 +99,16 @@ export class CustomFieldsComponent
|
|||||||
getDataType(field: CustomField): string {
|
getDataType(field: CustomField): string {
|
||||||
return DATA_TYPE_LABELS.find((l) => l.id === field.data_type).name
|
return DATA_TYPE_LABELS.find((l) => l.id === field.data_type).name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filterDocuments(field: CustomField) {
|
||||||
|
this.documentListViewService.quickFilter([
|
||||||
|
{
|
||||||
|
rule_type: FILTER_CUSTOM_FIELDS_QUERY,
|
||||||
|
value: JSON.stringify([
|
||||||
|
CustomFieldQueryLogicalOperator.Or,
|
||||||
|
[[field.id, CustomFieldQueryOperator.Exists, true]],
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,16 +79,15 @@
|
|||||||
<i-bs name="three-dots-vertical"></i-bs>
|
<i-bs name="three-dots-vertical"></i-bs>
|
||||||
</button>
|
</button>
|
||||||
<div ngbDropdownMenu aria-labelledby="actionsMenuMobile">
|
<div ngbDropdownMenu aria-labelledby="actionsMenuMobile">
|
||||||
<button (click)="filterDocuments(object)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }" ngbDropdownItem i18n>Filter Documents</button>
|
|
||||||
<button (click)="openEditDialog(object)" *pngxIfPermissions="{ action: PermissionAction.Change, type: permissionType }" ngbDropdownItem i18n>Edit</button>
|
<button (click)="openEditDialog(object)" *pngxIfPermissions="{ action: PermissionAction.Change, type: permissionType }" ngbDropdownItem i18n>Edit</button>
|
||||||
<button class="text-danger" (click)="openDeleteDialog(object)" *pngxIfPermissions="{ action: PermissionAction.Delete, type: permissionType }" ngbDropdownItem i18n>Delete</button>
|
<button class="text-danger" (click)="openDeleteDialog(object)" *pngxIfPermissions="{ action: PermissionAction.Delete, type: permissionType }" ngbDropdownItem i18n>Delete</button>
|
||||||
|
@if (object.document_count > 0) {
|
||||||
|
<button (click)="filterDocuments(object)" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }" ngbDropdownItem i18n>Filter Documents ({{ object.document_count }})</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group d-none d-sm-block">
|
<div class="btn-group d-none d-sm-inline-block">
|
||||||
<button class="btn btn-sm btn-outline-secondary" (click)="filterDocuments(object); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }">
|
|
||||||
<i-bs width="1em" height="1em" name="filter"></i-bs> <ng-container i18n>Documents</ng-container>
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-sm btn-outline-secondary" (click)="openEditDialog(object); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.Change, type: permissionType }" [disabled]="!userCanEdit(object)">
|
<button class="btn btn-sm btn-outline-secondary" (click)="openEditDialog(object); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.Change, type: permissionType }" [disabled]="!userCanEdit(object)">
|
||||||
<i-bs width="1em" height="1em" name="pencil"></i-bs> <ng-container i18n>Edit</ng-container>
|
<i-bs width="1em" height="1em" name="pencil"></i-bs> <ng-container i18n>Edit</ng-container>
|
||||||
</button>
|
</button>
|
||||||
@ -96,6 +95,13 @@
|
|||||||
<i-bs width="1em" height="1em" name="trash"></i-bs> <ng-container i18n>Delete</ng-container>
|
<i-bs width="1em" height="1em" name="trash"></i-bs> <ng-container i18n>Delete</ng-container>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@if (object.document_count > 0) {
|
||||||
|
<div class="btn-group d-none d-sm-inline-block ms-2">
|
||||||
|
<button class="btn btn-sm btn-outline-secondary" (click)="filterDocuments(object); $event.stopPropagation();" *pngxIfPermissions="{ action: PermissionAction.View, type: PermissionType.Document }">
|
||||||
|
<i-bs width="1em" height="1em" name="filter"></i-bs> <ng-container i18n>Documents</ng-container><span class="badge bg-light text-secondary ms-2">{{ object.document_count }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
@ -49,16 +49,19 @@ const tags: Tag[] = [
|
|||||||
name: 'Tag1 Foo',
|
name: 'Tag1 Foo',
|
||||||
matching_algorithm: MATCH_LITERAL,
|
matching_algorithm: MATCH_LITERAL,
|
||||||
match: 'foo',
|
match: 'foo',
|
||||||
|
document_count: 35,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: 'Tag2',
|
name: 'Tag2',
|
||||||
matching_algorithm: MATCH_NONE,
|
matching_algorithm: MATCH_NONE,
|
||||||
|
document_count: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: 'Tag3',
|
name: 'Tag3',
|
||||||
matching_algorithm: MATCH_AUTO,
|
matching_algorithm: MATCH_AUTO,
|
||||||
|
document_count: 5,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -180,7 +183,7 @@ describe('ManagementListComponent', () => {
|
|||||||
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
|
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
|
||||||
const reloadSpy = jest.spyOn(component, 'reloadData')
|
const reloadSpy = jest.spyOn(component, 'reloadData')
|
||||||
|
|
||||||
const editButton = fixture.debugElement.queryAll(By.css('button'))[7]
|
const editButton = fixture.debugElement.queryAll(By.css('button'))[6]
|
||||||
editButton.triggerEventHandler('click')
|
editButton.triggerEventHandler('click')
|
||||||
|
|
||||||
expect(modal).not.toBeUndefined()
|
expect(modal).not.toBeUndefined()
|
||||||
@ -205,7 +208,7 @@ describe('ManagementListComponent', () => {
|
|||||||
const deleteSpy = jest.spyOn(tagService, 'delete')
|
const deleteSpy = jest.spyOn(tagService, 'delete')
|
||||||
const reloadSpy = jest.spyOn(component, 'reloadData')
|
const reloadSpy = jest.spyOn(component, 'reloadData')
|
||||||
|
|
||||||
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[8]
|
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[7]
|
||||||
deleteButton.triggerEventHandler('click')
|
deleteButton.triggerEventHandler('click')
|
||||||
|
|
||||||
expect(modal).not.toBeUndefined()
|
expect(modal).not.toBeUndefined()
|
||||||
@ -225,7 +228,7 @@ describe('ManagementListComponent', () => {
|
|||||||
|
|
||||||
it('should support quick filter for objects', () => {
|
it('should support quick filter for objects', () => {
|
||||||
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
|
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
|
||||||
const filterButton = fixture.debugElement.queryAll(By.css('button'))[6]
|
const filterButton = fixture.debugElement.queryAll(By.css('button'))[8]
|
||||||
filterButton.triggerEventHandler('click')
|
filterButton.triggerEventHandler('click')
|
||||||
expect(qfSpy).toHaveBeenCalledWith([
|
expect(qfSpy).toHaveBeenCalledWith([
|
||||||
{ rule_type: FILTER_HAS_TAGS_ALL, value: tags[0].id.toString() },
|
{ rule_type: FILTER_HAS_TAGS_ALL, value: tags[0].id.toString() },
|
||||||
|
@ -59,4 +59,5 @@ export interface CustomField extends ObjectWithId {
|
|||||||
select_options?: string[]
|
select_options?: string[]
|
||||||
default_currency?: string
|
default_currency?: string
|
||||||
}
|
}
|
||||||
|
document_count?: number
|
||||||
}
|
}
|
||||||
|
@ -494,6 +494,8 @@ class CustomFieldSerializer(serializers.ModelSerializer):
|
|||||||
read_only=False,
|
read_only=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
document_count = serializers.IntegerField(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomField
|
model = CustomField
|
||||||
fields = [
|
fields = [
|
||||||
@ -501,6 +503,7 @@ class CustomFieldSerializer(serializers.ModelSerializer):
|
|||||||
"name",
|
"name",
|
||||||
"data_type",
|
"data_type",
|
||||||
"extra_data",
|
"extra_data",
|
||||||
|
"document_count",
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
@ -933,3 +934,51 @@ class TestCustomFieldsAPI(DirectoriesMixin, APITestCase):
|
|||||||
results = response.data["results"]
|
results = response.data["results"]
|
||||||
self.assertEqual(len(results), 1)
|
self.assertEqual(len(results), 1)
|
||||||
self.assertEqual(results[0]["name"], custom_field_int.name)
|
self.assertEqual(results[0]["name"], custom_field_int.name)
|
||||||
|
|
||||||
|
def test_custom_fields_document_count(self):
|
||||||
|
custom_field_string = CustomField.objects.create(
|
||||||
|
name="Test Custom Field String",
|
||||||
|
data_type=CustomField.FieldDataType.STRING,
|
||||||
|
)
|
||||||
|
doc = Document.objects.create(
|
||||||
|
title="WOW",
|
||||||
|
content="the content",
|
||||||
|
checksum="123",
|
||||||
|
mime_type="application/pdf",
|
||||||
|
owner=self.user,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
f"{self.ENDPOINT}",
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
results = response.data["results"]
|
||||||
|
self.assertEqual(results[0]["document_count"], 0)
|
||||||
|
|
||||||
|
CustomFieldInstance.objects.create(
|
||||||
|
document=doc,
|
||||||
|
field=custom_field_string,
|
||||||
|
value_text="test value",
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
f"{self.ENDPOINT}",
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
results = response.data["results"]
|
||||||
|
self.assertEqual(results[0]["document_count"], 1)
|
||||||
|
|
||||||
|
# Test as user without access to the document
|
||||||
|
non_superuser = User.objects.create_user(username="non_superuser")
|
||||||
|
non_superuser.user_permissions.add(
|
||||||
|
*Permission.objects.all(),
|
||||||
|
)
|
||||||
|
non_superuser.save()
|
||||||
|
self.client.force_authenticate(user=non_superuser)
|
||||||
|
self.client.force_login(user=non_superuser)
|
||||||
|
response = self.client.get(
|
||||||
|
f"{self.ENDPOINT}",
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
results = response.data["results"]
|
||||||
|
self.assertEqual(results[0]["document_count"], 0)
|
||||||
|
@ -1897,6 +1897,32 @@ class CustomFieldViewSet(ModelViewSet):
|
|||||||
|
|
||||||
queryset = CustomField.objects.all().order_by("-created")
|
queryset = CustomField.objects.all().order_by("-created")
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
filter = (
|
||||||
|
Q(fields__document__deleted_at__isnull=True)
|
||||||
|
if self.request.user is None or self.request.user.is_superuser
|
||||||
|
else (
|
||||||
|
Q(
|
||||||
|
fields__document__deleted_at__isnull=True,
|
||||||
|
fields__document__id__in=get_objects_for_user_owner_aware(
|
||||||
|
self.request.user,
|
||||||
|
"documents.view_document",
|
||||||
|
Document,
|
||||||
|
).values_list("id", flat=True),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
super()
|
||||||
|
.get_queryset()
|
||||||
|
.annotate(
|
||||||
|
document_count=Count(
|
||||||
|
"fields",
|
||||||
|
filter=filter,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SystemStatusView(PassUserMixin):
|
class SystemStatusView(PassUserMixin):
|
||||||
permission_classes = (IsAuthenticated,)
|
permission_classes = (IsAuthenticated,)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user