mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Enhancement: filter by file type (#8946)
This commit is contained in:
parent
880f08599a
commit
63bb3644f6
@ -1167,7 +1167,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">170</context>
|
||||
<context context-type="linenumber">173</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7314814725704332646" datatype="html">
|
||||
@ -2162,7 +2162,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">225</context>
|
||||
<context context-type="linenumber">224</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/saved-views/saved-views.component.html</context>
|
||||
@ -2196,11 +2196,11 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">221</context>
|
||||
<context context-type="linenumber">220</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">338</context>
|
||||
<context context-type="linenumber">337</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1373208150912772963" datatype="html">
|
||||
@ -2242,7 +2242,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">340</context>
|
||||
<context context-type="linenumber">339</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context>
|
||||
@ -2577,7 +2577,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">342</context>
|
||||
<context context-type="linenumber">341</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/workflows/workflows.component.ts</context>
|
||||
@ -2731,7 +2731,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
|
||||
<context context-type="linenumber">106</context>
|
||||
<context context-type="linenumber">107</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7886570921510760899" datatype="html">
|
||||
@ -2750,7 +2750,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
|
||||
<context context-type="linenumber">93</context>
|
||||
<context context-type="linenumber">94</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||
@ -2781,7 +2781,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
|
||||
<context context-type="linenumber">119</context>
|
||||
<context context-type="linenumber">120</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5421255270838137624" datatype="html">
|
||||
@ -2796,7 +2796,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.html</context>
|
||||
<context context-type="linenumber">132</context>
|
||||
<context context-type="linenumber">133</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3188389494264426470" datatype="html">
|
||||
@ -6192,7 +6192,7 @@
|
||||
<source>Other</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/dashboard/widgets/statistics-widget/statistics-widget.component.ts</context>
|
||||
<context context-type="linenumber">79</context>
|
||||
<context context-type="linenumber">83</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8187573012244728580" datatype="html">
|
||||
@ -6401,7 +6401,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">158</context>
|
||||
<context context-type="linenumber">160</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||
@ -7029,7 +7029,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">166</context>
|
||||
<context context-type="linenumber">168</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6475890479659129881" datatype="html">
|
||||
@ -7631,7 +7631,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">163</context>
|
||||
<context context-type="linenumber">165</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||
@ -7820,147 +7820,154 @@
|
||||
<source>Title & content</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">161</context>
|
||||
<context context-type="linenumber">163</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7408932238599462499" datatype="html">
|
||||
<source>File type</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">170</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2649431021108393503" datatype="html">
|
||||
<source>More like</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">176</context>
|
||||
<context context-type="linenumber">179</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3697582909018473071" datatype="html">
|
||||
<source>equals</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">182</context>
|
||||
<context context-type="linenumber">185</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5325481293405718739" datatype="html">
|
||||
<source>is empty</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">186</context>
|
||||
<context context-type="linenumber">189</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6166785695326182482" datatype="html">
|
||||
<source>is not empty</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">190</context>
|
||||
<context context-type="linenumber">193</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4686622206659266699" datatype="html">
|
||||
<source>greater than</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">194</context>
|
||||
<context context-type="linenumber">197</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8014012170270529279" datatype="html">
|
||||
<source>less than</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">198</context>
|
||||
<context context-type="linenumber">201</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5195932016807797291" datatype="html">
|
||||
<source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) => c.id == +rule.value)?.name"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">230,232</context>
|
||||
<context context-type="linenumber">233,235</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8170755470576301659" datatype="html">
|
||||
<source>Without correspondent</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">234</context>
|
||||
<context context-type="linenumber">237</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="317796810569008208" datatype="html">
|
||||
<source>Document type: <x id="PH" equiv-text="this.documentTypes.find((dt) => dt.id == +rule.value)?.name"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">240,242</context>
|
||||
<context context-type="linenumber">243,245</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4362173610367509215" datatype="html">
|
||||
<source>Without document type</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">244</context>
|
||||
<context context-type="linenumber">247</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="232202047340644471" datatype="html">
|
||||
<source>Storage path: <x id="PH" equiv-text="this.storagePaths.find((sp) => sp.id == +rule.value)?.name"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">250,252</context>
|
||||
<context context-type="linenumber">253,255</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1562820715074533164" datatype="html">
|
||||
<source>Without storage path</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">254</context>
|
||||
<context context-type="linenumber">257</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8180755793012580465" datatype="html">
|
||||
<source>Tag: <x id="PH" equiv-text="this.tags.find((t) => t.id == +rule.value)?.name"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">258,260</context>
|
||||
<context context-type="linenumber">261,263</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6494566478302448576" datatype="html">
|
||||
<source>Without any tag</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">264</context>
|
||||
<context context-type="linenumber">267</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8644099678903817943" datatype="html">
|
||||
<source>Custom fields query</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">268</context>
|
||||
<context context-type="linenumber">271</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6523384805359286307" datatype="html">
|
||||
<source>Title: <x id="PH" equiv-text="rule.value"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">271</context>
|
||||
<context context-type="linenumber">274</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1872523635812236432" datatype="html">
|
||||
<source>ASN: <x id="PH" equiv-text="rule.value"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">274</context>
|
||||
<context context-type="linenumber">277</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="102674688969746976" datatype="html">
|
||||
<source>Owner: <x id="PH" equiv-text="rule.value"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">277</context>
|
||||
<context context-type="linenumber">280</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3550877650686009106" datatype="html">
|
||||
<source>Owner not in: <x id="PH" equiv-text="rule.value"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">280</context>
|
||||
<context context-type="linenumber">283</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1082034558646673343" datatype="html">
|
||||
<source>Without an owner</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.ts</context>
|
||||
<context context-type="linenumber">283</context>
|
||||
<context context-type="linenumber">286</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7210076240260527720" datatype="html">
|
||||
@ -8455,7 +8462,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">325</context>
|
||||
<context context-type="linenumber">324</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4010735610815226758" datatype="html">
|
||||
@ -8538,7 +8545,7 @@
|
||||
<source>Automatic</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">117</context>
|
||||
<context context-type="linenumber">116</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/matching-model.ts</context>
|
||||
@ -8549,7 +8556,7 @@
|
||||
<source>None</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">119</context>
|
||||
<context context-type="linenumber">118</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/matching-model.ts</context>
|
||||
@ -8560,70 +8567,70 @@
|
||||
<source>Successfully created <x id="PH" equiv-text="this.typeName"/>.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">178</context>
|
||||
<context context-type="linenumber">177</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3928835053823658072" datatype="html">
|
||||
<source>Error occurred while creating <x id="PH" equiv-text="this.typeName"/>.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">183</context>
|
||||
<context context-type="linenumber">182</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4835942264662718903" datatype="html">
|
||||
<source>Successfully updated <x id="PH" equiv-text="this.typeName"/> "<x id="PH_1" equiv-text="object.name"/>".</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">198</context>
|
||||
<context context-type="linenumber">197</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6442673774206210733" datatype="html">
|
||||
<source>Error occurred while saving <x id="PH" equiv-text="this.typeName"/>.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">203</context>
|
||||
<context context-type="linenumber">202</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8371896857609524947" datatype="html">
|
||||
<source>Associated documents will not be deleted.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">223</context>
|
||||
<context context-type="linenumber">222</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6639207128255974941" datatype="html">
|
||||
<source>Error while deleting element</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">239</context>
|
||||
<context context-type="linenumber">238</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4863024195229581844" datatype="html">
|
||||
<source>Permissions updated successfully</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">318</context>
|
||||
<context context-type="linenumber">317</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1464476612812630086" datatype="html">
|
||||
<source>This operation will permanently delete all objects.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">339</context>
|
||||
<context context-type="linenumber">338</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5897787932098828336" datatype="html">
|
||||
<source>Objects deleted successfully</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">353</context>
|
||||
<context context-type="linenumber">352</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8273353839648035634" datatype="html">
|
||||
<source>Error deleting objects</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/management-list/management-list.component.ts</context>
|
||||
<context context-type="linenumber">359</context>
|
||||
<context context-type="linenumber">358</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1930477323485553035" datatype="html">
|
||||
|
@ -56,6 +56,7 @@
|
||||
[ngbPopover]="getFileTypeName(filetype)"
|
||||
i18n-ngbPopover
|
||||
triggers="mouseenter:mouseleave"
|
||||
(click)="filterByFileType(filetype)"
|
||||
[attr.aria-label]="getFileTypeName(filetype)"
|
||||
[class.me-1px]="!last"
|
||||
[style.width]="getFileTypePercent(filetype) + '%'"
|
||||
@ -70,7 +71,7 @@
|
||||
<div class="d-flex flex-wrap align-items-start">
|
||||
@for (filetype of statistics?.document_file_type_counts; track filetype; let i = $index) {
|
||||
<div class="d-flex">
|
||||
<div class="text-nowrap me-2">
|
||||
<div class="text-nowrap me-2" [class.cursor-pointer]="!filetype.is_other" (click)="filterByFileType(filetype)">
|
||||
<span class="badge rounded-pill bg-primary d-inline-block p-0 me-1" [style.opacity]="getItemOpacity(i)"></span>
|
||||
<small class="text-nowrap"><span class="fw-bold">{{ getFileTypeExtension(filetype) }}</span> <span class="text-muted">({{getFileTypePercent(filetype) | number: '1.0-1'}}%)</span></small>
|
||||
</div>
|
||||
|
@ -9,8 +9,10 @@ import { RouterTestingModule } from '@angular/router/testing'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Subject } from 'rxjs'
|
||||
import { routes } from 'src/app/app-routing.module'
|
||||
import { FILTER_MIME_TYPE } from 'src/app/data/filter-rule-type'
|
||||
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
|
||||
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||
import {
|
||||
FileStatus,
|
||||
WebsocketStatusService,
|
||||
@ -24,6 +26,7 @@ describe('StatisticsWidgetComponent', () => {
|
||||
let fixture: ComponentFixture<StatisticsWidgetComponent>
|
||||
let httpTestingController: HttpTestingController
|
||||
let websocketStatusService: WebsocketStatusService
|
||||
let documentListViewService: DocumentListViewService
|
||||
const fileStatusSubject = new Subject<FileStatus>()
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -48,6 +51,7 @@ describe('StatisticsWidgetComponent', () => {
|
||||
jest
|
||||
.spyOn(websocketStatusService, 'onDocumentConsumptionFinished')
|
||||
.mockReturnValue(fileStatusSubject)
|
||||
documentListViewService = TestBed.inject(DocumentListViewService)
|
||||
component = fixture.componentInstance
|
||||
|
||||
httpTestingController = TestBed.inject(HttpTestingController)
|
||||
@ -231,4 +235,26 @@ describe('StatisticsWidgetComponent', () => {
|
||||
'CurrentASN:'
|
||||
)
|
||||
})
|
||||
|
||||
it('should support quick filter by mime type', () => {
|
||||
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
|
||||
component.filterByFileType({
|
||||
mime_type: 'application/pdf',
|
||||
mime_type_count: 160,
|
||||
})
|
||||
expect(qfSpy).toHaveBeenCalledWith([
|
||||
{
|
||||
rule_type: FILTER_MIME_TYPE,
|
||||
value: 'application/pdf',
|
||||
},
|
||||
])
|
||||
|
||||
qfSpy.mockClear()
|
||||
component.filterByFileType({
|
||||
mime_type: 'Other',
|
||||
mime_type_count: 160,
|
||||
is_other: true,
|
||||
})
|
||||
expect(qfSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
@ -6,7 +6,10 @@ import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import * as mimeTypeNames from 'mime-names'
|
||||
import { first, Subject, Subscription, takeUntil } from 'rxjs'
|
||||
import { ComponentWithPermissions } from 'src/app/components/with-permissions/with-permissions.component'
|
||||
import { FILTER_HAS_TAGS_ANY } from 'src/app/data/filter-rule-type'
|
||||
import {
|
||||
FILTER_HAS_TAGS_ANY,
|
||||
FILTER_MIME_TYPE,
|
||||
} from 'src/app/data/filter-rule-type'
|
||||
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
|
||||
import { WebsocketStatusService } from 'src/app/services/websocket-status.service'
|
||||
@ -29,6 +32,7 @@ export interface Statistics {
|
||||
interface DocumentFileType {
|
||||
mime_type: string
|
||||
mime_type_count: number
|
||||
is_other?: boolean
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -77,6 +81,7 @@ export class StatisticsWidgetComponent
|
||||
statistics.document_file_type_counts.slice(0, fileTypeMax)
|
||||
statistics.document_file_type_counts.push({
|
||||
mime_type: $localize`Other`,
|
||||
is_other: true,
|
||||
mime_type_count: others.reduce(
|
||||
(currentValue, documentFileType) =>
|
||||
documentFileType.mime_type_count + currentValue,
|
||||
@ -132,4 +137,14 @@ export class StatisticsWidgetComponent
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
filterByFileType(filetype: DocumentFileType) {
|
||||
if (filetype.is_other) return
|
||||
this.documentListViewService.quickFilter([
|
||||
{
|
||||
rule_type: FILTER_MIME_TYPE,
|
||||
value: filetype.mime_type,
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ import {
|
||||
FILTER_HAS_STORAGE_PATH_ANY,
|
||||
FILTER_HAS_TAGS_ALL,
|
||||
FILTER_HAS_TAGS_ANY,
|
||||
FILTER_MIME_TYPE,
|
||||
FILTER_OWNER,
|
||||
FILTER_OWNER_ANY,
|
||||
FILTER_OWNER_DOES_NOT_INCLUDE,
|
||||
@ -389,6 +390,18 @@ describe('FilterEditorComponent', () => {
|
||||
expect(component.textFilterModifier).toEqual('less') // TEXT_FILTER_MODIFIER_LT
|
||||
}))
|
||||
|
||||
it('should ingest text filter rules for mime type', fakeAsync(() => {
|
||||
expect(component.textFilter).toEqual(null)
|
||||
component.filterRules = [
|
||||
{
|
||||
rule_type: FILTER_MIME_TYPE,
|
||||
value: 'pdf',
|
||||
},
|
||||
]
|
||||
expect(component.textFilter).toEqual('pdf')
|
||||
expect(component.textFilterTarget).toEqual('mime-type') // TEXT_FILTER_TARGET_MIME_TYPE
|
||||
}))
|
||||
|
||||
it('should ingest text filter rules for fulltext query', fakeAsync(() => {
|
||||
expect(component.textFilter).toEqual(null)
|
||||
component.filterRules = [
|
||||
@ -1222,12 +1235,30 @@ describe('FilterEditorComponent', () => {
|
||||
])
|
||||
}))
|
||||
|
||||
it('should convert user input to correct filter rules on mime type', fakeAsync(() => {
|
||||
component.textFilterInput.nativeElement.value = 'pdf'
|
||||
component.textFilterInput.nativeElement.dispatchEvent(new Event('input'))
|
||||
const textFieldTargetDropdown = fixture.debugElement.queryAll(
|
||||
By.directive(NgbDropdownItem)
|
||||
)[4]
|
||||
textFieldTargetDropdown.triggerEventHandler('click') // TEXT_FILTER_TARGET_MIME_TYPE
|
||||
fixture.detectChanges()
|
||||
tick(400)
|
||||
expect(component.textFilterTarget).toEqual('mime-type')
|
||||
expect(component.filterRules).toEqual([
|
||||
{
|
||||
rule_type: FILTER_MIME_TYPE,
|
||||
value: 'pdf',
|
||||
},
|
||||
])
|
||||
}))
|
||||
|
||||
it('should convert user input to correct filter rules on full text query', fakeAsync(() => {
|
||||
component.textFilterInput.nativeElement.value = 'foo'
|
||||
component.textFilterInput.nativeElement.dispatchEvent(new Event('input'))
|
||||
const textFieldTargetDropdown = fixture.debugElement.queryAll(
|
||||
By.directive(NgbDropdownItem)
|
||||
)[4]
|
||||
)[5]
|
||||
textFieldTargetDropdown.triggerEventHandler('click') // TEXT_FILTER_TARGET_ASN
|
||||
fixture.detectChanges()
|
||||
tick(400)
|
||||
@ -1594,7 +1625,7 @@ describe('FilterEditorComponent', () => {
|
||||
component.textFilterInput.nativeElement.dispatchEvent(new Event('input'))
|
||||
const textFieldTargetDropdown = fixture.debugElement.queryAll(
|
||||
By.directive(NgbDropdownItem)
|
||||
)[4]
|
||||
)[5]
|
||||
textFieldTargetDropdown.triggerEventHandler('click')
|
||||
fixture.detectChanges()
|
||||
tick(400)
|
||||
|
@ -66,6 +66,7 @@ import {
|
||||
FILTER_HAS_STORAGE_PATH_ANY,
|
||||
FILTER_HAS_TAGS_ALL,
|
||||
FILTER_HAS_TAGS_ANY,
|
||||
FILTER_MIME_TYPE,
|
||||
FILTER_OWNER,
|
||||
FILTER_OWNER_ANY,
|
||||
FILTER_OWNER_DOES_NOT_INCLUDE,
|
||||
@ -126,6 +127,7 @@ const TEXT_FILTER_TARGET_ASN = 'asn'
|
||||
const TEXT_FILTER_TARGET_FULLTEXT_QUERY = 'fulltext-query'
|
||||
const TEXT_FILTER_TARGET_FULLTEXT_MORELIKE = 'fulltext-morelike'
|
||||
const TEXT_FILTER_TARGET_CUSTOM_FIELDS = 'custom-fields'
|
||||
const TEXT_FILTER_TARGET_MIME_TYPE = 'mime-type'
|
||||
|
||||
const TEXT_FILTER_MODIFIER_EQUALS = 'equals'
|
||||
const TEXT_FILTER_MODIFIER_NULL = 'is null'
|
||||
@ -165,6 +167,7 @@ const DEFAULT_TEXT_FILTER_TARGET_OPTIONS = [
|
||||
id: TEXT_FILTER_TARGET_CUSTOM_FIELDS,
|
||||
name: $localize`Custom fields`,
|
||||
},
|
||||
{ id: TEXT_FILTER_TARGET_MIME_TYPE, name: $localize`File type` },
|
||||
{
|
||||
id: TEXT_FILTER_TARGET_FULLTEXT_QUERY,
|
||||
name: $localize`Advanced search`,
|
||||
@ -416,6 +419,10 @@ export class FilterEditorComponent
|
||||
this._textFilter = rule.value
|
||||
this.textFilterTarget = TEXT_FILTER_TARGET_CUSTOM_FIELDS
|
||||
break
|
||||
case FILTER_MIME_TYPE:
|
||||
this.textFilterTarget = TEXT_FILTER_TARGET_MIME_TYPE
|
||||
this._textFilter = rule.value
|
||||
break
|
||||
case FILTER_FULLTEXT_QUERY:
|
||||
let allQueryArgs = rule.value.split(',')
|
||||
let textQueryArgs = []
|
||||
@ -729,6 +736,15 @@ export class FilterEditorComponent
|
||||
value: this._textFilter,
|
||||
})
|
||||
}
|
||||
if (
|
||||
this._textFilter &&
|
||||
this.textFilterTarget == TEXT_FILTER_TARGET_MIME_TYPE
|
||||
) {
|
||||
filterRules.push({
|
||||
rule_type: FILTER_MIME_TYPE,
|
||||
value: this._textFilter,
|
||||
})
|
||||
}
|
||||
if (
|
||||
this._textFilter &&
|
||||
this.textFilterTarget == TEXT_FILTER_TARGET_FULLTEXT_QUERY
|
||||
|
@ -62,6 +62,8 @@ export const FILTER_HAS_ANY_CUSTOM_FIELDS = 41
|
||||
|
||||
export const FILTER_CUSTOM_FIELDS_QUERY = 42
|
||||
|
||||
export const FILTER_MIME_TYPE = 47
|
||||
|
||||
export const FILTER_RULE_TYPES: FilterRuleType[] = [
|
||||
{
|
||||
id: FILTER_TITLE,
|
||||
@ -354,6 +356,12 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
|
||||
datatype: 'string',
|
||||
multi: false,
|
||||
},
|
||||
{
|
||||
id: FILTER_MIME_TYPE,
|
||||
filtervar: 'mime_type',
|
||||
datatype: 'string',
|
||||
multi: false,
|
||||
},
|
||||
]
|
||||
|
||||
export interface FilterRuleType {
|
||||
|
@ -215,6 +215,14 @@ class CustomFieldsFilter(Filter):
|
||||
return qs
|
||||
|
||||
|
||||
class MimeTypeFilter(Filter):
|
||||
def filter(self, qs, value):
|
||||
if value:
|
||||
return qs.filter(mime_type__icontains=value)
|
||||
else:
|
||||
return qs
|
||||
|
||||
|
||||
class SelectField(serializers.CharField):
|
||||
def __init__(self, custom_field: CustomField):
|
||||
self._options = custom_field.extra_data["select_options"]
|
||||
@ -710,6 +718,8 @@ class DocumentFilterSet(FilterSet):
|
||||
|
||||
shared_by__id = SharedByUser()
|
||||
|
||||
mime_type = MimeTypeFilter()
|
||||
|
||||
class Meta:
|
||||
model = Document
|
||||
fields = {
|
||||
|
@ -62,6 +62,7 @@ class Migration(migrations.Migration):
|
||||
(44, "created from"),
|
||||
(45, "added to"),
|
||||
(46, "added from"),
|
||||
(47, "mime type is"),
|
||||
],
|
||||
verbose_name="rule type",
|
||||
),
|
||||
|
@ -526,6 +526,7 @@ class SavedViewFilterRule(models.Model):
|
||||
(44, _("created from")),
|
||||
(45, _("added to")),
|
||||
(46, _("added from")),
|
||||
(47, _("mime type is")),
|
||||
]
|
||||
|
||||
saved_view = models.ForeignKey(
|
||||
|
@ -639,6 +639,13 @@ class TestDocumentApi(DirectoriesMixin, DocumentConsumeDelayMixin, APITestCase):
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertEqual(results[0]["id"], doc3.id)
|
||||
|
||||
response = self.client.get(
|
||||
"/api/documents/?mime_type=pdf",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
results = response.data["results"]
|
||||
self.assertEqual(len(results), 3)
|
||||
|
||||
def test_custom_field_select_filter(self):
|
||||
"""
|
||||
GIVEN:
|
||||
|
Loading…
x
Reference in New Issue
Block a user