]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: date picker and date filter dropdown improvements (#9033)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Fri, 7 Feb 2025 07:01:48 +0000 (23:01 -0800)
committerGitHub <noreply@github.com>
Fri, 7 Feb 2025 07:01:48 +0000 (23:01 -0800)
20 files changed:
src-ui/e2e/document-list/document-list.spec.ts
src-ui/e2e/document-list/requests/api-document-list3.har
src-ui/messages.xlf
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.scss
src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.ts
src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.html
src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.scss
src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.spec.ts
src-ui/src/app/components/common/dates-dropdown/dates-dropdown.component.ts
src-ui/src/app/components/common/input/date/date.component.html
src-ui/src/app/components/common/input/date/date.component.scss
src-ui/src/app/components/common/input/date/date.component.ts
src-ui/src/app/components/document-list/filter-editor/filter-editor.component.html
src-ui/src/app/components/document-list/filter-editor/filter-editor.component.spec.ts
src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts
src-ui/src/app/data/filter-rule-type.ts
src/documents/filters.py
src/documents/migrations/1062_alter_savedviewfilterrule_rule_type.py [new file with mode: 0644]
src/documents/models.py

index 7719873d36d5fd9f4367e1cfff2de434e513eaea..cd1a4c54e7ecf38c5eb20ec166e6d5eba68e9e06 100644 (file)
@@ -83,9 +83,9 @@ test('date filtering', async ({ page }) => {
   await page.routeFromHAR(REQUESTS_HAR3, { notFound: 'fallback' })
   await page.goto('/documents')
   await page.getByRole('button', { name: 'Dates' }).click()
-  await page.getByRole('menuitem', { name: 'Last 3 months' }).first().click()
+  await page.getByRole('menuitem', { name: 'Within 3 months' }).first().click()
   await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
-  await page.getByRole('menuitem', { name: 'Last 3 months' }).first().click()
+  await page.getByRole('menuitem', { name: 'Within 3 months' }).first().click()
   await page.getByLabel('Datesselected').getByRole('button').first().click()
   await page.getByRole('combobox', { name: 'Select month' }).selectOption('12')
   await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
index 6d5d1808fdc9c74473c14b2c3b7d27145d45b127..291915a65af7cd76c24db70c23880d9f9446a0c9 100644 (file)
         "time": 1.501,
         "request": {
           "method": "GET",
-          "url": "http://localhost:8000/api/documents/?page=1&page_size=50&ordering=-created&truncate_content=true&created__date__gt=2022-12-11",
+          "url": "http://localhost:8000/api/documents/?page=1&page_size=50&ordering=-created&truncate_content=true&created__date__gte=2022-12-11",
           "httpVersion": "HTTP/1.1",
           "cookies": [],
           "headers": [
               "value": "true"
             },
             {
-              "name": "created__date__gt",
+              "name": "created__date__gte",
               "value": "2022-12-11"
             }
           ],
index 9983e6b55f9bea46603f50ad4288616214443938..caab96d4b2abb24f8ca7818ac5d889709080cf84 100644 (file)
         </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">170</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7314814725704332646" datatype="html">
           <context context-type="linenumber">93</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6048892649018070225" datatype="html">
+        <source>Today</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
+          <context context-type="linenumber">39</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">50</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">76</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">126</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">152</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
+          <context context-type="linenumber">21</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="7819314041543176992" datatype="html">
+        <source>Close</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
+          <context context-type="linenumber">40</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">51</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">77</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">127</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">153</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
+          <context context-type="linenumber">22</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">94</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">1375</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context>
+          <context context-type="linenumber">37</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="4465085913683915434" datatype="html">
         <source>True</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">40</context>
+          <context context-type="linenumber">47</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">77</context>
+          <context context-type="linenumber">84</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">83</context>
+          <context context-type="linenumber">90</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3800326155195149498" datatype="html">
         <source>False</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">41</context>
+          <context context-type="linenumber">48</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">78</context>
+          <context context-type="linenumber">85</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">84</context>
+          <context context-type="linenumber">91</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7551700625201096185" datatype="html">
         <source>Search docs...</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">100</context>
+          <context context-type="linenumber">107</context>
         </context-group>
       </trans-unit>
       <trans-unit id="3184700926171002527" datatype="html">
         <source>Any</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">132</context>
+          <context context-type="linenumber">139</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
         <source>All</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">134</context>
+          <context context-type="linenumber">141</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/filterable-dropdown/filterable-dropdown.component.html</context>
         <source>Not</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">137</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6548676277933116532" datatype="html">
         <source>Add query</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">156</context>
+          <context context-type="linenumber">163</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5599577087865387184" datatype="html">
         <source>Add expression</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html</context>
-          <context context-type="linenumber">159</context>
+          <context context-type="linenumber">166</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6052766076365105714" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
-          <context context-type="linenumber">89</context>
+          <context context-type="linenumber">101</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="6371576811194810854" datatype="html">
-        <source>After</source>
+      <trans-unit id="5203279511751768967" datatype="html">
+        <source>From</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
           <context context-type="linenumber">42</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
-          <context context-type="linenumber">106</context>
+          <context context-type="linenumber">118</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="1218334388194408974" datatype="html">
-        <source>Before</source>
+      <trans-unit id="1640609344969975994" datatype="html">
+        <source>To</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
-          <context context-type="linenumber">62</context>
+          <context context-type="linenumber">68</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
-          <context context-type="linenumber">126</context>
+          <context context-type="linenumber">144</context>
         </context-group>
       </trans-unit>
       <trans-unit id="231679111972850796" datatype="html">
         <source>Added</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
-          <context context-type="linenumber">74</context>
+          <context context-type="linenumber">86</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
           <context context-type="linenumber">93</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4873149362496451858" datatype="html">
-        <source>Last 7 days</source>
+      <trans-unit id="9129856334122659953" datatype="html">
+        <source>Within 1 week</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
           <context context-type="linenumber">67</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4463380307954693363" datatype="html">
-        <source>Last month</source>
+      <trans-unit id="123064370501514576" datatype="html">
+        <source>Within 1 month</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
           <context context-type="linenumber">72</context>
         </context-group>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
-          <context context-type="linenumber">19</context>
-        </context-group>
       </trans-unit>
-      <trans-unit id="8697368973702409683" datatype="html">
-        <source>Last 3 months</source>
+      <trans-unit id="1027161426440526546" datatype="html">
+        <source>Within 3 months</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
           <context context-type="linenumber">77</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="3566342898065860218" datatype="html">
-        <source>Last year</source>
+      <trans-unit id="226779700214642230" datatype="html">
+        <source>Within 1 year</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
           <context context-type="linenumber">82</context>
         </context-group>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
-          <context context-type="linenumber">14</context>
-        </context-group>
       </trans-unit>
       <trans-unit id="8743659855412792665" datatype="html">
         <source>Matching algorithm</source>
         <source>Invalid date.</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
-          <context context-type="linenumber">25</context>
+          <context context-type="linenumber">31</context>
         </context-group>
       </trans-unit>
       <trans-unit id="524422427194414813" datatype="html">
         <source>Suggestions:</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/date/date.component.html</context>
-          <context context-type="linenumber">31</context>
+          <context context-type="linenumber">37</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/select/select.component.html</context>
         <source>Filter documents with this <x id="PH" equiv-text="this.title"/></source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/date/date.component.ts</context>
-          <context context-type="linenumber">121</context>
+          <context context-type="linenumber">123</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/input/select/select.component.ts</context>
           <context context-type="linenumber">70</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="7819314041543176992" datatype="html">
-        <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">94</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">1375</context>
-        </context-group>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/guards/dirty-saved-view.guard.ts</context>
-          <context context-type="linenumber">37</context>
-        </context-group>
-      </trans-unit>
       <trans-unit id="4452427314943113135" datatype="html">
         <source>Previous</source>
         <context-group purpose="location">
         </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">154</context>
+          <context context-type="linenumber">158</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/data/document.ts</context>
         </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">162</context>
+          <context context-type="linenumber">166</context>
         </context-group>
       </trans-unit>
       <trans-unit id="6475890479659129881" datatype="html">
         </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">159</context>
+          <context context-type="linenumber">163</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/data/document.ts</context>
         <source>Title &amp; 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">157</context>
+          <context context-type="linenumber">161</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">172</context>
+          <context context-type="linenumber">176</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">178</context>
+          <context context-type="linenumber">182</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">182</context>
+          <context context-type="linenumber">186</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">186</context>
+          <context context-type="linenumber">190</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">190</context>
+          <context context-type="linenumber">194</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">194</context>
+          <context context-type="linenumber">198</context>
         </context-group>
       </trans-unit>
       <trans-unit id="5195932016807797291" datatype="html">
         <source>Correspondent: <x id="PH" equiv-text="this.correspondents.find((c) =&gt; 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">226,228</context>
+          <context context-type="linenumber">230,232</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">230</context>
+          <context context-type="linenumber">234</context>
         </context-group>
       </trans-unit>
       <trans-unit id="317796810569008208" datatype="html">
         <source>Document type: <x id="PH" equiv-text="this.documentTypes.find((dt) =&gt; 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">236,238</context>
+          <context context-type="linenumber">240,242</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">240</context>
+          <context context-type="linenumber">244</context>
         </context-group>
       </trans-unit>
       <trans-unit id="232202047340644471" datatype="html">
         <source>Storage path: <x id="PH" equiv-text="this.storagePaths.find((sp) =&gt; 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">246,248</context>
+          <context context-type="linenumber">250,252</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">250</context>
+          <context context-type="linenumber">254</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8180755793012580465" datatype="html">
         <source>Tag: <x id="PH" equiv-text="this.tags.find((t) =&gt; 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">254,256</context>
+          <context context-type="linenumber">258,260</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">260</context>
+          <context context-type="linenumber">264</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">264</context>
+          <context context-type="linenumber">268</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">267</context>
+          <context context-type="linenumber">271</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">270</context>
+          <context context-type="linenumber">274</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">273</context>
+          <context context-type="linenumber">277</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">276</context>
+          <context context-type="linenumber">280</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">279</context>
+          <context context-type="linenumber">283</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7210076240260527720" datatype="html">
           <context context-type="linenumber">36</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="3566342898065860218" datatype="html">
+        <source>Last year</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
+          <context context-type="linenumber">14</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="3393387677918927062" datatype="html">
         <source>%s years ago</source>
         <context-group purpose="location">
           <context context-type="linenumber">15</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="4463380307954693363" datatype="html">
+        <source>Last month</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
+          <context context-type="linenumber">19</context>
+        </context-group>
+      </trans-unit>
       <trans-unit id="1158628882375251480" datatype="html">
         <source>%s months ago</source>
         <context-group purpose="location">
index 2f119b0746b1f75134e9597c68f710ef8b51ddae..742dd8e8a3fece6e4697c471ba8c7a2f7320f1af 100644 (file)
     <input class="form-control" placeholder="yyyy-mm-dd"
       [(ngModel)]="atom.value"
       ngbDatepicker
-      #d="ngbDatepicker" />
+      #d="ngbDatepicker"
+      [footerTemplate]="datePickerFooterTemplate" />
     <button class="btn btn-sm btn-outline-secondary rounded-end" (click)="d.toggle()" type="button">
       <i-bs name="calendar-event"></i-bs>
     </button>
+    <ng-template #datePickerFooterTemplate>
+      <div class="btn-group-xs border-top p-2 d-flex">
+        <button type="button" class="btn btn-primary" (click)="atom.value = today; d.close()" i18n>Today</button>
+        <button type="button" class="btn btn-secondary ms-auto" (click)="d.close()" i18n>Close</button>
+      </div>
+    </ng-template>
   } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Float || getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Integer) {
     <input class="w-25 form-control rounded-end" type="number" [(ngModel)]="atom.value" [disabled]="disabled">
   } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.Boolean) {
index 0fa7fe536c58f8fcf2671da48f4b96a110d2fd5d..324fd27a53d4afe8dbd2f008cb7fcfebd40f0adc 100644 (file)
@@ -241,6 +241,8 @@ export class CustomFieldsQueryDropdownComponent extends LoadingComponentWithPerm
 
   customFields: CustomField[] = []
 
+  public readonly today: string = new Date().toISOString().split('T')[0]
+
   constructor(protected customFieldsService: CustomFieldsService) {
     super()
     this.selectionModel = new CustomFieldQueriesModel()
index dcab4606d2f5fc1c888eafe25dddd3bbfd1e293f..c3ff61ba88511ff3f13f20db32bd220601f0052f 100644 (file)
@@ -1,5 +1,5 @@
 <div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions">
-  <button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateBefore || createdDateAfter ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
+  <button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="createdDateTo || createdDateFrom ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled">
     <i-bs width="1em" height="1em" name="calendar-event-fill"></i-bs>
     <div class="d-none d-sm-inline">&nbsp;{{title}}</div>
     <pngx-clearable-badge [selected]="isActive" (cleared)="reset()"></pngx-clearable-badge><span class="visually-hidden">selected</span>
           <div class="list-group-item d-flex p-2" role="menuitem">
 
             <div class="selected-icon">
-              @if (createdDateAfter) {
-                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedAfter()">
+              @if (createdDateFrom) {
+                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedFrom()">
                   <i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
                   <i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
                 </a>
               }
             </div>
             <div class="input-group input-group-sm small ps-1 pe-2">
-              <span class="input-group-text w-25 small text-muted" i18n>After</span>
+              <span class="input-group-text w-25 small text-muted" i18n>From</span>
               <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                maxlength="10" [(ngModel)]="createdDateAfter" ngbDatepicker #createdDateAfterPicker="ngbDatepicker">
-              <button class="btn btn-outline-secondary" (click)="createdDateAfterPicker.toggle()" type="button">
+                maxlength="10" [(ngModel)]="createdDateFrom" ngbDatepicker #createdDateFromPicker="ngbDatepicker" [footerTemplate]="createdFromFooterTemplate">
+              <button class="btn btn-outline-secondary" (click)="createdDateFromPicker.toggle()" type="button">
                 <i-bs width="1em" height="1em" name="calendar"></i-bs>
               </button>
+              <ng-template #createdFromFooterTemplate>
+                <div class="btn-group-xs border-top p-2 d-flex">
+                  <button class="btn btn-primary" (click)="createdDateFrom = today; onChangeDebounce()" i18n>Today</button>
+                  <button class="btn btn-secondary ms-auto" (click)="createdDateFromPicker.close()" i18n>Close</button>
+                </div>
+              </ng-template>
             </div>
 
           </div>
           <div class="list-group-item d-flex p-2" role="menuitem">
 
             <div class="selected-icon">
-              @if (createdDateBefore) {
-                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedBefore()">
+              @if (createdDateTo) {
+                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedTo()">
                   <i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
                   <i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
                 </a>
               }
             </div>
             <div class="input-group input-group-sm small ps-1 pe-2">
-              <span class="input-group-text w-25 small text-muted" i18n>Before</span>
+              <span class="input-group-text w-25 small text-muted" i18n>To</span>
               <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                maxlength="10" [(ngModel)]="createdDateBefore" ngbDatepicker #createdDateBeforePicker="ngbDatepicker">
-              <button class="btn btn-outline-secondary" (click)="createdDateBeforePicker.toggle()" type="button">
+                maxlength="10" [(ngModel)]="createdDateTo" ngbDatepicker #createdDateToPicker="ngbDatepicker" [footerTemplate]="createdToFooterTemplate">
+              <button class="btn btn-outline-secondary" (click)="createdDateToPicker.toggle()" type="button">
                 <i-bs width="1em" height="1em" name="calendar"></i-bs>
               </button>
+              <ng-template #createdToFooterTemplate>
+                <div class="btn-group-xs border-top p-2 d-flex">
+                  <button class="btn btn-primary" (click)="createdDateTo = today; onChangeDebounce()" i18n>Today</button>
+                  <button class="btn btn-secondary ms-auto" (click)="createdDateToPicker.close()" i18n>Close</button>
+                </div>
+              </ng-template>
             </div>
 
           </div>
           <div class="list-group-item d-flex p-2" role="menuitem">
 
             <div class="selected-icon">
-              @if (addedDateAfter) {
-                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedAfter()">
+              @if (addedDateFrom) {
+                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedFrom()">
                   <i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
                   <i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
                 </a>
               }
             </div>
             <div class="input-group input-group-sm small ps-1 pe-2">
-              <span class="input-group-text w-25 small text-muted" i18n>After</span>
+              <span class="input-group-text w-25 small text-muted" i18n>From</span>
               <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                maxlength="10" [(ngModel)]="addedDateAfter" ngbDatepicker #addedDateAfterPicker="ngbDatepicker">
-              <button class="btn btn-outline-secondary" (click)="addedDateAfterPicker.toggle()" type="button">
+                maxlength="10" [(ngModel)]="addedDateFrom" ngbDatepicker #addedDateFromPicker="ngbDatepicker" [footerTemplate]="addedFromFooterTemplate">
+              <button class="btn btn-outline-secondary" (click)="addedDateFromPicker.toggle()" type="button">
                 <i-bs width="1em" height="1em" name="calendar"></i-bs>
               </button>
+              <ng-template #addedFromFooterTemplate>
+                <div class="btn-group-xs border-top p-2 d-flex">
+                  <button class="btn btn-primary" (click)="addedDateFrom = today; onChangeDebounce()" i18n>Today</button>
+                  <button class="btn btn-secondary ms-auto" (click)="addedDateFromPicker.close()" i18n>Close</button>
+                </div>
+              </ng-template>
             </div>
 
           </div>
           <div class="list-group-item d-flex p-2" role="menuitem">
 
             <div class="selected-icon">
-              @if (addedDateBefore) {
-                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedBefore()">
+              @if (addedDateTo) {
+                <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedTo()">
                   <i-bs width="1em" height="1em" name="check" class="variant-unfocused"></i-bs>
                   <i-bs width="1em" height="1em" name="x" class="variant-focused text-primary"></i-bs>
                 </a>
               }
             </div>
             <div class="input-group input-group-sm small ps-1 pe-2">
-              <span class="input-group-text w-25 small text-muted" i18n>Before</span>
+              <span class="input-group-text w-25 small text-muted" i18n>To</span>
               <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                maxlength="10" [(ngModel)]="addedDateBefore" ngbDatepicker #addedDateBeforePicker="ngbDatepicker">
-              <button class="btn btn-outline-secondary" (click)="addedDateBeforePicker.toggle()" type="button">
+                maxlength="10" [(ngModel)]="addedDateTo" ngbDatepicker #addedDateToPicker="ngbDatepicker" [footerTemplate]="addedToFooterTemplate">
+              <button class="btn btn-outline-secondary" (click)="addedDateToPicker.toggle()" type="button">
                 <i-bs width="1em" height="1em" name="calendar"></i-bs>
               </button>
+              <ng-template #addedToFooterTemplate>
+                <div class="btn-group-xs border-top p-2 d-flex">
+                  <button class="btn btn-primary" (click)="addedDateTo = today; onChangeDebounce()" i18n>Today</button>
+                  <button class="btn btn-secondary ms-auto" (click)="addedDateToPicker.close()" i18n>Close</button>
+                </div>
+              </ng-template>
             </div>
 
           </div>
index e101a131d20c8a75553e9f70c764a9eb70237e8b..ebd34b29aa8c4ba2498e8a571d6e40b24f0a1e98 100644 (file)
@@ -41,3 +41,9 @@
     }
   }
 }
+
+.btn-group-xs {
+  > .btn {
+    border-radius: 0.15rem;
+  }
+}
index 10762264a36fcc6ffe38c4e66f7b257e861e1091..1f6ee909e6cc3837500c207495317d92e0bb9200 100644 (file)
@@ -61,7 +61,7 @@ describe('DatesDropdownComponent', () => {
 
   it('should support date input, emit change', fakeAsync(() => {
     let result: string
-    component.createdDateAfterChange.subscribe((date) => (result = date))
+    component.createdDateFromChange.subscribe((date) => (result = date))
     const input: HTMLInputElement = fixture.nativeElement.querySelector('input')
     input.value = '5/30/2023'
     input.dispatchEvent(new Event('change'))
@@ -83,68 +83,68 @@ describe('DatesDropdownComponent', () => {
     let result: DateSelection
     component.datesSet.subscribe((date) => (result = date))
     component.setCreatedRelativeDate(null)
-    component.setCreatedRelativeDate(RelativeDate.LAST_7_DAYS)
+    component.setCreatedRelativeDate(RelativeDate.WITHIN_1_WEEK)
     component.setAddedRelativeDate(null)
-    component.setAddedRelativeDate(RelativeDate.LAST_7_DAYS)
+    component.setAddedRelativeDate(RelativeDate.WITHIN_1_WEEK)
     tick(500)
     expect(result).toEqual({
-      createdAfter: null,
-      createdBefore: null,
-      createdRelativeDateID: RelativeDate.LAST_7_DAYS,
-      addedAfter: null,
-      addedBefore: null,
-      addedRelativeDateID: RelativeDate.LAST_7_DAYS,
+      createdFrom: null,
+      createdTo: null,
+      createdRelativeDateID: RelativeDate.WITHIN_1_WEEK,
+      addedFrom: null,
+      addedTo: null,
+      addedRelativeDateID: RelativeDate.WITHIN_1_WEEK,
     })
   }))
 
   it('should support report if active', () => {
-    component.createdRelativeDate = RelativeDate.LAST_7_DAYS
+    component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK
     expect(component.isActive).toBeTruthy()
     component.createdRelativeDate = null
-    component.createdDateAfter = '2023-05-30'
+    component.createdDateFrom = '2023-05-30'
     expect(component.isActive).toBeTruthy()
-    component.createdDateAfter = null
-    component.createdDateBefore = '2023-05-30'
+    component.createdDateFrom = null
+    component.createdDateTo = '2023-05-30'
     expect(component.isActive).toBeTruthy()
-    component.createdDateBefore = null
+    component.createdDateTo = null
 
-    component.addedRelativeDate = RelativeDate.LAST_7_DAYS
+    component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK
     expect(component.isActive).toBeTruthy()
     component.addedRelativeDate = null
-    component.addedDateAfter = '2023-05-30'
+    component.addedDateFrom = '2023-05-30'
     expect(component.isActive).toBeTruthy()
-    component.addedDateAfter = null
-    component.addedDateBefore = '2023-05-30'
+    component.addedDateFrom = null
+    component.addedDateTo = '2023-05-30'
     expect(component.isActive).toBeTruthy()
-    component.addedDateBefore = null
+    component.addedDateTo = null
 
     expect(component.isActive).toBeFalsy()
   })
 
   it('should support reset', () => {
-    component.createdDateAfter = '2023-05-30'
+    component.createdDateFrom = '2023-05-30'
     component.reset()
-    expect(component.createdDateAfter).toBeNull()
+    expect(component.createdDateFrom).toBeNull()
   })
 
-  it('should support clearAfter', () => {
-    component.createdDateAfter = '2023-05-30'
-    component.clearCreatedAfter()
-    expect(component.createdDateAfter).toBeNull()
+  it('should support clearFrom', () => {
+    component.createdDateFrom = '2023-05-30'
+    component.clearCreatedFrom()
+    expect(component.createdDateFrom).toBeNull()
 
-    component.addedDateAfter = '2023-05-30'
-    component.clearAddedAfter()
-    expect(component.addedDateAfter).toBeNull()
+    component.addedDateFrom = '2023-05-30'
+    component.clearAddedFrom()
+    expect(component.addedDateFrom).toBeNull()
   })
 
-  it('should support clearBefore', () => {
-    component.createdDateBefore = '2023-05-30'
-    component.clearCreatedBefore()
-    expect(component.createdDateBefore).toBeNull()
+  it('should support clearTo', () => {
+    component.createdDateTo = '2023-05-30'
+    component.clearCreatedTo()
+    expect(component.createdDateTo).toBeNull()
 
-    component.addedDateBefore = '2023-05-30'
-    component.clearAddedBefore()
-    expect(component.addedDateBefore).toBeNull()
+    component.addedDateTo = '2023-05-30'
+    component.clearAddedTo()
+    expect(component.addedDateTo).toBeNull()
   })
 
   it('should limit keyboard events', () => {
index 356ba510a5c2e74d605af75a557fa3d76b00553d..e7d506d186756ca3d2922b3aa0fc71993be82933 100644 (file)
@@ -23,19 +23,19 @@ import { popperOptionsReenablePreventOverflow } from 'src/app/utils/popper-optio
 import { ClearableBadgeComponent } from '../clearable-badge/clearable-badge.component'
 
 export interface DateSelection {
-  createdBefore?: string
-  createdAfter?: string
+  createdTo?: string
+  createdFrom?: string
   createdRelativeDateID?: number
-  addedBefore?: string
-  addedAfter?: string
+  addedTo?: string
+  addedFrom?: string
   addedRelativeDateID?: number
 }
 
 export enum RelativeDate {
-  LAST_7_DAYS = 0,
-  LAST_MONTH = 1,
-  LAST_3_MONTHS = 2,
-  LAST_YEAR = 3,
+  WITHIN_1_WEEK = 0,
+  WITHIN_1_MONTH = 1,
+  WITHIN_3_MONTHS = 2,
+  WITHIN_1_YEAR = 3,
 }
 
 @Component({
@@ -63,23 +63,23 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
 
   relativeDates = [
     {
-      id: RelativeDate.LAST_7_DAYS,
-      name: $localize`Last 7 days`,
+      id: RelativeDate.WITHIN_1_WEEK,
+      name: $localize`Within 1 week`,
       date: new Date().setDate(new Date().getDate() - 7),
     },
     {
-      id: RelativeDate.LAST_MONTH,
-      name: $localize`Last month`,
+      id: RelativeDate.WITHIN_1_MONTH,
+      name: $localize`Within 1 month`,
       date: new Date().setMonth(new Date().getMonth() - 1),
     },
     {
-      id: RelativeDate.LAST_3_MONTHS,
-      name: $localize`Last 3 months`,
+      id: RelativeDate.WITHIN_3_MONTHS,
+      name: $localize`Within 3 months`,
       date: new Date().setMonth(new Date().getMonth() - 3),
     },
     {
-      id: RelativeDate.LAST_YEAR,
-      name: $localize`Last year`,
+      id: RelativeDate.WITHIN_1_YEAR,
+      name: $localize`Within 1 year`,
       date: new Date().setFullYear(new Date().getFullYear() - 1),
     },
   ]
@@ -88,16 +88,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
 
   // created
   @Input()
-  createdDateBefore: string
+  createdDateTo: string
 
   @Output()
-  createdDateBeforeChange = new EventEmitter<string>()
+  createdDateToChange = new EventEmitter<string>()
 
   @Input()
-  createdDateAfter: string
+  createdDateFrom: string
 
   @Output()
-  createdDateAfterChange = new EventEmitter<string>()
+  createdDateFromChange = new EventEmitter<string>()
 
   @Input()
   createdRelativeDate: RelativeDate
@@ -107,16 +107,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
 
   // added
   @Input()
-  addedDateBefore: string
+  addedDateTo: string
 
   @Output()
-  addedDateBeforeChange = new EventEmitter<string>()
+  addedDateToChange = new EventEmitter<string>()
 
   @Input()
-  addedDateAfter: string
+  addedDateFrom: string
 
   @Output()
-  addedDateAfterChange = new EventEmitter<string>()
+  addedDateFromChange = new EventEmitter<string>()
 
   @Input()
   addedRelativeDate: RelativeDate
@@ -133,14 +133,16 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
   @Input()
   disabled: boolean = false
 
+  public readonly today: string = new Date().toISOString().split('T')[0]
+
   get isActive(): boolean {
     return (
       this.createdRelativeDate !== null ||
-      this.createdDateAfter?.length > 0 ||
-      this.createdDateBefore?.length > 0 ||
+      this.createdDateFrom?.length > 0 ||
+      this.createdDateTo?.length > 0 ||
       this.addedRelativeDate !== null ||
-      this.addedDateAfter?.length > 0 ||
-      this.addedDateBefore?.length > 0
+      this.addedDateFrom?.length > 0 ||
+      this.addedDateTo?.length > 0
     )
   }
 
@@ -161,42 +163,42 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
   }
 
   reset() {
-    this.createdDateBefore = null
-    this.createdDateAfter = null
+    this.createdDateTo = null
+    this.createdDateFrom = null
     this.createdRelativeDate = null
-    this.addedDateBefore = null
-    this.addedDateAfter = null
+    this.addedDateTo = null
+    this.addedDateFrom = null
     this.addedRelativeDate = null
     this.onChange()
   }
 
   setCreatedRelativeDate(rd: RelativeDate) {
-    this.createdDateBefore = null
-    this.createdDateAfter = null
+    this.createdDateTo = null
+    this.createdDateFrom = null
     this.createdRelativeDate = this.createdRelativeDate == rd ? null : rd
     this.onChange()
   }
 
   setAddedRelativeDate(rd: RelativeDate) {
-    this.addedDateBefore = null
-    this.addedDateAfter = null
+    this.addedDateTo = null
+    this.addedDateFrom = null
     this.addedRelativeDate = this.addedRelativeDate == rd ? null : rd
     this.onChange()
   }
 
   onChange() {
-    this.createdDateBeforeChange.emit(this.createdDateBefore)
-    this.createdDateAfterChange.emit(this.createdDateAfter)
+    this.createdDateToChange.emit(this.createdDateTo)
+    this.createdDateFromChange.emit(this.createdDateFrom)
     this.createdRelativeDateChange.emit(this.createdRelativeDate)
-    this.addedDateBeforeChange.emit(this.addedDateBefore)
-    this.addedDateAfterChange.emit(this.addedDateAfter)
+    this.addedDateToChange.emit(this.addedDateTo)
+    this.addedDateFromChange.emit(this.addedDateFrom)
     this.addedRelativeDateChange.emit(this.addedRelativeDate)
     this.datesSet.emit({
-      createdAfter: this.createdDateAfter,
-      createdBefore: this.createdDateBefore,
+      createdFrom: this.createdDateFrom,
+      createdTo: this.createdDateTo,
       createdRelativeDateID: this.createdRelativeDate,
-      addedAfter: this.addedDateAfter,
-      addedBefore: this.addedDateBefore,
+      addedFrom: this.addedDateFrom,
+      addedTo: this.addedDateTo,
       addedRelativeDateID: this.addedRelativeDate,
     })
   }
@@ -205,30 +207,30 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
     this.createdRelativeDate = null
     this.addedRelativeDate = null
     this.datesSetDebounce$.next({
-      createdAfter: this.createdDateAfter,
-      createdBefore: this.createdDateBefore,
-      addedAfter: this.addedDateAfter,
-      addedBefore: this.addedDateBefore,
+      createdAfter: this.createdDateFrom,
+      createdBefore: this.createdDateTo,
+      addedAfter: this.addedDateFrom,
+      addedBefore: this.addedDateTo,
     })
   }
 
-  clearCreatedBefore() {
-    this.createdDateBefore = null
+  clearCreatedTo() {
+    this.createdDateTo = null
     this.onChange()
   }
 
-  clearCreatedAfter() {
-    this.createdDateAfter = null
+  clearCreatedFrom() {
+    this.createdDateFrom = null
     this.onChange()
   }
 
-  clearAddedBefore() {
-    this.addedDateBefore = null
+  clearAddedTo() {
+    this.addedDateTo = null
     this.onChange()
   }
 
-  clearAddedAfter() {
-    this.addedDateAfter = null
+  clearAddedFrom() {
+    this.addedDateFrom = null
     this.onChange()
   }
 
index 8f386e2c83db12b62084d97ba640107fa8f4ecd0..3221677fcec80753f49809749cdb024201e60ee9 100644 (file)
         <div class="input-group" [class.is-invalid]="error">
           <input #inputField class="form-control" [class.is-invalid]="error" [placeholder]="placeholder" [id]="inputId" maxlength="10"
             (dateSelect)="onChange(value)" (change)="onChange(value)" (keypress)="onKeyPress($event)" (paste)="onPaste($event)"
-            name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled">
+            name="dp" [(ngModel)]="value" ngbDatepicker #datePicker="ngbDatepicker" #datePickerContent="ngModel" [disabled]="disabled" [footerTemplate]="datePickerFooterTemplate">
           <button class="btn btn-outline-secondary calendar" (click)="datePicker.toggle()" type="button" [disabled]="disabled">
             <i-bs width="1.2em" height="1.2em" name="calendar"></i-bs>
           </button>
+          <ng-template #datePickerFooterTemplate>
+            <div class="btn-group-xs border-top p-2 d-flex">
+              <button type="button" class="btn btn-primary" (click)="value = today; onChange(value); datePicker.close()" i18n>Today</button>
+              <button type="button" class="btn btn-secondary ms-auto" (click)="datePicker.close()" i18n>Close</button>
+            </div>
+          </ng-template>
           @if (showFilter) {
             <button class="btn btn-outline-secondary" type="button" (click)="onFilterDocuments()" [disabled]="this.value === null" title="{{ filterButtonTitle }}">
               <i-bs width="1.2em" height="1.2em" name="filter"></i-bs>
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3a39ac88d6ed7fcc5d2cdd3a5b8bf8f9cf52ab02 100644 (file)
@@ -0,0 +1,5 @@
+.btn-group-xs {
+    > .btn {
+      border-radius: 0.15rem;
+    }
+  }
index b266ebfaa3ef9a4b137ba82a2c7eb357f884f60e..176b468f69ef96459f557d28f899669267474f23 100644 (file)
@@ -62,6 +62,8 @@ export class DateComponent
   @Output()
   filterDocuments = new EventEmitter<NgbDateStruct[]>()
 
+  public readonly today: string = new Date().toISOString().split('T')[0]
+
   getSuggestions() {
     return this.suggestions == null
       ? []
index 32c2a1908598e554098d358e73439036414685bb..fcb7bed8fccd9caddee5ef11f2b4f331d44b0e27 100644 (file)
         <pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
           title="Dates" i18n-title
           (datesSet)="updateRules()"
-          [(createdDateBefore)]="dateCreatedBefore"
-          [(createdDateAfter)]="dateCreatedAfter"
+          [(createdDateTo)]="dateCreatedTo"
+          [(createdDateFrom)]="dateCreatedFrom"
           [(createdRelativeDate)]="dateCreatedRelativeDate"
-          [(addedDateBefore)]="dateAddedBefore"
-          [(addedDateAfter)]="dateAddedAfter"
+          [(addedDateTo)]="dateAddedTo"
+          [(addedDateFrom)]="dateAddedFrom"
           [(addedRelativeDate)]="dateAddedRelativeDate">
         </pngx-dates-dropdown>
         <pngx-permissions-filter-dropdown class="flex-fill fade" [class.show]="show"
index 6e5e29400e39fdbf0094590dc98ea7181841cddb..3a5cedccb097b958632391b93a3ab9833b54555c 100644 (file)
@@ -32,6 +32,8 @@ import { DocumentType } from 'src/app/data/document-type'
 import {
   FILTER_ADDED_AFTER,
   FILTER_ADDED_BEFORE,
+  FILTER_ADDED_FROM,
+  FILTER_ADDED_TO,
   FILTER_ASN,
   FILTER_ASN_GT,
   FILTER_ASN_ISNULL,
@@ -39,6 +41,8 @@ import {
   FILTER_CORRESPONDENT,
   FILTER_CREATED_AFTER,
   FILTER_CREATED_BEFORE,
+  FILTER_CREATED_FROM,
+  FILTER_CREATED_TO,
   FILTER_CUSTOM_FIELDS_QUERY,
   FILTER_CUSTOM_FIELDS_TEXT,
   FILTER_DOCUMENT_TYPE,
@@ -465,48 +469,92 @@ describe('FilterEditorComponent', () => {
     ])
   }))
 
-  it('should ingest filter rules for date created after', fakeAsync(() => {
-    expect(component.dateCreatedAfter).toBeNull()
+  it('should ingest filter rules for date created after and adjust date by 1 day', fakeAsync(() => {
+    expect(component.dateCreatedFrom).toBeNull()
     component.filterRules = [
       {
         rule_type: FILTER_CREATED_AFTER,
         value: '2023-05-14',
       },
     ]
-    expect(component.dateCreatedAfter).toEqual('2023-05-14')
+    expect(component.dateCreatedFrom).toEqual('2023-05-15')
   }))
 
-  it('should ingest filter rules for date created before', fakeAsync(() => {
-    expect(component.dateCreatedBefore).toBeNull()
+  it('should ingest filter rules for date created from', fakeAsync(() => {
+    expect(component.dateCreatedFrom).toBeNull()
+    component.filterRules = [
+      {
+        rule_type: FILTER_CREATED_FROM,
+        value: '2023-05-14',
+      },
+    ]
+    expect(component.dateCreatedFrom).toEqual('2023-05-14')
+  }))
+
+  it('should ingest filter rules for date created before and adjust date by 1 day', fakeAsync(() => {
+    expect(component.dateCreatedTo).toBeNull()
     component.filterRules = [
       {
         rule_type: FILTER_CREATED_BEFORE,
         value: '2023-05-14',
       },
     ]
-    expect(component.dateCreatedBefore).toEqual('2023-05-14')
+    expect(component.dateCreatedTo).toEqual('2023-05-13')
+  }))
+
+  it('should ingest filter rules for date created to', fakeAsync(() => {
+    expect(component.dateCreatedTo).toBeNull()
+    component.filterRules = [
+      {
+        rule_type: FILTER_CREATED_TO,
+        value: '2023-05-14',
+      },
+    ]
+    expect(component.dateCreatedTo).toEqual('2023-05-14')
   }))
 
-  it('should ingest filter rules for date added after', fakeAsync(() => {
-    expect(component.dateAddedAfter).toBeNull()
+  it('should ingest filter rules for date added after and adjust date by 1 day', fakeAsync(() => {
+    expect(component.dateAddedFrom).toBeNull()
     component.filterRules = [
       {
         rule_type: FILTER_ADDED_AFTER,
         value: '2023-05-14',
       },
     ]
-    expect(component.dateAddedAfter).toEqual('2023-05-14')
+    expect(component.dateAddedFrom).toEqual('2023-05-15')
+  }))
+
+  it('should ingest filter rules for date added from', fakeAsync(() => {
+    expect(component.dateAddedFrom).toBeNull()
+    component.filterRules = [
+      {
+        rule_type: FILTER_ADDED_FROM,
+        value: '2023-05-14',
+      },
+    ]
+    expect(component.dateAddedFrom).toEqual('2023-05-14')
   }))
 
-  it('should ingest filter rules for date added before', fakeAsync(() => {
-    expect(component.dateAddedBefore).toBeNull()
+  it('should ingest filter rules for date added before and adjust date by 1 day', fakeAsync(() => {
+    expect(component.dateAddedTo).toBeNull()
     component.filterRules = [
       {
         rule_type: FILTER_ADDED_BEFORE,
         value: '2023-05-14',
       },
     ]
-    expect(component.dateAddedBefore).toEqual('2023-05-14')
+    expect(component.dateAddedTo).toEqual('2023-05-13')
+  }))
+
+  it('should ingest filter rules for date added to', fakeAsync(() => {
+    expect(component.dateAddedTo).toBeNull()
+    component.filterRules = [
+      {
+        rule_type: FILTER_ADDED_TO,
+        value: '2023-05-14',
+      },
+    ]
+    expect(component.dateAddedTo).toEqual('2023-05-14')
   }))
 
   it('should ingest filter rules for has all tags', fakeAsync(() => {
@@ -1464,7 +1512,7 @@ describe('FilterEditorComponent', () => {
     ])
   }))
 
-  it('should convert user input to correct filter rules on date created after', fakeAsync(() => {
+  it('should convert user input to correct filter rules on date created from', fakeAsync(() => {
     const dateCreatedDropdown = fixture.debugElement.queryAll(
       By.directive(DatesDropdownComponent)
     )[0]
@@ -1473,18 +1521,18 @@ describe('FilterEditorComponent', () => {
     dateCreatedAfter.nativeElement.value = '05/14/2023'
     // dateCreatedAfter.triggerEventHandler('change')
     // TODO: why isn't ngModel triggering this on change?
-    component.dateCreatedAfter = '2023-05-14'
+    component.dateCreatedFrom = '2023-05-14'
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
-        rule_type: FILTER_CREATED_AFTER,
+        rule_type: FILTER_CREATED_FROM,
         value: '2023-05-14',
       },
     ])
   }))
 
-  it('should convert user input to correct filter rules on date created before', fakeAsync(() => {
+  it('should convert user input to correct filter rules on date created to', fakeAsync(() => {
     const dateCreatedDropdown = fixture.debugElement.queryAll(
       By.directive(DatesDropdownComponent)
     )[0]
@@ -1493,12 +1541,12 @@ describe('FilterEditorComponent', () => {
     dateCreatedBefore.nativeElement.value = '05/14/2023'
     // dateCreatedBefore.triggerEventHandler('change')
     // TODO: why isn't ngModel triggering this on change?
-    component.dateCreatedBefore = '2023-05-14'
+    component.dateCreatedTo = '2023-05-14'
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
-        rule_type: FILTER_CREATED_BEFORE,
+        rule_type: FILTER_CREATED_TO,
         value: '2023-05-14',
       },
     ])
@@ -1578,12 +1626,12 @@ describe('FilterEditorComponent', () => {
     dateAddedAfter.nativeElement.value = '05/14/2023'
     // dateAddedAfter.triggerEventHandler('change')
     // TODO: why isn't ngModel triggering this on change?
-    component.dateAddedAfter = '2023-05-14'
+    component.dateAddedFrom = '2023-05-14'
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
-        rule_type: FILTER_ADDED_AFTER,
+        rule_type: FILTER_ADDED_FROM,
         value: '2023-05-14',
       },
     ])
@@ -1598,12 +1646,12 @@ describe('FilterEditorComponent', () => {
     dateAddedBefore.nativeElement.value = '05/14/2023'
     // dateAddedBefore.triggerEventHandler('change')
     // TODO: why isn't ngModel triggering this on change?
-    component.dateAddedBefore = '2023-05-14'
+    component.dateAddedTo = '2023-05-14'
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
-        rule_type: FILTER_ADDED_BEFORE,
+        rule_type: FILTER_ADDED_TO,
         value: '2023-05-14',
       },
     ])
index 6e9a3fb7d69cab3dbe0ec331113df0390b24ad7a..2179efaf478d289d4ce51e1e2a3feeb76d14db46 100644 (file)
@@ -38,6 +38,8 @@ import { FilterRule } from 'src/app/data/filter-rule'
 import {
   FILTER_ADDED_AFTER,
   FILTER_ADDED_BEFORE,
+  FILTER_ADDED_FROM,
+  FILTER_ADDED_TO,
   FILTER_ASN,
   FILTER_ASN_GT,
   FILTER_ASN_ISNULL,
@@ -45,6 +47,8 @@ import {
   FILTER_CORRESPONDENT,
   FILTER_CREATED_AFTER,
   FILTER_CREATED_BEFORE,
+  FILTER_CREATED_FROM,
+  FILTER_CREATED_TO,
   FILTER_CUSTOM_FIELDS_QUERY,
   FILTER_CUSTOM_FIELDS_TEXT,
   FILTER_DOCUMENT_TYPE,
@@ -133,19 +137,19 @@ const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:\[([^\]]+)\]/g
 const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:\[([^\]]+)\]/g
 const RELATIVE_DATE_QUERYSTRINGS = [
   {
-    relativeDate: RelativeDate.LAST_7_DAYS,
+    relativeDate: RelativeDate.WITHIN_1_WEEK,
     dateQuery: '-1 week to now',
   },
   {
-    relativeDate: RelativeDate.LAST_MONTH,
+    relativeDate: RelativeDate.WITHIN_1_MONTH,
     dateQuery: '-1 month to now',
   },
   {
-    relativeDate: RelativeDate.LAST_3_MONTHS,
+    relativeDate: RelativeDate.WITHIN_3_MONTHS,
     dateQuery: '-3 month to now',
   },
   {
-    relativeDate: RelativeDate.LAST_YEAR,
+    relativeDate: RelativeDate.WITHIN_1_YEAR,
     dateQuery: '-1 year to now',
   },
 ]
@@ -349,10 +353,10 @@ export class FilterEditorComponent
   storagePathSelectionModel = new FilterableDropdownSelectionModel()
   customFieldQueriesModel = new CustomFieldQueriesModel()
 
-  dateCreatedBefore: string
-  dateCreatedAfter: string
-  dateAddedBefore: string
-  dateAddedAfter: string
+  dateCreatedTo: string
+  dateCreatedFrom: string
+  dateAddedTo: string
+  dateAddedFrom: string
   dateCreatedRelativeDate: RelativeDate
   dateAddedRelativeDate: RelativeDate
 
@@ -385,10 +389,10 @@ export class FilterEditorComponent
     this.customFieldQueriesModel.clear(false)
     this._textFilter = null
     this._moreLikeId = null
-    this.dateAddedBefore = null
-    this.dateAddedAfter = null
-    this.dateCreatedBefore = null
-    this.dateCreatedAfter = null
+    this.dateAddedTo = null
+    this.dateAddedFrom = null
+    this.dateCreatedTo = null
+    this.dateCreatedFrom = null
     this.dateCreatedRelativeDate = null
     this.dateAddedRelativeDate = null
     this.textFilterModifier = TEXT_FILTER_MODIFIER_EQUALS
@@ -458,16 +462,40 @@ export class FilterEditorComponent
           })
           break
         case FILTER_CREATED_AFTER:
-          this.dateCreatedAfter = rule.value
+          // Old rules require adjusting date by a day
+          const createdAfter = new Date(rule.value)
+          createdAfter.setDate(createdAfter.getDate() + 1)
+          this.dateCreatedFrom = createdAfter.toISOString().split('T')[0]
           break
         case FILTER_CREATED_BEFORE:
-          this.dateCreatedBefore = rule.value
+          // Old rules require adjusting date by a day
+          const createdBefore = new Date(rule.value)
+          createdBefore.setDate(createdBefore.getDate() - 1)
+          this.dateCreatedTo = createdBefore.toISOString().split('T')[0]
           break
         case FILTER_ADDED_AFTER:
-          this.dateAddedAfter = rule.value
+          // Old rules require adjusting date by a day
+          const addedAfter = new Date(rule.value)
+          addedAfter.setDate(addedAfter.getDate() + 1)
+          this.dateAddedFrom = addedAfter.toISOString().split('T')[0]
           break
         case FILTER_ADDED_BEFORE:
-          this.dateAddedBefore = rule.value
+          // Old rules require adjusting date by a day
+          const addedBefore = new Date(rule.value)
+          addedBefore.setDate(addedBefore.getDate() - 1)
+          this.dateAddedTo = addedBefore.toISOString().split('T')[0]
+          break
+        case FILTER_CREATED_FROM:
+          this.dateCreatedFrom = rule.value
+          break
+        case FILTER_CREATED_TO:
+          this.dateCreatedTo = rule.value
+          break
+        case FILTER_ADDED_FROM:
+          this.dateAddedFrom = rule.value
+          break
+        case FILTER_ADDED_TO:
+          this.dateAddedTo = rule.value
           break
         case FILTER_HAS_TAGS_ALL:
           this.tagSelectionModel.logicalOperator = LogicalOperator.And
@@ -814,28 +842,28 @@ export class FilterEditorComponent
         value: JSON.stringify(queries[0]),
       })
     }
-    if (this.dateCreatedBefore) {
+    if (this.dateCreatedTo) {
       filterRules.push({
-        rule_type: FILTER_CREATED_BEFORE,
-        value: this.dateCreatedBefore,
+        rule_type: FILTER_CREATED_TO,
+        value: this.dateCreatedTo,
       })
     }
-    if (this.dateCreatedAfter) {
+    if (this.dateCreatedFrom) {
       filterRules.push({
-        rule_type: FILTER_CREATED_AFTER,
-        value: this.dateCreatedAfter,
+        rule_type: FILTER_CREATED_FROM,
+        value: this.dateCreatedFrom,
       })
     }
-    if (this.dateAddedBefore) {
+    if (this.dateAddedTo) {
       filterRules.push({
-        rule_type: FILTER_ADDED_BEFORE,
-        value: this.dateAddedBefore,
+        rule_type: FILTER_ADDED_TO,
+        value: this.dateAddedTo,
       })
     }
-    if (this.dateAddedAfter) {
+    if (this.dateAddedFrom) {
       filterRules.push({
-        rule_type: FILTER_ADDED_AFTER,
-        value: this.dateAddedAfter,
+        rule_type: FILTER_ADDED_FROM,
+        value: this.dateAddedFrom,
       })
     }
     if (
index 1c6b1cdf8551235c5e84da254bbb3889fab6b641..dd9d8731afce7426a469df77b93591a3a1bd51b6 100644 (file)
@@ -36,6 +36,11 @@ export const FILTER_CREATED_DAY = 12
 export const FILTER_ADDED_BEFORE = 13
 export const FILTER_ADDED_AFTER = 14
 
+export const FILTER_CREATED_TO = 43
+export const FILTER_CREATED_FROM = 44
+export const FILTER_ADDED_TO = 45
+export const FILTER_ADDED_FROM = 46
+
 export const FILTER_MODIFIED_BEFORE = 15
 export const FILTER_MODIFIED_AFTER = 16
 
@@ -179,6 +184,18 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
     datatype: 'date',
     multi: false,
   },
+  {
+    id: FILTER_CREATED_TO,
+    filtervar: 'created__date__lte',
+    datatype: 'date',
+    multi: false,
+  },
+  {
+    id: FILTER_CREATED_FROM,
+    filtervar: 'created__date__gte',
+    datatype: 'date',
+    multi: false,
+  },
   {
     id: FILTER_CREATED_YEAR,
     filtervar: 'created__year',
@@ -210,6 +227,18 @@ export const FILTER_RULE_TYPES: FilterRuleType[] = [
     datatype: 'date',
     multi: false,
   },
+  {
+    id: FILTER_ADDED_TO,
+    filtervar: 'added__date__lte',
+    datatype: 'date',
+    multi: false,
+  },
+  {
+    id: FILTER_ADDED_FROM,
+    filtervar: 'added__date__gte',
+    datatype: 'date',
+    multi: false,
+  },
   {
     id: FILTER_MODIFIED_BEFORE,
     filtervar: 'modified__date__lt',
index 185ba7b6fbe7ac7fe4f6f978df5e603960cfefdd..142f3f519f3b24003ec57324306f3b57c44e1350 100644 (file)
@@ -41,7 +41,19 @@ from documents.models import Tag
 CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"]
 ID_KWARGS = ["in", "exact"]
 INT_KWARGS = ["exact", "gt", "gte", "lt", "lte", "isnull"]
-DATE_KWARGS = ["year", "month", "day", "date__gt", "gt", "date__lt", "lt"]
+DATE_KWARGS = [
+    "year",
+    "month",
+    "day",
+    "date__gt",
+    "date__gte",
+    "gt",
+    "gte",
+    "date__lt",
+    "date__lte",
+    "lt",
+    "lte",
+]
 
 CUSTOM_FIELD_QUERY_MAX_DEPTH = 10
 CUSTOM_FIELD_QUERY_MAX_ATOMS = 20
diff --git a/src/documents/migrations/1062_alter_savedviewfilterrule_rule_type.py b/src/documents/migrations/1062_alter_savedviewfilterrule_rule_type.py
new file mode 100644 (file)
index 0000000..0b0e3cb
--- /dev/null
@@ -0,0 +1,69 @@
+# Generated by Django 5.1.4 on 2025-02-06 05:54
+
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("documents", "1061_workflowactionwebhook_as_json"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="savedviewfilterrule",
+            name="rule_type",
+            field=models.PositiveIntegerField(
+                choices=[
+                    (0, "title contains"),
+                    (1, "content contains"),
+                    (2, "ASN is"),
+                    (3, "correspondent is"),
+                    (4, "document type is"),
+                    (5, "is in inbox"),
+                    (6, "has tag"),
+                    (7, "has any tag"),
+                    (8, "created before"),
+                    (9, "created after"),
+                    (10, "created year is"),
+                    (11, "created month is"),
+                    (12, "created day is"),
+                    (13, "added before"),
+                    (14, "added after"),
+                    (15, "modified before"),
+                    (16, "modified after"),
+                    (17, "does not have tag"),
+                    (18, "does not have ASN"),
+                    (19, "title or content contains"),
+                    (20, "fulltext query"),
+                    (21, "more like this"),
+                    (22, "has tags in"),
+                    (23, "ASN greater than"),
+                    (24, "ASN less than"),
+                    (25, "storage path is"),
+                    (26, "has correspondent in"),
+                    (27, "does not have correspondent in"),
+                    (28, "has document type in"),
+                    (29, "does not have document type in"),
+                    (30, "has storage path in"),
+                    (31, "does not have storage path in"),
+                    (32, "owner is"),
+                    (33, "has owner in"),
+                    (34, "does not have owner"),
+                    (35, "does not have owner in"),
+                    (36, "has custom field value"),
+                    (37, "is shared by me"),
+                    (38, "has custom fields"),
+                    (39, "has custom field in"),
+                    (40, "does not have custom field in"),
+                    (41, "does not have custom field"),
+                    (42, "custom fields query"),
+                    (43, "created to"),
+                    (44, "created from"),
+                    (45, "added to"),
+                    (46, "added from"),
+                ],
+                verbose_name="rule type",
+            ),
+        ),
+    ]
index 79856b83701d4d1af8bb1687b58fe571ca05ccfd..e7d866e2428d4c39f8e50edfa71deceb6e7ef56e 100644 (file)
@@ -522,6 +522,10 @@ class SavedViewFilterRule(models.Model):
         (40, _("does not have custom field in")),
         (41, _("does not have custom field")),
         (42, _("custom fields query")),
+        (43, _("created to")),
+        (44, _("created from")),
+        (45, _("added to")),
+        (46, _("added from")),
     ]
 
     saved_view = models.ForeignKey(