From c015d9501675bab5127cbe4f604d773960bfed62 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Thu, 9 Jul 2026 17:37:36 +0800 Subject: [PATCH] fix(grid): restore row actions and remove edit badge --- apps/desktop/src/components/grid/DataGrid.vue | 28 ++++++++----------- apps/desktop/src/i18n/locales/en.ts | 2 -- apps/desktop/src/i18n/locales/es.ts | 2 -- apps/desktop/src/i18n/locales/it.ts | 2 -- apps/desktop/src/i18n/locales/ja.ts | 2 -- apps/desktop/src/i18n/locales/pt-BR.ts | 2 -- apps/desktop/src/i18n/locales/zh-CN.ts | 2 -- apps/desktop/src/i18n/locales/zh-TW.ts | 2 -- packages/app-tests/dataGridProps.test.ts | 19 +++++++++++++ 9 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 packages/app-tests/dataGridProps.test.ts diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index b65537b9b..dce1b3341 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -193,7 +193,7 @@ type ConditionSuggestion = { type SortMenuValue = "local-asc" | "local-desc" | "database-asc" | "database-desc" | "clear"; -const props = defineProps<{ +interface DataGridProps { result: QueryResult; sql?: string; editable?: boolean; @@ -234,7 +234,14 @@ const props = defineProps<{ queryEditabilityReason?: QueryEditabilityReason; allowInsertRows?: boolean; allowDeleteRows?: boolean; -}>(); +} + +const props = withDefaults(defineProps(), { + // Vue casts absent Boolean props to false unless the default is explicitly + // undefined; omitted row-action limits must keep normal table-data editing. + allowInsertRows: undefined, + allowDeleteRows: undefined, +}); const dataGridTraceId = uuid().slice(0, 8); const dataGridCreatedAt = performance.now(); @@ -3505,9 +3512,7 @@ watch( } }, ); -const showQueryEditReadyBadge = computed(() => isResultsContext.value && hasData.value && !!props.editable && (!!props.tableMeta || !!props.customSaveHandler)); -const queryEditReadyTargetLabel = computed(() => props.tableMeta?.tableName ?? props.customSaveHandler?.targetLabel ?? ""); -const showQueryEditReadOnlyBadge = computed(() => isResultsContext.value && hasData.value && !showQueryEditReadyBadge.value && !!props.queryEditabilityReason); +const showQueryEditReadOnlyBadge = computed(() => isResultsContext.value && hasData.value && !props.editable && !!props.queryEditabilityReason); const queryEditReadOnlyReason = computed(() => (props.queryEditabilityReason ? t(`grid.queryEditUnsupported.${props.queryEditabilityReason}`) : "")); const showKeylessEditWarning = computed(() => !!props.editable && !!props.tableMeta && canUseKeylessRowPredicate(props.databaseType, props.tableMeta.primaryKeys ?? [])); const canShowWhereSearch = computed(() => !!props.onExecuteSql && !isResultsContext.value); @@ -3943,7 +3948,6 @@ const showDataGridTopbar = computed( hasLocalColumnFilters.value || canShowWhereSearch.value || hasSearchBarSlot.value || - showQueryEditReadyBadge.value || showQueryEditReadOnlyBadge.value || props.context !== "results" || (!!props.editable && hasDataGridSaveTarget.value) || @@ -8833,17 +8837,7 @@ const gridContextMenuItems = computed(() => {
- - -
- {{ t("grid.queryEditReady") }} -
-
- - {{ t("grid.queryEditReadyHint", { table: queryEditReadyTargetLabel }) }} - -
- +
{{ t("grid.queryEditReadOnly") }} diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 5e010d601..91e906bc1 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -971,8 +971,6 @@ export default { nonTransactionalSaveHint: "Save {count} pending change(s) one by one. If one fails, earlier successful changes will not be rolled back.", keylessEditWarning: "No primary key", keylessEditWarningHint: "This table has no primary key. Updates and deletes use all original row values in the WHERE clause; exact duplicate rows may be affected together.", - queryEditReady: "Editable", - queryEditReadyHint: "Writable cells in this result save back to “{table}”. Use the pending-changes action to review and save.", queryEditReadOnly: "Read-only result", queryEditUnsupported: { "not-select": "Only SELECT query results can be edited directly.", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index 3472521cd..ce9870225 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -915,8 +915,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "Guarda {count} cambio(s) pendiente(s) uno por uno. Si uno falla, los cambios anteriores correctos no se revierten.", keylessEditWarning: "Sin clave primaria", keylessEditWarningHint: "Esta tabla no tiene clave primaria. Las actualizaciones y eliminaciones usan todos los valores originales de la fila en WHERE; filas duplicadas exactas pueden verse afectadas juntas.", - queryEditReady: "Editable", - queryEditReadyHint: 'Las celdas editables de este resultado se guardan en "{table}". Usa la acción de cambios pendientes para revisar y guardar.', queryEditReadOnly: "Resultado de solo lectura", queryEditUnsupported: { "not-select": "Solo los resultados de consultas SELECT pueden editarse directamente.", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index cf6b5373b..8d706f373 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -913,8 +913,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "Salva {count} modifica/he in sospeso una ad una. In caso di errore, le modifiche salvate in precedenza non saranno annullate.", keylessEditWarning: "Nessuna chiave primaria", keylessEditWarningHint: "Questa tabella non ha chiavi primarie. Gli aggiornamenti e le eliminazioni utilizzano tutti i valori originali delle righe nella clausola WHERE; le righe duplicate esatte potrebbero essere influenzate contemporaneamente.", - queryEditReady: "Modificabile", - queryEditReadyHint: "Le celle modificabili in questo risultato vengono salvate in “{table}”. Usa l'azione delle modifiche in sospeso per rivedere e salvare.", queryEditReadOnly: "Risultato in sola lettura", queryEditUnsupported: { "not-select": "Only SELECT query results can be edited directly.", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index 95e71637c..5df7e831a 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -907,8 +907,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "{count}件の保留中の変更を1件ずつ保存します。途中で失敗した場合、それまでの成功した変更はロールバックされません。", keylessEditWarning: "主キーなし", keylessEditWarningHint: "このテーブルには主キーがありません。更新と削除はWHERE句にすべての元の行値を使用します。完全に重複する行はまとめて影響を受ける可能性があります。", - queryEditReady: "編集可能", - queryEditReadyHint: "この結果の書き込み可能なセルは「{table}」へ保存されます。保留中の変更アクションで確認して保存してください。", queryEditReadOnly: "読み取り専用の結果", queryEditUnsupported: { "not-select": "SELECTクエリの結果のみ直接編集できます。", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index cadf69445..f87fc5a61 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -914,8 +914,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "Salvar {count} alteração(ões) pendente(s) uma a uma. Se uma falhar, as alterações bem-sucedidas anteriores não serão revertidas.", keylessEditWarning: "Sem chave primária", keylessEditWarningHint: "Esta tabela não possui chave primária. Atualizações e exclusões usam todos os valores originais da linha na cláusula WHERE; linhas exatamente duplicadas podem ser afetadas juntas.", - queryEditReady: "Editável", - queryEditReadyHint: "As células editáveis deste resultado são salvas em “{table}”. Use a ação de alterações pendentes para revisar e salvar.", queryEditReadOnly: "Resultado somente leitura", queryEditUnsupported: { "not-select": "Apenas resultados de consultas SELECT podem ser editados diretamente.", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index aff7a5e2f..20c03ed8b 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -973,8 +973,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "逐条保存 {count} 项更改;如果中途失败,前面已成功的更改不会回滚。", keylessEditWarning: "无主键定位", keylessEditWarningHint: "这张表没有主键。保存更新或删除时会使用整行原始值作为 WHERE 条件;如果存在完全重复的行,可能会影响多行。", - queryEditReady: "可编辑", - queryEditReadyHint: "此结果中的可写单元格会回写到“{table}”。请通过待保存按钮查看并保存更改。", queryEditReadOnly: "只读结果", queryEditUnsupported: { "not-select": "只有 SELECT 查询结果可以直接编辑。", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index 076fc57fb..5c81fe99a 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -914,8 +914,6 @@ export default withEnglishFallback({ nonTransactionalSaveHint: "逐條儲存 {count} 項更改;如果中途失敗,前面已成功的更改不會回溯。", keylessEditWarning: "無主鍵定位", keylessEditWarningHint: "此資料表沒有主鍵。更新與刪除會在 WHERE 子句中使用所有原始資料列值;完全重複的資料列可能會一起受到影響。", - queryEditReady: "可編輯", - queryEditReadyHint: "此結果中的可寫儲存格會回寫到「{table}」。請透過待儲存按鈕檢視並儲存變更。", queryEditReadOnly: "唯讀結果", queryEditUnsupported: { "not-select": "只有 SELECT 查詢結果可以直接編輯。", diff --git a/packages/app-tests/dataGridProps.test.ts b/packages/app-tests/dataGridProps.test.ts new file mode 100644 index 000000000..c571837ea --- /dev/null +++ b/packages/app-tests/dataGridProps.test.ts @@ -0,0 +1,19 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; +import { test } from "vitest"; +import { compileScript, parse } from "vue/compiler-sfc"; + +function compiledDataGridScript(): string { + const source = readFileSync("apps/desktop/src/components/grid/DataGrid.vue", "utf8"); + const { descriptor } = parse(source, { filename: "DataGrid.vue" }); + return compileScript(descriptor, { id: "data-grid-props-test" }).content; +} + +test("row action limit props default to undefined when omitted", () => { + const compiled = compiledDataGridScript(); + + // Vue Boolean props normally cast an absent prop to false. DataGrid callers + // omit these props to mean "not restricted", so the runtime default matters. + assert.match(compiled, /allowInsertRows:\s*\{\s*type:\s*Boolean,\s*required:\s*false,\s*default:\s*undefined\s*\}/); + assert.match(compiled, /allowDeleteRows:\s*\{\s*type:\s*Boolean,\s*required:\s*false,\s*default:\s*undefined\s*\}/); +});