fix: optimize query cell detail panel layout
* fix: improve cell detail editor layout * test: update cell detail drawer default --------- Co-authored-by: staff <staff@qimaos-MacBook-Pro.local>
This commit is contained in:
1 parent
902419a3b9
commit
96aada2631
4 files changed
+34
-28
No files matched your search
@@ -7817,7 +7817,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
</div>
|
||||
|
||||
<TabsContent value="details" class="m-0 min-h-0 flex-1 flex flex-col">
|
||||
<div data-native-clipboard class="flex-1 min-h-0 overflow-auto p-3 text-xs space-y-3">
|
||||
<div data-native-clipboard class="flex-1 min-h-0 overflow-auto p-3 text-xs" :class="isEditingDetail ? 'flex flex-col gap-3' : 'space-y-3'">
|
||||
<div v-if="cellDetailPanelIsBottom" class="grid grid-cols-[minmax(180px,1.6fr)_repeat(4,minmax(74px,0.55fr))_minmax(160px,1fr)] gap-3 rounded border bg-muted/20 p-2">
|
||||
<div class="min-w-0 space-y-1">
|
||||
<div class="text-muted-foreground">{{ t("grid.columnName") }}</div>
|
||||
@@ -7882,23 +7882,23 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="space-y-1" :class="cellDetailPanelIsBottom ? 'min-h-0' : ''">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="space-y-1" :class="[{ 'min-h-0 flex flex-col': cellDetailPanelIsBottom || isEditingDetail }, isEditingDetail ? 'flex-1' : '']">
|
||||
<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-6 gap-1 px-2 text-xs" :title="t('grid.formattedJson')" @click="sideDetailJsonView = !sideDetailJsonView">
|
||||
<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="sideDetailJsonView = !sideDetailJsonView">
|
||||
<Code2 class="h-3 w-3" />
|
||||
{{ t("grid.formattedJson") }}
|
||||
</Button>
|
||||
<Button v-if="activeCellDetail.isEditable" variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.editValue')" @click="startDetailEdit">
|
||||
<Button v-if="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-6 w-6" :title="t('grid.copyValue')" @click="copyDetailCurrentValue">
|
||||
<Button 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)">
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.downloadBinaryValue')">
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.downloadBinaryValue')">
|
||||
<Download class="h-3 w-3" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
@@ -7911,7 +7911,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
<!-- Skip hex fallback from backend (unsupported geometry types like TIN/Triangle) -->
|
||||
<Popover v-if="isGeometryColumnType(activeCellDetail.type) && activeCellDetail.value !== null && !isEditingDetail && !isHexGeometry(activeCellDetail.value as string)" v-model:open="sideGeometryPreviewOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-6 w-6" :title="t('grid.geometryPreview')">
|
||||
<Button variant="ghost" size="icon" class="h-5 w-5" :title="t('grid.geometryPreview')">
|
||||
<Eye class="h-3 w-3" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
@@ -7928,15 +7928,9 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
</a>
|
||||
</div>
|
||||
<template v-if="isEditingDetail">
|
||||
<TemporalCellEditor v-if="detailTemporalEditorKind" v-model="detailEditValue" :kind="detailTemporalEditorKind" variant="inline" :commit-on-close="false" @cancel="cancelDetailEdit" @commit="commitDetailEdit" />
|
||||
<div v-else ref="detailsEditorContainer" data-cell-detail-editor-root class="w-full rounded border overflow-hidden" :class="cellDetailPanelIsBottom ? 'h-28' : 'h-40'" />
|
||||
<div class="flex gap-1 mt-1">
|
||||
<Button size="sm" class="h-6 text-xs" @click="commitDetailEdit">
|
||||
{{ t("dangerDialog.confirm") }}
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" class="h-6 text-xs" @click="cancelDetailEdit">
|
||||
{{ t("dangerDialog.cancel") }}
|
||||
</Button>
|
||||
<div class="min-h-0 flex-1">
|
||||
<TemporalCellEditor v-if="detailTemporalEditorKind" v-model="detailEditValue" :kind="detailTemporalEditorKind" variant="inline" :commit-on-close="false" @cancel="cancelDetailEdit" @commit="commitDetailEdit" />
|
||||
<div v-else ref="detailsEditorContainer" data-cell-detail-editor-root class="min-h-0 h-full w-full rounded border overflow-hidden" />
|
||||
</div>
|
||||
</template>
|
||||
<pre v-else class="overflow-auto rounded border bg-muted/20 p-2 font-mono text-xs whitespace-pre-wrap break-words cursor-pointer hover:border-primary/50" :class="{ 'cursor-text': activeCellDetail.isEditable }" @dblclick="startDetailEdit">{{
|
||||
@@ -7952,10 +7946,20 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t p-2 grid gap-1" :class="cellDetailPanelIsBottom ? 'grid-cols-[repeat(3,max-content)] justify-end' : 'grid-cols-1'">
|
||||
<Button v-if="activeCellDetail.isEditable && activeCellDetail.value !== null" variant="ghost" size="sm" class="h-7 justify-start text-xs" @click="setDetailNull"> <X class="w-3 h-3 mr-2" /> {{ t("grid.setNull") }} </Button>
|
||||
<Button variant="ghost" size="sm" class="h-7 justify-start text-xs" @click="copyDetailColumnName"> <Copy class="w-3 h-3 mr-2" /> {{ t("grid.copyColumnName") }} </Button>
|
||||
<Button variant="ghost" size="sm" class="h-7 justify-start text-xs" :disabled="!canCopyPreparedDetailSqlCondition()" @click="copyDetailSqlCondition"> <Code2 class="w-3 h-3 mr-2" /> {{ t("grid.copySqlCondition") }} </Button>
|
||||
<div class="border-t p-1.5 flex gap-1" :class="cellDetailPanelIsBottom ? 'items-center' : 'flex-col'">
|
||||
<div v-if="isEditingDetail" class="flex shrink-0 gap-1" :class="cellDetailPanelIsBottom ? 'mr-auto' : ''">
|
||||
<Button size="sm" class="h-6 text-xs" @click="commitDetailEdit">
|
||||
{{ t("dangerDialog.confirm") }}
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" class="h-6 text-xs" @click="cancelDetailEdit">
|
||||
{{ t("dangerDialog.cancel") }}
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex gap-1" :class="cellDetailPanelIsBottom ? 'ml-auto shrink-0 justify-end' : 'flex-col'">
|
||||
<Button v-if="activeCellDetail.isEditable && activeCellDetail.value !== null" variant="ghost" size="sm" class="h-6 justify-start text-xs" @click="setDetailNull"> <X class="w-3 h-3 mr-2" /> {{ t("grid.setNull") }} </Button>
|
||||
<Button variant="ghost" size="sm" class="h-6 justify-start text-xs" @click="copyDetailColumnName"> <Copy class="w-3 h-3 mr-2" /> {{ t("grid.copyColumnName") }} </Button>
|
||||
<Button variant="ghost" size="sm" class="h-6 justify-start text-xs" :disabled="!canCopyPreparedDetailSqlCondition()" @click="copyDetailSqlCondition"> <Code2 class="w-3 h-3 mr-2" /> {{ t("grid.copySqlCondition") }} </Button>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
|
||||
@@ -135,6 +135,8 @@ const { t } = useI18n();
|
||||
const queryStore = useQueryStore();
|
||||
const connectionStore = useConnectionStore();
|
||||
const { toast } = useToast();
|
||||
const DEFAULT_QUERY_RESULTS_PANE_SIZE = 68;
|
||||
const DEFAULT_QUERY_EDITOR_PANE_SIZE = 100 - DEFAULT_QUERY_RESULTS_PANE_SIZE;
|
||||
|
||||
onMounted(() => {
|
||||
const preload = () => preloadDataGridComponent();
|
||||
@@ -537,7 +539,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
<!-- Query mode: editor + results -->
|
||||
<template v-if="activeTab.mode === 'query'">
|
||||
<Splitpanes horizontal class="query-output-splitpanes flex-1 min-h-0 overflow-hidden">
|
||||
<Pane class="min-h-0" :size="resultsPaneOpen ? 40 : 100" :min-size="resultsPaneOpen ? 15 : 100">
|
||||
<Pane class="min-h-0" :size="resultsPaneOpen ? DEFAULT_QUERY_EDITOR_PANE_SIZE : 100" :min-size="resultsPaneOpen ? 15 : 100">
|
||||
<div class="h-full flex flex-col relative">
|
||||
<QueryEditor
|
||||
ref="queryEditorRef"
|
||||
@@ -574,7 +576,7 @@ defineExpose({ focusSearch, refreshData, handleModRTarget, requestQueryEditorExe
|
||||
</Button>
|
||||
</div>
|
||||
</Pane>
|
||||
<Pane v-if="resultsPaneOpen" class="min-h-0" :size="60" :min-size="20">
|
||||
<Pane v-if="resultsPaneOpen" class="min-h-0" :size="DEFAULT_QUERY_RESULTS_PANE_SIZE" :min-size="20">
|
||||
<div class="h-full flex flex-col">
|
||||
<div v-if="hasQueryOutput" class="flex h-10 shrink-0 items-center gap-1 border-b bg-muted/20 px-2">
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
|
||||
Reference in new issue
Block a user