fix(grid): keep JSON format reachable after compacting

This commit is contained in:
zipg
2026-09-21 16:57:48 +08:00
committed by GitHub
parent 3b58269ca5
commit 0f8ad280c1
7 changed files with 86 additions and 0 deletions
@@ -6034,6 +6034,7 @@ const {
restoreDetailOriginalValue,
setValueEditorNull,
formatValueEditorJson,
formatDetailJsonDraft,
compactDetailJson,
openDetailJsonCompare,
setDetailNull,
@@ -13613,6 +13614,7 @@ useUpdateBlocker(() => (hasPendingChanges.value || hasPendingDataEditorDraft.val
:can-copy-sql-condition="canCopyPreparedDetailSqlCondition"
:database-type="resolvedDatabaseType"
@start-edit="startDetailEdit"
@format-json="formatDetailJsonDraft"
@compact-json="compactDetailJson"
@compare-json="openDetailJsonCompare"
@toggle-formatted="toggleCellDetailJsonFormatted"
@@ -47,6 +47,7 @@ const detailEditValue = defineModel<string>("value", { default: "" });
const emit = defineEmits<{
startEdit: [];
formatJson: [];
compactJson: [];
compareJson: [];
toggleFormatted: [];
@@ -153,6 +154,8 @@ defineExpose({ openSearch });
:unsafe-number="typeof detail.value === 'number' && Number.isInteger(detail.value) && !Number.isSafeInteger(detail.value) && (!editing || detailEditValue === detail.rawValue)"
/>
<Button v-if="editing && showCompareJson" variant="ghost" size="sm" class="h-5 gap-1 px-1.5 text-xs" :disabled="!canCompareJson" :title="t('grid.compareJson')" @mousedown.prevent @click="emit('compareJson')"><FileDiff class="h-3 w-3" />{{ t("grid.compareJson") }}</Button>
<!-- issue #9832:编辑中「压缩 JSON」作用于草稿,格式化入口不能再被 !editing 挡掉,否则压缩后就无法展开。 -->
<Button v-if="showCompactJson" variant="ghost" size="sm" class="h-5 gap-1 px-1.5 text-xs" :disabled="!canCompactJson" :title="t('grid.formatJson')" @click="emit('formatJson')"><Code2 class="h-3 w-3" />{{ t("grid.formatJson") }}</Button>
<Button v-if="showCompactJson" variant="ghost" size="sm" class="h-5 gap-1 px-1.5 text-xs" :disabled="!canCompactJson" :title="t('grid.compactJson')" @click="emit('compactJson')"><Code2 class="h-3 w-3" />{{ t("grid.compactJson") }}</Button>
<Button v-if="!editing && detail.formattedJson" :variant="sideJsonView ? 'secondary' : 'ghost'" size="sm" class="h-5 gap-1 px-1.5 text-xs" :title="t('grid.formattedJson')" @click="emit('toggleFormatted')"><Code2 class="h-3 w-3" />{{ t("grid.formattedJson") }}</Button>
<Button v-if="!editing && detail.isEditable" variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.editValue')" @click="emit('startEdit')"><Pencil class="h-3 w-3" /></Button>
@@ -1864,6 +1864,37 @@ describe("cell detail surfaces", () => {
expect(dataGridSource).toContain(':disabled="!canCompareDetailJson" @mousedown.prevent @click="openDetailJsonCompare"');
expect(dataGridSource).toContain('v-model:open="detailValueDiffOpen" :snapshot="detailValueDiffSnapshot"');
});
// issue #9832:编辑中点「压缩 JSON」会把草稿压成单行,此时必须仍能点「格式化 JSON」
// 重新展开,否则 Mongo 这类对象字段的 JSON 一旦压缩就再也无法格式化。
it("keeps the JSON format action reachable while a compacted draft is being edited", async () => {
const formatJson = vi.fn();
const mounted = mountComponent(DataGridCellDetailPanel, {
detail: detail(),
panelIsBottom: true,
metadataCollapsed: false,
valueFillsHeight: true,
editing: true,
sideJsonView: false,
showCompactJson: true,
canCompactJson: true,
typeColorClass: () => "",
canDownloadBinaryValue: () => false,
downloadBinaryValue: vi.fn(),
canImportBinaryValue: () => false,
importBinaryValue: vi.fn(),
openImagePreview: vi.fn(),
canCopySqlCondition: () => true,
onFormatJson: formatJson,
});
const formatButton = findOne(mounted.root, (node) => node.props.title === "grid.formatJson");
dispatch(formatButton, "click");
expect(formatJson).toHaveBeenCalledOnce();
await mounted.setProps({ showCompactJson: false });
expect(findAll(mounted.root, (node) => node.props.title === "grid.formatJson")).toHaveLength(0);
});
});
describe("DataGridCopyColumnNamesDialog", () => {
@@ -152,4 +152,44 @@ describe("useDataGridCellDetailEdit", () => {
expect(editor.isEditingDetail.value).toBe(false);
expect(editor.detailEditValue.value).toBe("");
});
// issue #9832:单元格详情面板的「格式化 JSON」只重排编辑器草稿,不触发
// 「正在编辑格式化后的 JSON」提示,也不改动原始值。
it("expands a compacted JSON draft without warning about formatted JSON", async () => {
const compact = '{"owner":"zipg","tags":["a"]}';
const activeDetail = ref<DataGridCellDetail | null>(detail(compact));
const syncEditor = vi.fn();
const warnFormattedJsonEdit = vi.fn();
const editor = useDataGridCellDetailEdit({
activeDetail: computed(() => activeDetail.value),
activeTab: ref("valueEditor"),
jsonFormatted: computed(() => false),
databaseType: computed(() => "mongodb"),
resultRows: computed(() => [["id", compact]]),
getColumnInfo: () => undefined,
getRowItem: () => ({ sourceIndex: 0, isNew: false, isDeleted: false }),
hydrateLargeValueCell: async () => true,
applyCellValue: vi.fn(),
restoreCellValue: vi.fn(),
syncEditor,
refreshDetail: vi.fn(),
warnFormattedJsonEdit,
});
await editor.startDetailEdit();
syncEditor.mockClear();
warnFormattedJsonEdit.mockClear();
editor.formatDetailJsonDraft();
expect(editor.detailEditValue.value).toBe('{\n "owner": "zipg",\n "tags": [\n "a"\n ]\n}');
expect(editor.detailEditOriginalValue.value).toBe(compact);
expect(syncEditor).toHaveBeenLastCalledWith('{\n "owner": "zipg",\n "tags": [\n "a"\n ]\n}', "");
expect(warnFormattedJsonEdit).not.toHaveBeenCalled();
syncEditor.mockClear();
editor.detailEditValue.value = "not json";
editor.formatDetailJsonDraft();
expect(editor.detailEditValue.value).toBe("not json");
expect(syncEditor).not.toHaveBeenCalled();
});
});
@@ -203,6 +203,15 @@ export function useDataGridCellDetailEdit(options: UseDataGridCellDetailEditOpti
options.warnFormattedJsonEdit(detail, true);
}
// 与 formatValueEditorJson 相同的草稿格式化,但不弹「正在编辑格式化后的 JSON」
// 提示:用户是在单元格详情面板里主动点「格式化 JSON」展开草稿(issue #9832)。
function formatDetailJsonDraft() {
const detail = options.activeDetail.value;
if (!detail || !canFormatCellDetailJson(detailEditValue.value, detail.type)) return;
detailEditValue.value = formatJsonText(detailEditValue.value) ?? detailEditValue.value;
syncEditorFromDetailEdit();
}
function compactDetailJson() {
const detail = options.activeDetail.value;
if (!detail || !canFormatCellDetailJson(detailEditValue.value, detail.type)) return;
@@ -250,6 +259,7 @@ export function useDataGridCellDetailEdit(options: UseDataGridCellDetailEditOpti
restoreDetailOriginalValue,
setValueEditorNull,
formatValueEditorJson,
formatDetailJsonDraft,
compactDetailJson,
openDetailJsonCompare,
setDetailNull,
Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB