feat(grid): compact JSON action in cell detail editor
Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
parent
937131a426
commit
a6df5c1f35
|
|
@ -113,7 +113,7 @@ import { getApplicablePreviewActions } from "@/lib/resultPreviewRegistry";
|
|||
import "@/lib/previewHandlers/geometryMapPreview";
|
||||
import { BINARY_CELL_DOWNLOAD_MODES, binaryCellDisplayText, binaryCellDownloadFileName, binaryCellDownloadPayload, canDownloadBinaryCellValue, downloadBinaryCellPayload, isBinaryCellColumnType, parseBinaryCellBytes, type BinaryCellDownloadMode } from "@/lib/binaryCellDownload";
|
||||
import { buildBinaryHexViewRows } from "@/lib/binaryHexViewer";
|
||||
import { canFormatCellDetailJson, cellDetailEditorText, defaultCellDetailTab, formatJsonText, isGeometryColumnType, linkedCellDetailTarget, valueEditorActions, visibleCellDetailTabs, type CellDetailTab } from "@/lib/cellDetailPresentation";
|
||||
import { canFormatCellDetailJson, cellDetailEditorText, compactJsonText, defaultCellDetailTab, formatJsonText, isGeometryColumnType, linkedCellDetailTarget, looksLikeJsonContainerText, valueEditorActions, visibleCellDetailTabs, type CellDetailTab } from "@/lib/cellDetailPresentation";
|
||||
import { renderWktOnCanvas, isHexGeometry } from "@/lib/geometryPreview";
|
||||
import { buildDataGridCellDetail, buildDataGridColumnDetail, buildDataGridRowDetail, dataGridColumnDetailJson, dataGridColumnDetailTsv, dataGridRowDetailJson, dataGridRowDetailTsv, filterDataGridDetailFields, type DataGridCellDetail } from "@/lib/dataGridDetail";
|
||||
import { applyColumnFormatter, buildColumnFormatterKey, normalizeColumnFormatter, resolveColumnFormatter, type ColumnFormatterConfig, type DateTimeFormatterUnit, DateTimePatterns } from "@/lib/columnFormatter";
|
||||
|
|
@ -4587,6 +4587,15 @@ const sideJsonPreviewText = computed(() => {
|
|||
if (!detail?.formattedJson) return "";
|
||||
return sideDetailJsonView.value ? detail.formattedJson : detail.rawValuePreview;
|
||||
});
|
||||
const canCompactDetailJson = computed(() => {
|
||||
const detail = activeCellDetail.value;
|
||||
return !!detail && isEditingDetail.value && canFormatCellDetailJson(detailEditValue.value, detail.type);
|
||||
});
|
||||
const showCompactDetailJson = computed(() => {
|
||||
const detail = activeCellDetail.value;
|
||||
if (!detail || !isEditingDetail.value) return false;
|
||||
return !!detail.formattedJson || looksLikeJsonContainerText(detailEditValue.value);
|
||||
});
|
||||
|
||||
// CodeMirror-based cell detail editors
|
||||
const detailsEditorContainer = ref<HTMLElement>();
|
||||
|
|
@ -4821,6 +4830,13 @@ function formatValueEditorJson() {
|
|||
warnFormattedJsonEditIfNeeded(detail, true);
|
||||
}
|
||||
|
||||
function compactDetailJson() {
|
||||
const detail = activeCellDetail.value;
|
||||
if (!detail || !canFormatCellDetailJson(detailEditValue.value, detail.type)) return;
|
||||
detailEditValue.value = compactJsonText(detailEditValue.value) ?? detailEditValue.value;
|
||||
syncEditorFromDetailEdit();
|
||||
}
|
||||
|
||||
function setDetailNull() {
|
||||
const detail = activeCellDetail.value;
|
||||
if (!detail || !detail.isEditable) return;
|
||||
|
|
@ -9737,18 +9753,22 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
|||
<div class="space-y-1" :class="[{ 'min-h-0 flex flex-col': sideDetailValueFillsHeight }, sideDetailValueFillsHeight && !(activeCellDetail.imagePreviewUrl && !isEditingDetail) ? 'flex-1' : '', activeCellDetail.imagePreviewUrl && !isEditingDetail ? 'shrink-0' : '']">
|
||||
<div class="flex min-h-5 items-center justify-between gap-2">
|
||||
<div class="text-muted-foreground">{{ t("grid.cellValue") }}</div>
|
||||
<div v-if="!isEditingDetail" class="flex items-center gap-1">
|
||||
<Button v-if="activeCellDetail.formattedJson" :variant="sideDetailJsonView ? 'secondary' : 'ghost'" size="sm" class="h-5 gap-1 px-1.5 text-xs" :title="t('grid.formattedJson')" @click="toggleCellDetailJsonFormatted">
|
||||
<div class="flex items-center gap-1">
|
||||
<Button v-if="showCompactDetailJson" variant="ghost" size="sm" class="h-5 gap-1 px-1.5 text-xs" :disabled="!canCompactDetailJson" :title="t('grid.compactJson')" @click="compactDetailJson">
|
||||
<Code2 class="h-3 w-3" />
|
||||
{{ t("grid.compactJson") }}
|
||||
</Button>
|
||||
<Button v-if="!isEditingDetail && activeCellDetail.formattedJson" :variant="sideDetailJsonView ? 'secondary' : 'ghost'" size="sm" class="h-5 gap-1 px-1.5 text-xs" :title="t('grid.formattedJson')" @click="toggleCellDetailJsonFormatted">
|
||||
<Code2 class="h-3 w-3" />
|
||||
{{ t("grid.formattedJson") }}
|
||||
</Button>
|
||||
<Button v-if="activeCellDetail.isEditable" variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.editValue')" @click="startDetailEdit">
|
||||
<Button v-if="!isEditingDetail && activeCellDetail.isEditable" variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.editValue')" @click="startDetailEdit">
|
||||
<Pencil class="h-3 w-3" />
|
||||
</Button>
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.copyValue')" @click="copyDetailCurrentValue">
|
||||
<Button v-if="!isEditingDetail" variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.copyValue')" @click="copyDetailCurrentValue">
|
||||
<Copy class="h-3 w-3" />
|
||||
</Button>
|
||||
<DropdownMenu v-if="canDownloadDetailBinaryValue(activeCellDetail)">
|
||||
<DropdownMenu v-if="!isEditingDetail && canDownloadDetailBinaryValue(activeCellDetail)">
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.downloadBinaryValue')">
|
||||
<Download class="h-3 w-3" />
|
||||
|
|
|
|||
|
|
@ -813,6 +813,7 @@ export default {
|
|||
copyColumnTsv: "Copy Column (TSV)",
|
||||
editValue: "Edit Value",
|
||||
formatJson: "Format JSON",
|
||||
compactJson: "Compact JSON",
|
||||
formattedJsonEditWarning: "You are editing formatted JSON. Saving will write it as JSON, so the original formatting may change.",
|
||||
setNull: "Set NULL",
|
||||
restoreOriginalValue: "Restore Original",
|
||||
|
|
|
|||
|
|
@ -816,6 +816,7 @@ export default withEnglishFallback({
|
|||
copyColumnTsv: "复制列 (TSV)",
|
||||
editValue: "编辑值",
|
||||
formatJson: "格式化 JSON",
|
||||
compactJson: "压缩 JSON",
|
||||
formattedJsonEditWarning: "正在编辑格式化后的 JSON。保存后会以JSON格式写入,原始排版可能变化。",
|
||||
setNull: "设为 NULL",
|
||||
restoreOriginalValue: "恢复原值",
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export function canFormatCellDetailJson(value: unknown, columnType?: string): bo
|
|||
const text = cellDetailRawEditorText(value);
|
||||
if (text.length > CELL_DETAIL_JSON_FORMAT_MAX_LENGTH) return false;
|
||||
if (isJsonColumnType(columnType)) return !!formatJsonText(text);
|
||||
return typeof value === "string" && looksLikeJsonContainer(text) && !!formatJsonText(text);
|
||||
return typeof value === "string" && looksLikeJsonContainerText(text) && !!formatJsonText(text);
|
||||
}
|
||||
|
||||
export function formatJsonText(text: string): string | undefined {
|
||||
|
|
@ -96,7 +96,18 @@ export function formatJsonText(text: string): string | undefined {
|
|||
}
|
||||
}
|
||||
|
||||
function looksLikeJsonContainer(text: string): boolean {
|
||||
export function compactJsonText(text: string): string | undefined {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed) return undefined;
|
||||
if (trimmed.length > CELL_DETAIL_JSON_FORMAT_MAX_LENGTH) return undefined;
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(trimmed));
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function looksLikeJsonContainerText(text: string): boolean {
|
||||
const trimmed = text.trim();
|
||||
return trimmed.startsWith("{") || trimmed.startsWith("[");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue