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()
</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 & 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) => 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) => 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) => 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) => 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">
-<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"> {{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' }} – <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' }} – <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' }} – <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' }} – <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>
.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;
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,
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',
})
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,
+ })
+ }))
})
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'
}
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({
NgxBootstrapIconsModule,
NgbDatepickerModule,
NgbDropdownModule,
+ NgSelectModule,
FormsModule,
ReactiveFormsModule,
NgClass,
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>()
@Input()
disabled: boolean = false
+ @Input()
+ placement: string = 'bottom-start'
+
public readonly today: string = new Date().toISOString().split('T')[0]
get isActive(): boolean {
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()
}
this.onChange()
}
+ clearCreatedRelativeDate() {
+ this.createdRelativeDate = null
+ this.onChange()
+ }
+
clearAddedTo() {
this.addedDateTo = null
this.onChange()
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)) {
}
<pngx-dates-dropdown class="flex-fill fade" [class.show]="show"
title="Dates" i18n-title
+ placement="bottom-end"
(datesSet)="updateRules()"
[(createdDateTo)]="dateCreatedTo"
[(createdDateFrom)]="dateCreatedFrom"
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,
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()
}))
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()
}))
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([
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([
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]',
},
])
}))
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]',
},
])
}))
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',
},
]
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
}
}
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