feat: add date math for filters #1342

Merged
konrad merged 88 commits from feature/date-math into main 2022-03-28 17:30:43 +00:00
1 changed files with 64 additions and 45 deletions
Showing only changes of commit 950fdce111 - Show all commits

View File

@ -1,46 +1,54 @@
<template>
<a @click="showPopup = !showPopup">
{{ $t('task.show.select') }}
</a>
<div class="datepicker-with-range-container">
<transition name="fade">
<div class="datepicker-with-range" v-if="showPopup">
<div class="selections">
<button @click="setDateRange(datesToday)" :class="{'is-active': dateRange === datesToday}">
{{ $t('task.show.today') }}
</button>
<button @click="setDateRange(datesThisWeek)" :class="{'is-active': dateRange === datesThisWeek}">
{{ $t('task.show.thisWeek') }}
</button>
<button @click="setDateRange(datesNextWeek)" :class="{'is-active': dateRange === datesNextWeek}">
{{ $t('task.show.nextWeek') }}
</button>
<button @click="setDateRange(datesNext7Days)" :class="{'is-active': dateRange === datesNext7Days}">
{{ $t('task.show.next7Days') }}
</button>
<button @click="setDateRange(datesThisMonth)" :class="{'is-active': dateRange === datesThisMonth}">
{{ $t('task.show.thisMonth') }}
</button>
<button @click="setDateRange(datesNextMonth)" :class="{'is-active': dateRange === datesNextMonth}">
{{ $t('task.show.nextMonth') }}
</button>
<button @click="setDateRange(datesNext30Days)"
:class="{'is-active': dateRange === datesNext30Days}">
{{ $t('task.show.next30Days') }}
</button>
<button @click="setDateRange('')" :class="{'is-active': customRangeActive}">
{{ $t('misc.custom') }}
</button>
<popup>
<template #trigger="{toggle}">
<a @click.prevent.stop="toggle()">
konrad marked this conversation as resolved Outdated

Provide buttonText as slot prop aswell

Provide `buttonText` as slot prop aswell

Done.

Done.
{{ $t('task.show.select') }}
konrad marked this conversation as resolved Outdated

The styles (=props) selected for the button are hightly specific and create an indirect dependency to its indented use case. The latter might change in the future and then we have to remember this dependency. This is why I think it makes sense to remove at least the specific use case of this button. Since we wouldn't use it then at all anymore (since you need to overwrite the default slot) it might make it simpler to only define the slot.

The styles (=props) selected for the button are hightly specific and create an indirect dependency to its indented use case. The latter might change in the future and then we have to remember this dependency. This is why I think it makes sense to remove at least the specific use case of this button. Since we wouldn't use it then at all anymore (since you need to overwrite the default slot) it might make it simpler to only define the slot.

Moved everything to a slot.

Moved everything to a slot.
</a>
</template>
<template #content="{isOpen}">
<div class="datepicker-with-range" :class="{'is-open': isOpen}">
<div class="selections">
<button @click="setDateRange(datesToday)" :class="{'is-active': dateRange === datesToday}">
{{ $t('task.show.today') }}
</button>
konrad marked this conversation as resolved Outdated

Use BaseButton

Use BaseButton

Done.

Done.
<button @click="setDateRange(datesThisWeek)"
:class="{'is-active': dateRange === datesThisWeek}">
{{ $t('task.show.thisWeek') }}
konrad marked this conversation as resolved Outdated

Use BaseButton

Use BaseButton

Done.

Done.
</button>
<button @click="setDateRange(datesNextWeek)"
:class="{'is-active': dateRange === datesNextWeek}">
{{ $t('task.show.nextWeek') }}
</button>
<button @click="setDateRange(datesNext7Days)"
:class="{'is-active': dateRange === datesNext7Days}">
{{ $t('task.show.next7Days') }}
</button>
<button @click="setDateRange(datesThisMonth)"
:class="{'is-active': dateRange === datesThisMonth}">
{{ $t('task.show.thisMonth') }}
</button>
konrad marked this conversation as resolved Outdated

Instead of calling inputChanged from here better watch the from and below the to value.
This prevents future mistakes

Instead of calling `inputChanged` from here better watch the `from` and below the `to` value. This prevents future mistakes

Changed. I kept inputChanged though because I need to watchers.

Changed. I kept `inputChanged` though because I need to watchers.
<button @click="setDateRange(datesNextMonth)"
:class="{'is-active': dateRange === datesNextMonth}">
{{ $t('task.show.nextMonth') }}
</button>
<button @click="setDateRange(datesNext30Days)"
:class="{'is-active': dateRange === datesNext30Days}">
{{ $t('task.show.next30Days') }}
</button>
<button @click="setDateRange('')" :class="{'is-active': customRangeActive}">
{{ $t('misc.custom') }}
</button>
</div>
<div class="flatpickr-container">
<flat-pickr
:config="flatPickerConfig"
v-model="dateRange"
/>
</div>
</div>
<div class="flatpickr-container">
<flat-pickr
:config="flatPickerConfig"
v-model="dateRange"
/>
</div>
</div>
</transition>
</template>
</popup>
</div>
</template>
@ -51,6 +59,7 @@ import {computed, ref, watch} from 'vue'
import {useI18n} from 'vue-i18n'
import {store} from '@/store'
import {format} from 'date-fns'
import Popup from '@/components/misc/popup'
const {t} = useI18n()
konrad marked this conversation as resolved Outdated

The whole explanation card should be its own component.

The whole explanation card should be its own component.

Done!

Done!
@ -202,15 +211,25 @@ const customRangeActive = computed<Boolean>(() => {
.datepicker-with-range-container {
position: relative;
z-index: 10;
:deep(.popup) {
margin-top: 1rem;

I think this is a good usecase for a reactive.

I think this is a good usecase for a reactive.

What would be the advantage over a ref?

What would be the advantage over a ref?

Both values can be changed at the same time
=> watchers aren't triggered twice when you change stuff shortly after each other.

Both values can be changed at the same time => watchers aren't triggered twice when you change stuff shortly after each other.

How do I type it properly? If I only pass a string into a reactive it complains I should pass in an object instead.

Edit: using String (capital S) seems to work.

How do I type it properly? If I only pass a string into a reactive it complains I should pass in an object instead. Edit: using `String` (capital S) seems to work.

Okay even with the typing solved it still complains when trying to set it: Because we do const from = ... I won't be able to do from = fromDate. Any idea how to solve this?

Okay even with the typing solved it still complains when trying to set it: Because we do `const from = ...` I won't be able to do `from = fromDate`. Any idea how to solve this?
border-radius: $radius;
border: 1px solid var(--grey-200);
background-color: var(--white);
box-shadow: $shadow;

Use v-model for values.
Might be useful: https://vueuse.org/core/usevmodel/

Use v-model for values. Might be useful: https://vueuse.org/core/usevmodel/

What I don't like with using a v-model here would be the need to introduce another watcher in ShowTasks because we need to push the changes to the route. I think the current way with an event nicely circumvents this.

Also I'd like to keep the current behaviour where it only does one route change if you change both values instead of two (but that could easily be kept with passing an object to v-model?).

What I don't like with using a v-model here would be the need to introduce another watcher in ShowTasks because we need to push the changes to the route. I think the current way with an event nicely circumvents this. Also I'd like to keep the current behaviour where it only does one route change if you change both values instead of two (but that could easily be kept with passing an object to v-model?).

Also I'd like to keep the current behaviour where it only does one route change if you change both values instead of two (but that could easily be kept with passing an object to v-model?).

correct

> Also I'd like to keep the current behaviour where it only does one route change if you change both values instead of two (but that could easily be kept with passing an object to v-model?). correct
&.is-open {
width: 500px;
height: 320px;
}
}
}
.datepicker-with-range {
border-radius: $radius;
border: 1px solid var(--grey-200);
background-color: var(--white);
box-shadow: $shadow;
display: flex;
width: 500px;
width: 100%;
height: 100%;
position: absolute;
:deep(.flatpickr-calendar) {