From b9c4316abcdfd1d5861cd3a91485bff03ad80eee Mon Sep 17 00:00:00 2001 From: Gregor Vostrak Date: Fri, 7 Feb 2025 13:35:11 +0100 Subject: [PATCH] remove duplicates from recently tracked dropdown, improve focus handling --- .../src/TimeEntry/TimeEntryAggregateRow.vue | 1 - .../ui/src/TimeEntry/TimeEntryRow.vue | 1 - .../src/TimeTracker/TimeTrackerControls.vue | 34 +++++++++++++++++-- .../TimeTrackerRecentlyTrackedEntry.vue | 9 ++--- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue b/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue index a7e26f81..334fde83 100644 --- a/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue +++ b/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue @@ -129,7 +129,6 @@ function onSelectChange(event: Event) { :project="timeEntry.project_id" :enable-estimated-time :currency="currency" - class="border border-border-primary" :task=" timeEntry.task_id " diff --git a/resources/js/packages/ui/src/TimeEntry/TimeEntryRow.vue b/resources/js/packages/ui/src/TimeEntry/TimeEntryRow.vue index 547a8bd8..21bd3ccc 100644 --- a/resources/js/packages/ui/src/TimeEntry/TimeEntryRow.vue +++ b/resources/js/packages/ui/src/TimeEntry/TimeEntryRow.vue @@ -119,7 +119,6 @@ function onSelectChange(event: Event) { :show-badge-border="false" :project="timeEntry.project_id" :currency="currency" - class="border border-border-primary" :enable-estimated-time :task=" timeEntry.task_id diff --git a/resources/js/packages/ui/src/TimeTracker/TimeTrackerControls.vue b/resources/js/packages/ui/src/TimeTracker/TimeTrackerControls.vue index 51e4e9b5..b174fb9d 100644 --- a/resources/js/packages/ui/src/TimeTracker/TimeTrackerControls.vue +++ b/resources/js/packages/ui/src/TimeTracker/TimeTrackerControls.vue @@ -103,10 +103,14 @@ function setBillableDefaultForProject() { } } +const blockRefocus = ref(false); + function onToggleButtonPress(newState: boolean) { if (newState) { emit('startTimer'); - currentTimeEntryDescriptionInput.value?.focus(); + if (!blockRefocus.value){ + currentTimeEntryDescriptionInput.value?.focus(); + } } else { emit('stopTimer'); } @@ -129,11 +133,27 @@ function updateTimeEntryDescription() { const {timeEntries} = storeToRefs(useTimeEntriesStore()); const filteredRecentlyTrackedTimeEntries = computed(() => { - return timeEntries.value.filter((item) => { + // do not include running time entries + const finishedTimeEntries = timeEntries.value.filter((item) => item.end !== null); + + // filter out duplicates based on description, task, project, tags and billable + const nonDuplicateTimeEntries = finishedTimeEntries.filter((item, index, self) => { + return index === self.findIndex((t) => ( + t.description === item.description && + t.task_id === item.task_id && + t.project_id === item.project_id && + t.tags.length === item.tags.length && + t.tags.every((tag) => item.tags.includes(tag)) && + t.billable === item.billable + )); + }); + + // filter time entries based on current description + return nonDuplicateTimeEntries.filter((item) => { return item.description ?.toLowerCase() ?.includes(tempDescription.value?.toLowerCase()?.trim() || ''); - }).slice(0, 5);; + }).slice(0, 5); }); const showDropdown = ref(false); @@ -143,6 +163,14 @@ watch(focused, (focused) => { nextTick(() => { // make sure the click event on the dropdown does not get interrupted showDropdown.value = focused + + // make sure that the input does not get refocused after the dropdown is closed + if(!focused){ + blockRefocus.value = true; + setTimeout(() => { + blockRefocus.value = false; + }, 100); + } }); }); diff --git a/resources/js/packages/ui/src/TimeTracker/TimeTrackerRecentlyTrackedEntry.vue b/resources/js/packages/ui/src/TimeTracker/TimeTrackerRecentlyTrackedEntry.vue index 1608a76e..7d50116f 100644 --- a/resources/js/packages/ui/src/TimeTracker/TimeTrackerRecentlyTrackedEntry.vue +++ b/resources/js/packages/ui/src/TimeTracker/TimeTrackerRecentlyTrackedEntry.vue @@ -30,13 +30,14 @@ const task = computed(() => { tabindex="-1" :data-select-id="timeEntry.id" :class="twMerge('px-2 py-1.5 flex justify-between items-center space-x-2 w-full rounded', props.highlighted && 'bg-card-background-active')"> - + {{ - timeEntry.description !== '' - ? timeEntry.description - : 'No Description' + timeEntry.description }} + + No Description +