diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index b7d3aa53f..94fc95668 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -3271,6 +3271,11 @@ const triggers = ref([]); const triggersLoaded = ref(false); const triggersLoading = ref(false); const triggersError = ref(""); +const searchQuery = ref(""); + +watch(activeTableInfoTab, () => { + searchQuery.value = ""; +}); const ddlDrawerStyle = computed(() => ({ width: `${ddlWidth.value}px`, @@ -3537,7 +3542,52 @@ onUnmounted(() => { clearInterval(_loadingTimer); }); -const highlightedDdlContent = computed(() => highlight(ddlContent.value)); +const filteredColumns = computed(() => { + if (!searchQuery.value) return props.tableMeta?.columns ?? []; + const q = searchQuery.value.toLowerCase(); + return (props.tableMeta?.columns ?? []).filter( + (c) => c.name.toLowerCase().includes(q) || c.data_type.toLowerCase().includes(q), + ); +}); + +const filteredIndexes = computed(() => { + if (!searchQuery.value) return indexes.value; + const q = searchQuery.value.toLowerCase(); + return indexes.value.filter( + (i) => i.name.toLowerCase().includes(q) || i.columns.some((c) => c.toLowerCase().includes(q)), + ); +}); + +const filteredForeignKeys = computed(() => { + if (!searchQuery.value) return foreignKeys.value; + const q = searchQuery.value.toLowerCase(); + return foreignKeys.value.filter( + (fk) => + fk.name.toLowerCase().includes(q) || + fk.column.toLowerCase().includes(q) || + fk.ref_table.toLowerCase().includes(q) || + fk.ref_column.toLowerCase().includes(q), + ); +}); + +const filteredTriggers = computed(() => { + if (!searchQuery.value) return triggers.value; + const q = searchQuery.value.toLowerCase(); + return triggers.value.filter((t) => t.name.toLowerCase().includes(q)); +}); + +const filteredDdlContent = computed(() => { + if (!ddlContent.value) return ""; + const html = highlight(ddlContent.value); + if (!searchQuery.value) return html; + + const escaped = searchQuery.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const regex = new RegExp(`(${escaped})`, "gi"); + // Match only text between > and < (text nodes), then replace the search term within those spans + return html.replace(/>([^<]*) { + return `>${text.replace(regex, "$1")}<`; + }); +}); defineExpose({ useTransaction, @@ -4937,8 +4987,33 @@ defineExpose({ +
+
+ + + +
+
+
- +
+ {{ t("grid.tableInfoNoResults") }} +
+
@@ -4948,7 +5023,7 @@ defineExpose({
{{ indexesError }}
+
+ {{ t("grid.tableInfoNoResults") }} +
{{ t("grid.tableInfoEmpty") }}
-
+
{{ index.name }}
{{ foreignKeysError }}
+
+ {{ t("grid.tableInfoNoResults") }} +
{{ t("grid.tableInfoEmpty") }}
-
+
{{ fk.name }}
{{ fk.column }} -> {{ fk.ref_table }}.{{ fk.ref_column }} @@ -5026,11 +5113,17 @@ defineExpose({
{{ triggersError }}
+
+ {{ t("grid.tableInfoNoResults") }} +
{{ t("grid.tableInfoEmpty") }}
-
+
{{ trigger.name }}
{{ trigger.timing }} {{ trigger.event }}
@@ -5041,7 +5134,7 @@ defineExpose({ v-else-if="activeTableInfoTab === 'ddl' && !ddlLoading" class="flex-1 min-w-0 text-xs font-mono p-3 overflow-auto ddl-code leading-5 select-text" :class="ddlWrap ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'" - v-html="highlightedDdlContent" + v-html="filteredDdlContent" >
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 5dd415455..d187eb587 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -533,6 +533,8 @@ export default { tableInfoTriggers: "Triggers", tableInfoNullable: "Nullable", tableInfoEmpty: "No metadata", + tableInfoSearch: "Search...", + tableInfoNoResults: "No results", queryError: "Query Error", refresh: "Refresh", commit: "Commit", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index 54be1103d..d875e7c8d 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -492,6 +492,8 @@ export default { transpose: "Transponer fila", rowsPerPageShort: " filas", columnDetails: "Detalles de columna", + tableInfoSearch: "Buscar...", + tableInfoNoResults: "Sin resultados", queryError: "Error de consulta", refresh: "Actualizar", commit: "Confirmar", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index ae8914a31..19458aee1 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -528,6 +528,8 @@ export default { tableInfoTriggers: "触发器", tableInfoNullable: "可空", tableInfoEmpty: "暂无元数据", + tableInfoSearch: "搜索...", + tableInfoNoResults: "无匹配结果", queryError: "查询出错", refresh: "刷新", commit: "提交",
{{ t("grid.columnName") }}