]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: reorganize dates dropdown, add more relative options (#9307)
authorshamoon <4887959+shamoon@users.noreply.github.com>
Wed, 5 Mar 2025 20:48:42 +0000 (12:48 -0800)
committerGitHub <noreply@github.com>
Wed, 5 Mar 2025 20:48:42 +0000 (12:48 -0800)
src-ui/e2e/document-list/document-list.spec.ts
src-ui/messages.xlf
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/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

index cd1a4c54e7ecf38c5eb20ec166e6d5eba68e9e06..45857bb09ff1daa82ade7520b56855820ef44c1e 100644 (file)
@@ -83,10 +83,17 @@ 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: 'Within 3 months' }).first().click()
+  await page.locator('.ng-arrow-wrapper').first().click()
+  await page.getByRole('option', { name: 'Within 3 months' }).click()
   await expect(page.locator('pngx-document-list')).toHaveText(/one document/i)
-  await page.getByRole('menuitem', { name: 'Within 3 months' }).first().click()
-  await page.getByLabel('Datesselected').getByRole('button').first().click()
+  await page
+    .getByRole('menuitem', { name: 'Relative dates' })
+    .locator('span')
+    .first()
+    .click()
+  await page.getByRole('option', { name: 'Within 3 months' }).click()
+  await page.getByLabel('Dates selected').locator('button').first().click()
+  await page.getByLabel('Dates selected').locator('button').first().click()
   await page.getByRole('combobox', { name: 'Select month' }).selectOption('12')
   await page.getByRole('combobox', { name: 'Select year' }).selectOption('2022')
   await page.getByText('11', { exact: true }).click()
index 1649d61002fddfb156ba73ecb4a8ee1e449dc356..2f6a515bec7fc6adcb1f21e37755fcc920d485ff 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">173</context>
+          <context context-type="linenumber">193</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8508424367627989968" datatype="html">
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
-          <context context-type="linenumber">105</context>
+          <context context-type="linenumber">106</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/manage/mail/mail.component.html</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">11</context>
+          <context context-type="linenumber">8</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-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 context-type="linenumber">52</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</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">128</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/dates-dropdown/dates-dropdown.component.ts</context>
+          <context context-type="linenumber">103</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>
         <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 context-type="linenumber">53</context>
         </context-group>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</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 context-type="linenumber">129</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">168</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="6052766076365105714" datatype="html">
-        <source>now</source>
+      <trans-unit id="6312759212949884929" datatype="html">
+        <source>Relative dates</source>
         <context-group purpose="location">
           <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
           <context context-type="linenumber">25</context>
           <context context-type="linenumber">101</context>
         </context-group>
       </trans-unit>
+      <trans-unit id="6052766076365105714" datatype="html">
+        <source>now</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.html</context>
+          <context context-type="linenumber">29</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">105</context>
+        </context-group>
+      </trans-unit>
       <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 context-type="linenumber">44</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">118</context>
+          <context context-type="linenumber">120</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1640609344969975994" 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">86</context>
+          <context context-type="linenumber">84</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>
         <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 context-type="linenumber">73</context>
         </context-group>
       </trans-unit>
       <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 context-type="linenumber">78</context>
         </context-group>
       </trans-unit>
       <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 context-type="linenumber">83</context>
         </context-group>
       </trans-unit>
       <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 context-type="linenumber">88</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="8462417627724236320" datatype="html">
+        <source>This 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">93</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="842657237693374355" datatype="html">
+        <source>This 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">98</context>
+        </context-group>
+      </trans-unit>
+      <trans-unit id="4498682414491138092" datatype="html">
+        <source>Yesterday</source>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/components/common/dates-dropdown/dates-dropdown.component.ts</context>
+          <context context-type="linenumber">108</context>
+        </context-group>
+        <context-group purpose="location">
+          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
+          <context context-type="linenumber">29</context>
         </context-group>
       </trans-unit>
       <trans-unit id="8743659855412792665" 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">160</context>
+          <context context-type="linenumber">180</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">168</context>
+          <context context-type="linenumber">188</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.html</context>
-          <context context-type="linenumber">111</context>
+          <context context-type="linenumber">112</context>
         </context-group>
       </trans-unit>
       <trans-unit id="1559883523769732271" 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">165</context>
+          <context context-type="linenumber">185</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">163</context>
+          <context context-type="linenumber">183</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 context-type="linenumber">190</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">179</context>
+          <context context-type="linenumber">199</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">185</context>
+          <context context-type="linenumber">205</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">189</context>
+          <context context-type="linenumber">209</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">193</context>
+          <context context-type="linenumber">213</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">197</context>
+          <context context-type="linenumber">217</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">201</context>
+          <context context-type="linenumber">221</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">233,235</context>
+          <context context-type="linenumber">253,255</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">237</context>
+          <context context-type="linenumber">257</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">243,245</context>
+          <context context-type="linenumber">263,265</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">247</context>
+          <context context-type="linenumber">267</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">253,255</context>
+          <context context-type="linenumber">273,275</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">257</context>
+          <context context-type="linenumber">277</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">261,263</context>
+          <context context-type="linenumber">281,283</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">267</context>
+          <context context-type="linenumber">287</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">271</context>
+          <context context-type="linenumber">291</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">274</context>
+          <context context-type="linenumber">294</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">277</context>
+          <context context-type="linenumber">297</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">280</context>
+          <context context-type="linenumber">300</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">283</context>
+          <context context-type="linenumber">303</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">286</context>
+          <context context-type="linenumber">306</context>
         </context-group>
       </trans-unit>
       <trans-unit id="7210076240260527720" datatype="html">
           <context context-type="linenumber">25</context>
         </context-group>
       </trans-unit>
-      <trans-unit id="4498682414491138092" datatype="html">
-        <source>Yesterday</source>
-        <context-group purpose="location">
-          <context context-type="sourcefile">src/app/pipes/custom-date.pipe.ts</context>
-          <context context-type="linenumber">29</context>
-        </context-group>
-      </trans-unit>
       <trans-unit id="5601594741748068208" datatype="html">
         <source>%s days ago</source>
         <context-group purpose="location">
index c3ff61ba88511ff3f13f20db32bd220601f0052f..86b43f73128546ba7961a8cb3edbb49143075f66 100644 (file)
-<div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions">
+<div class="btn-group w-100" ngbDropdown role="group" [popperOptions]="popperOptions" [placement]="placement">
   <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>
   </button>
   <div class="dropdown-menu date-dropdown shadow p-2" ngbDropdownMenu attr.aria-labelledby="dropdown{{title}}">
-    <div class="row d-flex">
-      <div class="col border-end">
-        <div class="list-group list-group-flush">
-          <h6 class="dropdown-header border-bottom" i18n>Created</h6>
-          @for (rd of relativeDates; track rd) {
-            <button class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setCreatedRelativeDate(rd.id)">
-              <div class="selected-icon">
-                @if (createdRelativeDate === rd.id) {
-                  <i-bs width="1em" height="1em" name="check"></i-bs>
-                }
-              </div>
-              <div class="d-flex justify-content-between w-100 align-items-center ps-2">
-                <div class="pe-4">
-                  {{rd.name}}
-                </div>
-                <div class="text-muted small pe-2">
-                  <span class="small">
-                    {{ rd.date | customDate:'mediumDate' }} &ndash; <ng-container i18n>now</ng-container>
-                  </span>
-                </div>
-              </div>
-            </button>
+    <h6 class="dropdown-header border-bottom" i18n>Created</h6>
+    <div class="list-group list-group-flush">
+      <div class="list-group-item d-flex p-2 select-item" role="menuitem">
+        <div class="selected-icon">
+          @if (createdRelativeDate) {
+            <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearCreatedRelativeDate()">
+              <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 class="list-group-item d-flex p-2" role="menuitem">
-
-            <div class="selected-icon">
-              @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>From</span>
-              <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                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 (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>To</span>
-              <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
-                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>
+        <div class="input-group input-group-sm small ps-1 pe-2">
+          <ng-select class="w-100" name="createdRelativeDate"
+          [items]="relativeDates" [(ngModel)]="createdRelativeDate"
+          bindValue="id"
+          bindLabel="name"
+          clearable="false"
+          placeholder="Relative dates"
+          i18n-placeholder
+          (change)="onSetCreatedRelativeDate($event)">
+          <ng-template ng-option-tmp let-item="item">
+            <div class="d-flex">{{ item.name }}<span class="ms-auto text-muted small">{{ item.date | customDate:'mediumDate' }} &ndash; <ng-container i18n>now</ng-container></span></div>
+          </ng-template>
+          </ng-select>
         </div>
       </div>
-      <div class="col">
-        <h6 class="dropdown-header border-bottom" i18n>Added</h6>
-        <div class="list-group list-group-flush">
-          @for (rd of relativeDates; track rd) {
-            <button class="list-group-item small list-goup list-group-item-action d-flex p-2" role="menuitem" (click)="setAddedRelativeDate(rd.id)">
-              <div class="selected-icon">
-                @if (addedRelativeDate === rd.id) {
-                  <i-bs width="1em" height="1em" name="check"></i-bs>
-                }
-              </div>
-              <div class="d-flex justify-content-between w-100 align-items-center ps-2">
-                <div class="pe-4">
-                  {{rd.name}}
-                </div>
-                <div class="text-muted small pe-2">
-                  <span class="small">
-                    {{ rd.date | customDate:'mediumDate' }} &ndash; <ng-container i18n>now</ng-container>
-                  </span>
-                </div>
-              </div>
-            </button>
+      <div class="list-group-item d-flex p-2" role="menuitem">
+        <div class="selected-icon">
+          @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 class="list-group-item d-flex p-2" role="menuitem">
-
-            <div class="selected-icon">
-              @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>From</span>
+          <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
+            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>
-            <div class="input-group input-group-sm small ps-1 pe-2">
-              <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)]="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>
+          </ng-template>
+        </div>
+      </div>
+      <div class="list-group-item d-flex p-2" role="menuitem">
+        <div class="selected-icon">
+          @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>To</span>
+          <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
+            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 (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>
+    <h6 class="dropdown-header border-bottom" i18n>Added</h6>
+    <div class="list-group list-group-flush">
+      <div class="list-group-item d-flex p-2 select-item" role="menuitem">
+        <div class="selected-icon">
+          @if (addedRelativeDate) {
+            <a class="text-light focus-variants" href="javascript:void(0)" (click)="clearAddedRelativeDate()">
+              <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">
+          <ng-select class="w-100" name="addedRelativeDate"
+            [items]="relativeDates" [(ngModel)]="addedRelativeDate"
+            bindValue="id"
+            bindLabel="name"
+            clearable="false"
+            placeholder="Relative dates"
+            i18n-placeholder
+            (change)="onSetAddedRelativeDate($event)">
+            <ng-template ng-option-tmp let-item="item">
+              <div class="d-flex">{{ item.name }}<span class="ms-auto text-muted small">{{ item.date | customDate:'mediumDate' }} &ndash; <ng-container i18n>now</ng-container></span></div>
+            </ng-template>
+          </ng-select>
+        </div>
+      </div>
+      <div class="list-group-item d-flex p-2" role="menuitem">
+        <div class="selected-icon">
+          @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>From</span>
+          <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
+            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>
-            <div class="input-group input-group-sm small ps-1 pe-2">
-              <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)]="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>
+          </ng-template>
+        </div>
+      </div>
+      <div class="list-group-item d-flex p-2" role="menuitem">
+        <div class="selected-icon">
+          @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>To</span>
+          <input class="form-control small" [placeholder]="datePlaceHolder" (dateSelect)="onChangeDebounce()" (change)="onChangeDebounce()" (keypress)="onKeyPress($event)"
+            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>
-
-          </div>
+          </ng-template>
         </div>
       </div>
     </div>
index ebd34b29aa8c4ba2498e8a571d6e40b24f0a1e98..616835b3a709a3081ca1ac6a23f0f087d01671d0 100644 (file)
@@ -1,16 +1,7 @@
 .date-dropdown {
+  --bs-dropdown-min-width: 22rem;
   white-space: nowrap;
 
-  @media(min-width: 768px) {
-    --bs-dropdown-min-width: 40rem;
-  }
-
-  @media screen and (max-width: 767px) {
-    .border-end {
-      border: none !important;
-    }
-  }
-
   .btn-link {
     line-height: 1;
   }
   min-height: 1em;
 }
 
+.select-item .selected-icon {
+  line-height: 2em;
+}
+
 .input-group-sm {
   .form-control {
     font-size: 0.875rem;
index 1f6ee909e6cc3837500c207495317d92e0bb9200..ee99a726bf2e1c424b9ba822ffacc42fb9520a98 100644 (file)
@@ -82,10 +82,12 @@ describe('DatesDropdownComponent', () => {
   it('should support relative dates', fakeAsync(() => {
     let result: DateSelection
     component.datesSet.subscribe((date) => (result = date))
-    component.setCreatedRelativeDate(null)
-    component.setCreatedRelativeDate(RelativeDate.WITHIN_1_WEEK)
-    component.setAddedRelativeDate(null)
-    component.setAddedRelativeDate(RelativeDate.WITHIN_1_WEEK)
+    component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK // normally set by ngModel binding in dropdown
+    component.onSetCreatedRelativeDate({
+      id: RelativeDate.WITHIN_1_WEEK,
+    } as any)
+    component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK // normally set by ngModel binding in dropdown
+    component.onSetAddedRelativeDate({ id: RelativeDate.WITHIN_1_WEEK } as any)
     tick(500)
     expect(result).toEqual({
       createdFrom: null,
@@ -147,8 +149,19 @@ describe('DatesDropdownComponent', () => {
     expect(component.addedDateTo).toBeNull()
   })
 
+  it('should support clearRelativeDate', () => {
+    component.createdRelativeDate = RelativeDate.WITHIN_1_WEEK
+    component.clearCreatedRelativeDate()
+    expect(component.createdRelativeDate).toBeNull()
+
+    component.addedRelativeDate = RelativeDate.WITHIN_1_WEEK
+    component.clearAddedRelativeDate()
+    expect(component.addedRelativeDate).toBeNull()
+  })
+
   it('should limit keyboard events', () => {
-    const input: HTMLInputElement = fixture.nativeElement.querySelector('input')
+    const input: HTMLInputElement =
+      fixture.nativeElement.querySelector('input.form-control')
     let event: KeyboardEvent = new KeyboardEvent('keypress', {
       key: '9',
     })
@@ -163,4 +176,19 @@ describe('DatesDropdownComponent', () => {
     input.dispatchEvent(event)
     expect(eventSpy).toHaveBeenCalled()
   })
+
+  it('should support debounce', fakeAsync(() => {
+    let result: DateSelection
+    component.datesSet.subscribe((date) => (result = date))
+    component.onChangeDebounce()
+    tick(500)
+    expect(result).toEqual({
+      createdFrom: null,
+      createdTo: null,
+      createdRelativeDateID: null,
+      addedFrom: null,
+      addedTo: null,
+      addedRelativeDateID: null,
+    })
+  }))
 })
index 50565aaa28a300347810eb23171dc4572f995593..c220262a4ddaa57ce55d83636ccef0c90498a016 100644 (file)
@@ -13,6 +13,7 @@ import {
   NgbDatepickerModule,
   NgbDropdownModule,
 } from '@ng-bootstrap/ng-bootstrap'
+import { NgSelectModule } from '@ng-select/ng-select'
 import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
 import { Subject, Subscription } from 'rxjs'
 import { debounceTime } from 'rxjs/operators'
@@ -32,10 +33,14 @@ export interface DateSelection {
 }
 
 export enum RelativeDate {
-  WITHIN_1_WEEK = 0,
-  WITHIN_1_MONTH = 1,
-  WITHIN_3_MONTHS = 2,
-  WITHIN_1_YEAR = 3,
+  WITHIN_1_WEEK = 1,
+  WITHIN_1_MONTH = 2,
+  WITHIN_3_MONTHS = 3,
+  WITHIN_1_YEAR = 4,
+  THIS_YEAR = 5,
+  THIS_MONTH = 6,
+  TODAY = 7,
+  YESTERDAY = 8,
 }
 
 @Component({
@@ -49,6 +54,7 @@ export enum RelativeDate {
     NgxBootstrapIconsModule,
     NgbDatepickerModule,
     NgbDropdownModule,
+    NgSelectModule,
     FormsModule,
     ReactiveFormsModule,
     NgClass,
@@ -82,44 +88,64 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
       name: $localize`Within 1 year`,
       date: new Date().setFullYear(new Date().getFullYear() - 1),
     },
+    {
+      id: RelativeDate.THIS_YEAR,
+      name: $localize`This year`,
+      date: new Date('1/1/' + new Date().getFullYear()),
+    },
+    {
+      id: RelativeDate.THIS_MONTH,
+      name: $localize`This month`,
+      date: new Date().setDate(1),
+    },
+    {
+      id: RelativeDate.TODAY,
+      name: $localize`Today`,
+      date: new Date().setHours(0, 0, 0, 0),
+    },
+    {
+      id: RelativeDate.YESTERDAY,
+      name: $localize`Yesterday`,
+      date: new Date().setDate(new Date().getDate() - 1),
+    },
   ]
 
   datePlaceHolder: string
 
   // created
   @Input()
-  createdDateTo: string
+  createdDateTo: string = null
 
   @Output()
   createdDateToChange = new EventEmitter<string>()
 
   @Input()
-  createdDateFrom: string
+  createdDateFrom: string = null
 
   @Output()
   createdDateFromChange = new EventEmitter<string>()
 
   @Input()
-  createdRelativeDate: RelativeDate
+  createdRelativeDate: RelativeDate = null
 
   @Output()
   createdRelativeDateChange = new EventEmitter<number>()
 
   // added
   @Input()
-  addedDateTo: string
+  addedDateTo: string = null
 
   @Output()
   addedDateToChange = new EventEmitter<string>()
 
   @Input()
-  addedDateFrom: string
+  addedDateFrom: string = null
 
   @Output()
   addedDateFromChange = new EventEmitter<string>()
 
   @Input()
-  addedRelativeDate: RelativeDate
+  addedRelativeDate: RelativeDate = null
 
   @Output()
   addedRelativeDateChange = new EventEmitter<number>()
@@ -133,6 +159,9 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
   @Input()
   disabled: boolean = false
 
+  @Input()
+  placement: string = 'bottom-start'
+
   public readonly today: string = new Date().toISOString().split('T')[0]
 
   get isActive(): boolean {
@@ -172,17 +201,17 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
     this.onChange()
   }
 
-  setCreatedRelativeDate(rd: RelativeDate) {
+  onSetCreatedRelativeDate(rd: { id: number; name: string; date: number }) {
+    // createdRelativeDate is set by ngModel
     this.createdDateTo = null
     this.createdDateFrom = null
-    this.createdRelativeDate = this.createdRelativeDate == rd ? null : rd
     this.onChange()
   }
 
-  setAddedRelativeDate(rd: RelativeDate) {
+  onSetAddedRelativeDate(rd: { id: number; name: string; date: number }) {
+    // addedRelativeDate is set by ngModel
     this.addedDateTo = null
     this.addedDateFrom = null
-    this.addedRelativeDate = this.addedRelativeDate == rd ? null : rd
     this.onChange()
   }
 
@@ -224,6 +253,11 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
     this.onChange()
   }
 
+  clearCreatedRelativeDate() {
+    this.createdRelativeDate = null
+    this.onChange()
+  }
+
   clearAddedTo() {
     this.addedDateTo = null
     this.onChange()
@@ -234,6 +268,11 @@ export class DatesDropdownComponent implements OnInit, OnDestroy {
     this.onChange()
   }
 
+  clearAddedRelativeDate() {
+    this.addedRelativeDate = null
+    this.onChange()
+  }
+
   // prevent chars other than numbers and separators
   onKeyPress(event: KeyboardEvent) {
     if ('Enter' !== event.key && !/[0-9,\.\/-]+/.test(event.key)) {
index fcb7bed8fccd9caddee5ef11f2b4f331d44b0e27..f8d346cba67f54e0a703c585d6cae90a97e9b881 100644 (file)
@@ -93,6 +93,7 @@
         }
         <pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
           title="Dates" i18n-title
+          placement="bottom-end"
           (datesSet)="updateRules()"
           [(createdDateTo)]="dateCreatedTo"
           [(createdDateFrom)]="dateCreatedFrom"
index c4528637b6dfc832d9ffcb60cf409e6ba86a63aa..58524fa99712f22847f92beb2ecf3af09eb1988f 100644 (file)
@@ -96,7 +96,10 @@ import {
 import { environment } from 'src/environments/environment'
 import { ClearableBadgeComponent } from '../../common/clearable-badge/clearable-badge.component'
 import { CustomFieldsQueryDropdownComponent } from '../../common/custom-fields-query-dropdown/custom-fields-query-dropdown.component'
-import { DatesDropdownComponent } from '../../common/dates-dropdown/dates-dropdown.component'
+import {
+  DatesDropdownComponent,
+  RelativeDate,
+} from '../../common/dates-dropdown/dates-dropdown.component'
 import {
   FilterableDropdownComponent,
   Intersection,
@@ -422,7 +425,7 @@ describe('FilterEditorComponent', () => {
         value: 'created:[-1 week to now]',
       },
     ]
-    expect(component.dateCreatedRelativeDate).toEqual(0) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
+    expect(component.dateCreatedRelativeDate).toEqual(1) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
     expect(component.textFilter).toBeNull()
   }))
 
@@ -434,7 +437,7 @@ describe('FilterEditorComponent', () => {
         value: 'added:[-1 week to now]',
       },
     ]
-    expect(component.dateAddedRelativeDate).toEqual(0) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
+    expect(component.dateAddedRelativeDate).toEqual(1) // RELATIVE_DATE_QUERYSTRINGS['-1 week to now']
     expect(component.textFilter).toBeNull()
   }))
 
@@ -1587,10 +1590,8 @@ describe('FilterEditorComponent', () => {
     const dateCreatedDropdown = fixture.debugElement.queryAll(
       By.directive(DatesDropdownComponent)
     )[0]
-    const dateCreatedBeforeRelativeButton = dateCreatedDropdown.queryAll(
-      By.css('button')
-    )[1]
-    dateCreatedBeforeRelativeButton.triggerEventHandler('click')
+    component.dateCreatedRelativeDate = RelativeDate.WITHIN_1_WEEK
+    dateCreatedDropdown.triggerEventHandler('datesSet')
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
@@ -1606,10 +1607,8 @@ describe('FilterEditorComponent', () => {
     const dateCreatedDropdown = fixture.debugElement.queryAll(
       By.directive(DatesDropdownComponent)
     )[0]
-    const dateCreatedBeforeRelativeButton = dateCreatedDropdown.queryAll(
-      By.css('button')
-    )[1]
-    dateCreatedBeforeRelativeButton.triggerEventHandler('click')
+    component.dateCreatedRelativeDate = RelativeDate.WITHIN_1_WEEK
+    dateCreatedDropdown.triggerEventHandler('datesSet')
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
@@ -1692,16 +1691,14 @@ describe('FilterEditorComponent', () => {
     const datesDropdown = fixture.debugElement.query(
       By.directive(DatesDropdownComponent)
     )
-    const dateCreatedBeforeRelativeButton = datesDropdown.queryAll(
-      By.css('button')
-    )[1]
-    dateCreatedBeforeRelativeButton.triggerEventHandler('click')
+    component.dateAddedRelativeDate = RelativeDate.WITHIN_1_WEEK
+    datesDropdown.triggerEventHandler('datesSet')
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
         rule_type: FILTER_FULLTEXT_QUERY,
-        value: 'created:[-1 week to now]',
+        value: 'added:[-1 week to now]',
       },
     ])
   }))
@@ -1711,16 +1708,14 @@ describe('FilterEditorComponent', () => {
     const datesDropdown = fixture.debugElement.query(
       By.directive(DatesDropdownComponent)
     )
-    const dateCreatedBeforeRelativeButton = datesDropdown.queryAll(
-      By.css('button')
-    )[1]
-    dateCreatedBeforeRelativeButton.triggerEventHandler('click')
+    component.dateAddedRelativeDate = RelativeDate.WITHIN_1_WEEK
+    datesDropdown.triggerEventHandler('datesSet')
     fixture.detectChanges()
     tick(400)
     expect(component.filterRules).toEqual([
       {
         rule_type: FILTER_FULLTEXT_QUERY,
-        value: 'foo,created:[-1 week to now]',
+        value: 'foo,added:[-1 week to now]',
       },
     ])
   }))
index 0916d9c0d42e5cd5d0a5d3b0d259944e10ade8b9..900e72785ae4c3f250e6522df6ab95288be2558b 100644 (file)
@@ -135,24 +135,44 @@ const TEXT_FILTER_MODIFIER_NOTNULL = 'not null'
 const TEXT_FILTER_MODIFIER_GT = 'greater'
 const TEXT_FILTER_MODIFIER_LT = 'less'
 
-const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:\[([^\]]+)\]/g
-const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:\[([^\]]+)\]/g
+const RELATIVE_DATE_QUERY_REGEXP_CREATED = /created:[\["]([^\]]+)[\]"]/g
+const RELATIVE_DATE_QUERY_REGEXP_ADDED = /added:[\["]([^\]]+)[\]"]/g
 const RELATIVE_DATE_QUERYSTRINGS = [
   {
     relativeDate: RelativeDate.WITHIN_1_WEEK,
     dateQuery: '-1 week to now',
+    isRange: true,
   },
   {
     relativeDate: RelativeDate.WITHIN_1_MONTH,
     dateQuery: '-1 month to now',
+    isRange: true,
   },
   {
     relativeDate: RelativeDate.WITHIN_3_MONTHS,
     dateQuery: '-3 month to now',
+    isRange: true,
   },
   {
     relativeDate: RelativeDate.WITHIN_1_YEAR,
     dateQuery: '-1 year to now',
+    isRange: true,
+  },
+  {
+    relativeDate: RelativeDate.THIS_YEAR,
+    dateQuery: 'this year',
+  },
+  {
+    relativeDate: RelativeDate.THIS_MONTH,
+    dateQuery: 'this month',
+  },
+  {
+    relativeDate: RelativeDate.TODAY,
+    dateQuery: 'today',
+  },
+  {
+    relativeDate: RelativeDate.YESTERDAY,
+    dateQuery: 'yesterday',
   },
 ]
 
@@ -907,12 +927,11 @@ export class FilterEditorComponent
 
       let existingRuleArgs = existingRule?.value.split(',')
       if (this.dateCreatedRelativeDate !== null) {
+        const rd = RELATIVE_DATE_QUERYSTRINGS.find(
+          (qS) => qS.relativeDate == this.dateCreatedRelativeDate
+        )
         queryArgs.push(
-          `created:[${
-            RELATIVE_DATE_QUERYSTRINGS.find(
-              (qS) => qS.relativeDate == this.dateCreatedRelativeDate
-            ).dateQuery
-          }]`
+          `created:${rd.isRange ? `[${rd.dateQuery}]` : `"${rd.dateQuery}"`}`
         )
         if (existingRule) {
           queryArgs = existingRuleArgs
@@ -921,12 +940,11 @@ export class FilterEditorComponent
         }
       }
       if (this.dateAddedRelativeDate !== null) {
+        const rd = RELATIVE_DATE_QUERYSTRINGS.find(
+          (qS) => qS.relativeDate == this.dateAddedRelativeDate
+        )
         queryArgs.push(
-          `added:[${
-            RELATIVE_DATE_QUERYSTRINGS.find(
-              (qS) => qS.relativeDate == this.dateAddedRelativeDate
-            ).dateQuery
-          }]`
+          `added:${rd.isRange ? `[${rd.dateQuery}]` : `"${rd.dateQuery}"`}`
         )
         if (existingRule) {
           queryArgs = existingRuleArgs