0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-08 10:13:39 +02:00

Implement search functionality for file extensions in DiffFileExtensionFilter

This commit is contained in:
Michał Krela 2026-04-01 17:55:55 +02:00
parent 8f34cb362f
commit 86fc0e7438

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import {ref, onMounted, onUnmounted, useTemplateRef, type ShallowRef} from 'vue';
import {ref, computed, onMounted, onUnmounted} from 'vue';
import {SvgIcon} from '../svg.ts';
import {generateElemId} from '../utils/dom.ts';
@ -20,7 +20,7 @@ const menuVisible = ref(false);
const extensions = ref<Array<Extension>>([]);
const isFiltering = ref(false);
const appliedExtensions = ref<Array<string> | null>(null);
const expandBtn = useTemplateRef('expandBtn') as Readonly<ShallowRef<HTMLButtonElement>>;
const searchQuery = ref('');
const mutationObserver = ref<MutationObserver | null>(null);
const uniqueIdMenu = generateElemId('diff-extension-filter-menu-');
const locale = {
@ -28,8 +28,21 @@ const locale = {
select_all: el.getAttribute('data-select_all') ?? 'Select all',
deselect_all: el.getAttribute('data-deselect_all') ?? 'Deselect all',
apply: el.getAttribute('data-apply') ?? 'Apply',
search: el.getAttribute('data-search') ?? 'Search extensions...',
} as Record<string, string>;
/**
* Filter extensions based on search query
* Matches against extension name (e.g., ".ts", ".go")
*/
const filteredExtensions = computed(() => {
if (!searchQuery.value.trim()) {
return extensions.value;
}
const query = searchQuery.value.toLowerCase();
return extensions.value.filter((ext) => ext.ext.toLowerCase().includes(query));
});
/**
* Extract file extension from filename
* Returns the extension with dot (e.g., ".ts", ".go")
@ -124,18 +137,17 @@ function focusElem(elem: HTMLElement | null, prevElem: HTMLElement | null) {
/**
* Toggle dropdown menu visibility
* Rescans extensions when opening, optionally restores focus to button when closing
* @param refocus Whether to refocus the expand button when closing (default: true)
* Rescans extensions when opening, clears search when closing
*/
function toggleMenu(refocus = true) {
function toggleMenu() {
menuVisible.value = !menuVisible.value;
if (menuVisible.value) {
searchQuery.value = '';
scanExtensions();
} else if (refocus) {
if (expandBtn.value) {
expandBtn.value.tabIndex = 0;
expandBtn.value.focus();
}
setTimeout(() => {
const searchInput = el.querySelector('.diff-ext-search-input') as HTMLInputElement;
if (searchInput) searchInput.focus();
}, 0);
}
}
@ -274,7 +286,6 @@ onUnmounted(() => {
<template>
<div class="ui scrolling dropdown custom diff-file-extension-filter">
<button
ref="expandBtn"
class="ui tiny basic button"
:class="{'diff-ext-filter-btn-active': isFiltering}"
@click="toggleMenu()"
@ -289,10 +300,23 @@ onUnmounted(() => {
<div class="left menu transition" :id="uniqueIdMenu" :class="{visible: menuVisible}" v-show="menuVisible" v-cloak :aria-expanded="menuVisible ? 'true': 'false'">
<div class="header">{{ locale.filter_by_file_extension }}</div>
<div class="ui divider tw-mt-2 tw-mb-0"/>
<!-- Search input -->
<div class="ui form tw-mb-2">
<div class="ui input fluid field tw-mb-0">
<input
type="text"
v-model="searchQuery"
class="diff-ext-search-input"
:placeholder="locale.search"
@keydown.escape="toggleMenu()"
/>
</div>
</div>
<div class="ui divider tw-mt-2 tw-mb-0"/>
<div class="ui form">
<!-- Extension checkboxes -->
<div class="grouped fields">
<template v-for="ext in extensions" :key="ext.ext">
<template v-if="filteredExtensions.length > 0" v-for="ext in filteredExtensions" :key="ext.ext">
<div class="field" role="menuitem" tabindex="-1">
<div class="ui checkbox">
<input
@ -307,6 +331,9 @@ onUnmounted(() => {
</div>
</div>
</template>
<div v-if="filteredExtensions.length === 0" class="tw-py-4 tw-text-center tw-text-text-light-2">
{{ locale.no_results ?? 'No extensions found' }}
</div>
</div>
</div>
@ -369,4 +396,12 @@ onUnmounted(() => {
.ui.dropdown.diff-file-extension-filter .diff-ext-text-btn:hover {
text-decoration: underline;
}
.ui.dropdown.diff-file-extension-filter .diff-ext-search-input {
width: 100%;
}
.ui.dropdown.diff-file-extension-filter .ui.input {
margin-bottom: 0.5rem;
}
</style>