add vertical panel option to dashboard settings page

This commit is contained in:
pa
2026-03-13 09:51:42 +09:00
parent 73493cb0aa
commit bb32b6e92b
5 changed files with 37 additions and 9 deletions
+1
View File
@@ -90,6 +90,7 @@
"add_row": "Add Row", "add_row": "Add Row",
"add_full_row": "Add Full Row", "add_full_row": "Add Full Row",
"add_split_row": "Add Split Row", "add_split_row": "Add Split Row",
"add_vertical_row": "Add Vertical Row",
"cancel": "Cancel", "cancel": "Cancel",
"save": "Save", "save": "Save",
"delete": "Delete" "delete": "Delete"
+3 -1
View File
@@ -24,7 +24,9 @@ function cloneRows(rows) {
if (!panels.length) { if (!panels.length) {
return null; return null;
} }
return { panels }; const direction =
row?.direction === 'vertical' ? 'vertical' : 'horizontal';
return { panels, direction };
}) })
.filter(Boolean); .filter(Boolean);
} }
+14 -2
View File
@@ -39,16 +39,28 @@
<button <button
type="button" type="button"
class="flex h-10 w-16 items-center justify-center rounded-md border-2 border-dashed border-muted-foreground/30 transition-colors hover:border-primary/50 hover:bg-primary/5" class="flex h-10 w-16 items-center justify-center rounded-md border-2 border-dashed border-muted-foreground/30 transition-colors hover:border-primary/50 hover:bg-primary/5"
:title="t('dashboard.actions.add_full_row')"
@click.stop="handleAddRow(1)"> @click.stop="handleAddRow(1)">
<div class="h-6 w-12 rounded bg-muted-foreground/20" /> <div class="h-6 w-12 rounded bg-muted-foreground/20" />
</button> </button>
<button <button
type="button" type="button"
class="flex h-10 w-16 items-center justify-center gap-1 rounded-md border-2 border-dashed border-muted-foreground/30 transition-colors hover:border-primary/50 hover:bg-primary/5" class="flex h-10 w-16 items-center justify-center gap-1 rounded-md border-2 border-dashed border-muted-foreground/30 transition-colors hover:border-primary/50 hover:bg-primary/5"
:title="t('dashboard.actions.add_split_row')"
@click.stop="handleAddRow(2)"> @click.stop="handleAddRow(2)">
<div class="h-6 w-5 rounded bg-muted-foreground/20" /> <div class="h-6 w-5 rounded bg-muted-foreground/20" />
<div class="h-6 w-5 rounded bg-muted-foreground/20" /> <div class="h-6 w-5 rounded bg-muted-foreground/20" />
</button> </button>
<button
type="button"
class="flex h-10 w-16 items-center justify-center gap-1 rounded-md border-2 border-dashed border-muted-foreground/30 transition-colors hover:border-primary/50 hover:bg-primary/5"
:title="t('dashboard.actions.add_vertical_row')"
@click.stop="handleAddRow(2, 'vertical')">
<div class="flex flex-col gap-0.5">
<div class="h-2.5 w-10 rounded bg-muted-foreground/20" />
<div class="h-2.5 w-10 rounded bg-muted-foreground/20" />
</div>
</button>
</div> </div>
<Plus v-else class="size-6 opacity-50" /> <Plus v-else class="size-6 opacity-50" />
</div> </div>
@@ -143,9 +155,9 @@
showAddRowOptions.value = !showAddRowOptions.value; showAddRowOptions.value = !showAddRowOptions.value;
}; };
const handleAddRow = (panelCount) => { const handleAddRow = (panelCount, direction = 'horizontal') => {
const panels = Array(panelCount).fill(null); const panels = Array(panelCount).fill(null);
editRows.value.push({ panels }); editRows.value.push({ panels, direction });
showAddRowOptions.value = false; showAddRowOptions.value = false;
}; };
@@ -2,7 +2,7 @@
<div class="relative flex min-h-0 flex-1 overflow-hidden rounded-md border bg-card"> <div class="relative flex min-h-0 flex-1 overflow-hidden rounded-md border bg-card">
<template v-if="isEditing"> <template v-if="isEditing">
<div class="flex w-full min-h-0 flex-col gap-2 p-3"> <div class="flex w-full min-h-0 flex-col gap-2 p-3">
<div class="flex items-center gap-2 text-xs text-muted-foreground"> <div class="flex flex-1 items-center justify-center gap-2 text-xs text-muted-foreground">
<i v-if="panelIcon" :class="panelIcon" class="text-base" /> <i v-if="panelIcon" :class="panelIcon" class="text-base" />
<span>{{ panelLabel || t('dashboard.panel.not_selected') }}</span> <span>{{ panelLabel || t('dashboard.panel.not_selected') }}</span>
</div> </div>
@@ -1,18 +1,21 @@
<template> <template>
<div class="relative h-full min-h-[180px]"> <div class="relative h-full min-h-[180px]">
<div v-if="isEditing" class="flex h-full gap-2"> <div
v-if="isEditing"
class="flex h-full gap-2"
:class="isVertical ? 'flex-col' : 'flex-row'">
<DashboardPanel <DashboardPanel
v-for="(panelKey, panelIndex) in row.panels" v-for="(panelKey, panelIndex) in row.panels"
:key="panelIndex" :key="panelIndex"
:panel-key="panelKey" :panel-key="panelKey"
:is-editing="true" :is-editing="true"
:class="row.panels.length === 1 ? 'w-full' : 'w-1/2'" :class="panelEditClass"
@select="(key) => emit('update-panel', rowIndex, panelIndex, key)" /> @select="(key) => emit('update-panel', rowIndex, panelIndex, key)" />
<Button <Button
variant="ghost" variant="ghost"
size="icon-sm" size="icon-sm"
class="absolute -right-1 top-2 z-20 bg-background/80" class="absolute right-1 top-2 z-20 bg-background/80"
@click="emit('remove-row', rowIndex)"> @click="emit('remove-row', rowIndex)">
<X class="size-4" /> <X class="size-4" />
</Button> </Button>
@@ -20,7 +23,7 @@
<ResizablePanelGroup <ResizablePanelGroup
v-else-if="row.panels.length === 2" v-else-if="row.panels.length === 2"
direction="horizontal" :direction="isVertical ? 'vertical' : 'horizontal'"
:auto-save-id="`dashboard-${dashboardId}-row-${rowIndex}`" :auto-save-id="`dashboard-${dashboardId}-row-${rowIndex}`"
class="h-full min-h-[180px]"> class="h-full min-h-[180px]">
<ResizablePanel :default-size="50" :min-size="20"> <ResizablePanel :default-size="50" :min-size="20">
@@ -39,6 +42,7 @@
</template> </template>
<script setup> <script setup>
import { computed } from 'vue';
import { X } from 'lucide-vue-next'; import { X } from 'lucide-vue-next';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -46,7 +50,7 @@
import DashboardPanel from './DashboardPanel.vue'; import DashboardPanel from './DashboardPanel.vue';
defineProps({ const props = defineProps({
row: { row: {
type: Object, type: Object,
required: true required: true
@@ -66,4 +70,13 @@
}); });
const emit = defineEmits(['update-panel', 'remove-row']); const emit = defineEmits(['update-panel', 'remove-row']);
const isVertical = computed(() => props.row.direction === 'vertical');
const panelEditClass = computed(() => {
if (props.row.panels.length === 1) {
return 'w-full';
}
return isVertical.value ? 'h-1/2' : 'w-1/2';
});
</script> </script>