fix(grid): restore row actions and remove edit badge

This commit is contained in:
t8y2 2026-07-09 17:37:36 +08:00
parent b0d6559866
commit c015d95016
9 changed files with 30 additions and 31 deletions

View File

@ -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<DataGridProps>(), {
// 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<ContextMenuItem[]>(() => {
</div>
<div class="flex shrink-0 items-center gap-1 px-1 ml-auto" @wheel="onDataGridTopbarFixedActionWheel">
<Tooltip v-if="showQueryEditReadyBadge">
<TooltipTrigger as-child>
<div class="flex h-5 items-center gap-1 rounded border border-emerald-500/30 bg-emerald-500/10 px-1.5 text-xs font-medium text-emerald-700 dark:text-emerald-300">
{{ t("grid.queryEditReady") }}
</div>
</TooltipTrigger>
<TooltipContent side="bottom" class="max-w-sm">
{{ t("grid.queryEditReadyHint", { table: queryEditReadyTargetLabel }) }}
</TooltipContent>
</Tooltip>
<Tooltip v-else-if="showQueryEditReadOnlyBadge">
<Tooltip v-if="showQueryEditReadOnlyBadge">
<TooltipTrigger as-child>
<div class="flex h-5 items-center gap-1 rounded border border-muted-foreground/30 bg-muted/60 px-1.5 text-xs font-medium text-muted-foreground">
{{ t("grid.queryEditReadOnly") }}

View File

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

View File

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

View File

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

View File

@ -907,8 +907,6 @@ export default withEnglishFallback({
nonTransactionalSaveHint: "{count}件の保留中の変更を1件ずつ保存します。途中で失敗した場合、それまでの成功した変更はロールバックされません。",
keylessEditWarning: "主キーなし",
keylessEditWarningHint: "このテーブルには主キーがありません。更新と削除はWHERE句にすべての元の行値を使用します。完全に重複する行はまとめて影響を受ける可能性があります。",
queryEditReady: "編集可能",
queryEditReadyHint: "この結果の書き込み可能なセルは「{table}」へ保存されます。保留中の変更アクションで確認して保存してください。",
queryEditReadOnly: "読み取り専用の結果",
queryEditUnsupported: {
"not-select": "SELECTクエリの結果のみ直接編集できます。",

View File

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

View File

@ -973,8 +973,6 @@ export default withEnglishFallback({
nonTransactionalSaveHint: "逐条保存 {count} 项更改;如果中途失败,前面已成功的更改不会回滚。",
keylessEditWarning: "无主键定位",
keylessEditWarningHint: "这张表没有主键。保存更新或删除时会使用整行原始值作为 WHERE 条件;如果存在完全重复的行,可能会影响多行。",
queryEditReady: "可编辑",
queryEditReadyHint: "此结果中的可写单元格会回写到“{table}”。请通过待保存按钮查看并保存更改。",
queryEditReadOnly: "只读结果",
queryEditUnsupported: {
"not-select": "只有 SELECT 查询结果可以直接编辑。",

View File

@ -914,8 +914,6 @@ export default withEnglishFallback({
nonTransactionalSaveHint: "逐條儲存 {count} 項更改;如果中途失敗,前面已成功的更改不會回溯。",
keylessEditWarning: "無主鍵定位",
keylessEditWarningHint: "此資料表沒有主鍵。更新與刪除會在 WHERE 子句中使用所有原始資料列值;完全重複的資料列可能會一起受到影響。",
queryEditReady: "可編輯",
queryEditReadyHint: "此結果中的可寫儲存格會回寫到「{table}」。請透過待儲存按鈕檢視並儲存變更。",
queryEditReadOnly: "唯讀結果",
queryEditUnsupported: {
"not-select": "只有 SELECT 查詢結果可以直接編輯。",

View File

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