Compare commits

...

1 Commits

Author SHA1 Message Date
Gregor Vostrak
b9c4316abc remove duplicates from recently tracked dropdown, improve focus handling 2025-02-07 13:35:11 +01:00
4 changed files with 36 additions and 9 deletions

View File

@@ -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
"

View File

@@ -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

View File

@@ -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);
}
});
});

View File

@@ -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')">
<span class="text-sm font-medium">
<span v-if="timeEntry.description !== ''" class="text-sm font-medium">
{{
timeEntry.description !== ''
? timeEntry.description
: 'No Description'
timeEntry.description
}}
</span>
<span v-else class="text-sm text-text-tertiary font-medium">
No Description
</span>
<ProjectBadge
ref="projectDropdownTrigger"
:color="project?.color"