diff --git a/apps/desktop/src/components/editor/AiAssistant.vue b/apps/desktop/src/components/editor/AiAssistant.vue index 15206d9e6..e83f454cc 100644 --- a/apps/desktop/src/components/editor/AiAssistant.vue +++ b/apps/desktop/src/components/editor/AiAssistant.vue @@ -82,6 +82,7 @@ const queryStore = useQueryStore(); const { openTableTarget } = useNavigationTargets({ showFieldLineageDialog: ref(false), showDatabaseSearchDialog: ref(false), + showDiagramDialog: ref(false), }); const { toast } = useToast(); const { isDark } = useTheme(); diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 235ac5f67..8e5fb8906 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -1080,6 +1080,7 @@ const serverFilterValueByKey = ref>(new Map()); let serverFilterRequestId = 0; let serverFilterSearchTimer: ReturnType | undefined; const filterBuilderOpen = ref(false); +const filterBuilderColumnSearch = ref(""); const filterModeOptions: Array<{ value: FilterMode; labelKey: string }> = [ { value: "equals", labelKey: "grid.filterBuilderEquals" }, { value: "not-equals", labelKey: "grid.filterBuilderNotEquals" }, @@ -1092,6 +1093,12 @@ const filterModeOptions: Array<{ value: FilterMode; labelKey: string }> = [ ]; const filterBuilderColumns = computed(() => props.tableMeta?.columns ?? []); const filterBuilderColumnOptions = computed(() => filterBuilderColumns.value.map((column) => column.name)); +const filteredFilterBuilderColumnOptions = computed(() => { + const query = filterBuilderColumnSearch.value.trim().toLowerCase(); + if (!query) return filterBuilderColumnOptions.value; + return filterBuilderColumnOptions.value.filter((columnName) => columnName.toLowerCase().includes(query)); +}); +const filterBuilderColumnSearchNavigationKeys = new Set(["Escape", "Tab", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"]); const structuredFilterCacheKey = computed(() => props.cacheKey || [props.connectionId ?? "", props.database ?? "", props.context ?? "", props.tableMeta?.schema ?? "", props.tableMeta?.tableName ?? ""].join("\u0001")); const structuredFilterScopeKey = computed(() => [props.connectionId ?? "", props.database ?? "", props.schema ?? "", props.context ?? "", props.tableMeta?.schema ?? "", props.tableMeta?.tableName ?? "", filterBuilderColumnOptions.value.join("\0")].join("\u0001")); const structuredFilterRules = ref([]); @@ -1815,6 +1822,24 @@ function updateStructuredFilterRule(ruleId: string, patch: Partial 0 ? [defaultStructuredFilterRule()] : []; @@ -1871,6 +1896,10 @@ async function applyStructuredFilters() { watch([structuredFilterCacheKey, structuredFilterScopeKey], loadStructuredFilterStateForScope, { immediate: true }); +watch(filterBuilderOpen, (open) => { + if (!open) filterBuilderColumnSearch.value = ""; +}); + watch( [structuredFilterRules, appliedStructuredWhereInput], () => { @@ -8243,14 +8272,32 @@ const gridContextMenuItems = computed(() => {
- - - + + {{ columnName }} +
+ {{ t("grid.filterBuilderNoMatchingColumns") }} +
+
+ + +
diff --git a/apps/desktop/src/components/ui/select/SelectContent.vue b/apps/desktop/src/components/ui/select/SelectContent.vue index 01f880c08..a95ab328a 100644 --- a/apps/desktop/src/components/ui/select/SelectContent.vue +++ b/apps/desktop/src/components/ui/select/SelectContent.vue @@ -16,17 +16,19 @@ const props = withDefaults( class?: HTMLAttributes["class"]; disablePortal?: boolean; disableOutsidePointerEvents?: boolean; + hideScrollButtons?: boolean; } >(), { position: "popper", disablePortal: false, disableOutsidePointerEvents: true, + hideScrollButtons: false, }, ); const emits = defineEmits(); -const delegatedProps = reactiveOmit(props, "class", "disablePortal"); +const delegatedProps = reactiveOmit(props, "class", "disablePortal", "hideScrollButtons"); const forwarded = useForwardPropsEmits(delegatedProps, emits); @@ -45,11 +47,11 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits); ) " > - + - +
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index aaef3406e..3d6fcef6f 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -719,6 +719,8 @@ export default { filterBuilderSummary: "{count} rules", filterBuilderAddRule: "Add rule", filterBuilderColumn: "Column", + filterBuilderSearchColumns: "Search columns...", + filterBuilderNoMatchingColumns: "No matching columns", filterBuilderValue: "Value", filterBuilderNoValue: "No value needed", filterBuilderEmpty: "Add a rule to start filtering rows.", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index cb3e19f6b..cf1bfca54 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -919,6 +919,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Este SQL no admite ordenamiento del resultado completo. Intenta con una consulta SELECT simple.", truncatedHint: "Los resultados están limitados a 10.000 filas. Usa LIMIT/OFFSET en tu consulta para paginar.", + filterBuilderSearchColumns: "Buscar columnas...", + filterBuilderNoMatchingColumns: "Sin columnas coincidentes", }, exportProgress: { title: "Exportando datos de la tabla", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index 1570ecbfe..71783b925 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -917,6 +917,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Questo SQL non supporta l'ordinamento sull'intero risultato. Riprova con una query SELECT semplice.", truncatedHint: "Risultati troncati a {count} righe. Usa la paginazione a piè di pagina o regola le righe per pagina.", + filterBuilderSearchColumns: "Cerca campi...", + filterBuilderNoMatchingColumns: "Nessun campo corrispondente", }, exportProgress: { title: "Esportazione Dati Tabella", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index c00e425c6..8b47efc19 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -917,6 +917,8 @@ export default withEnglishFallback({ renderMode: "レンダーモード", undoChange: "変更を元に戻す", redoChange: "変更をやり直す", + filterBuilderSearchColumns: "フィールドを検索...", + filterBuilderNoMatchingColumns: "一致するフィールドがありません", }, exportProgress: { title: "テーブルデータをエクスポート中", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index a9b710990..6064582dd 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -918,6 +918,8 @@ export default withEnglishFallback({ }, sortUnsupported: "Este SQL não suporta a ordenação do resultado completo. Tente novamente com uma única consulta SELECT.", truncatedHint: "Resultados truncados em {count} linhas. Use a paginação no rodapé ou ajuste as linhas por página.", + filterBuilderSearchColumns: "Pesquisar campos...", + filterBuilderNoMatchingColumns: "Nenhum campo correspondente", }, exportProgress: { title: "Exportando Dados da Tabela", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index 27f688ed3..1a969cc4d 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -721,6 +721,8 @@ export default withEnglishFallback({ filterBuilderSummary: "{count} 条规则", filterBuilderAddRule: "新增条件", filterBuilderColumn: "字段", + filterBuilderSearchColumns: "搜索字段...", + filterBuilderNoMatchingColumns: "没有匹配的字段", filterBuilderValue: "值", filterBuilderNoValue: "无需输入值", filterBuilderEmpty: "新增一条条件后即可开始筛选。", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index 4d7080cc0..a5de67270 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -918,6 +918,8 @@ export default withEnglishFallback({ }, sortUnsupported: "目前 SQL 不支援完整排序,請改為單條 SELECT 查詢後再嘗試。", truncatedHint: "結果已截斷,僅顯示前 {count} 行。可經由底部分頁繼續載入,或調整每頁行數。", + filterBuilderSearchColumns: "搜尋欄位...", + filterBuilderNoMatchingColumns: "沒有匹配的欄位", }, exportProgress: { title: "匯出資料表資料",