improve dashboard

This commit is contained in:
pa
2026-03-13 11:52:09 +09:00
parent 044c1a42d4
commit 0135d9bb29
6 changed files with 41 additions and 22 deletions

View File

@@ -96,7 +96,6 @@
"delete": "Delete"
},
"toolbar": {
"editing": "Editing Dashboard",
"name_placeholder": "Dashboard Name",
"icon_placeholder": "Icon Class (Optional)"
},

View File

@@ -28,7 +28,7 @@
:dashboard-id="id"
:is-editing="true"
@update-panel="handleUpdatePanel"
@remove-row="handleRemoveRow" />
@remove-panel="handleRemovePanel" />
<div
class="mt-auto flex min-h-[80px] flex-1 items-center justify-center rounded-md border-2 border-dashed border-muted-foreground/20 text-muted-foreground transition-colors hover:border-primary/40 hover:bg-primary/5"
@@ -161,8 +161,14 @@
showAddRowOptions.value = false;
};
const handleRemoveRow = (rowIndex) => {
editRows.value.splice(rowIndex, 1);
const handleRemovePanel = (rowIndex, panelIndex) => {
const row = editRows.value[rowIndex];
if (!row) return;
if (row.panels.length <= 1) {
editRows.value.splice(rowIndex, 1);
} else {
row.panels.splice(panelIndex, 1);
}
};
const handleUpdatePanel = (rowIndex, panelIndex, panelKey) => {

View File

@@ -1,9 +1,8 @@
<template>
<div class="flex items-center gap-2 rounded-md border bg-card px-3 py-2">
<span class="text-sm font-medium text-muted-foreground">{{ t('dashboard.toolbar.editing') }}</span>
<Input
:model-value="name"
:placeholder="t('dashboard.name_placeholder')"
:placeholder="t('dashboard.toolbar.name_placeholder')"
class="mx-2 h-7 max-w-[200px] text-sm"
@update:model-value="emit('update:name', $event)" />
<div class="flex gap-2">

View File

@@ -1,6 +1,14 @@
<template>
<div class="relative flex min-h-0 flex-1 overflow-hidden rounded-md border bg-card">
<template v-if="isEditing">
<Button
v-if="showRemove"
variant="ghost"
size="icon-sm"
class="absolute right-1 top-1 z-20"
@click="emit('remove')">
<X class="size-4" />
</Button>
<div class="flex w-full min-h-0 flex-col gap-2 p-3">
<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" />
@@ -13,7 +21,7 @@
</template>
<template v-else-if="panelKey && panelComponent">
<div class="h-full w-full overflow-y-auto">
<div class="dashboard-panel h-full w-full overflow-y-auto">
<component :is="panelComponent" />
</div>
</template>
@@ -32,6 +40,7 @@
<script setup>
import { computed, ref } from 'vue';
import { X } from 'lucide-vue-next';
import { useI18n } from 'vue-i18n';
import { Button } from '@/components/ui/button';
@@ -48,10 +57,14 @@
isEditing: {
type: Boolean,
default: false
},
showRemove: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['select']);
const emit = defineEmits(['select', 'remove']);
const { t } = useI18n();
const selectorOpen = ref(false);
@@ -87,3 +100,13 @@
selectorOpen.value = false;
};
</script>
<style scoped>
.dashboard-panel :deep(.x-container) {
height: 100%;
margin: 0;
border: none;
border-radius: 0;
background: transparent;
}
</style>

View File

@@ -9,16 +9,10 @@
:key="panelIndex"
:panel-key="panelKey"
:is-editing="true"
:show-remove="true"
:class="panelEditClass"
@select="(key) => emit('update-panel', rowIndex, panelIndex, key)" />
<Button
variant="ghost"
size="icon-sm"
class="absolute right-1 top-2 z-20 bg-background/80"
@click="emit('remove-row', rowIndex)">
<X class="size-4" />
</Button>
@select="(key) => emit('update-panel', rowIndex, panelIndex, key)"
@remove="emit('remove-panel', rowIndex, panelIndex)" />
</div>
<ResizablePanelGroup
@@ -43,9 +37,7 @@
<script setup>
import { computed } from 'vue';
import { X } from 'lucide-vue-next';
import { Button } from '@/components/ui/button';
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable';
import DashboardPanel from './DashboardPanel.vue';
@@ -69,7 +61,7 @@
}
});
const emit = defineEmits(['update-panel', 'remove-row']);
const emit = defineEmits(['update-panel', 'remove-panel']);
const isVertical = computed(() => props.row.direction === 'vertical');

View File

@@ -126,7 +126,7 @@
<Spinner class="text-2xl" />
</div>
<template v-else-if="searchWorldResults.length > 0">
<ItemGroup class="grid grid-cols-5 gap-3">
<ItemGroup class="grid gap-3" style="grid-template-columns: repeat(auto-fill, minmax(180px, 1fr))">
<Item
v-for="world in searchWorldResults"
:key="world.id"
@@ -200,7 +200,7 @@
<Spinner class="text-2xl" />
</div>
<template v-else-if="searchAvatarPage.length > 0">
<ItemGroup class="grid grid-cols-5 gap-3">
<ItemGroup class="grid gap-3" style="grid-template-columns: repeat(auto-fill, minmax(180px, 1fr))">
<Item
v-for="avatar in searchAvatarPage"
:key="avatar.id"