up OLAPConstructor.vue
This commit is contained in:
@@ -106,8 +106,8 @@
|
|||||||
|
|
||||||
<!-- Правая часть -->
|
<!-- Правая часть -->
|
||||||
<div class="flex-1 overflow-x-auto">
|
<div class="flex-1 overflow-x-auto">
|
||||||
<div class="card p-3 mb-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3 items-end">
|
<div class="card p-3 mb-4">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-3 items-end">
|
||||||
<!-- Тип отчета -->
|
<!-- Тип отчета -->
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<label class="text-xs text-gray-500">Тип отчета</label>
|
<label class="text-xs text-gray-500">Тип отчета</label>
|
||||||
@@ -147,63 +147,69 @@
|
|||||||
|
|
||||||
<!-- Опции справа -->
|
<!-- Опции справа -->
|
||||||
<div class="flex items-center justify-end gap-2 h-full col-span-2 md:col-span-3 lg:col-span-2">
|
<div class="flex items-center justify-end gap-2 h-full col-span-2 md:col-span-3 lg:col-span-2">
|
||||||
|
|
||||||
<!-- Summary -->
|
|
||||||
<label
|
<label
|
||||||
class="flex items-center gap-2 px-2.5 h-[30px] rounded-md border cursor-pointer transition
|
class="flex items-center gap-2 px-2.5 h-[30px] rounded-md border cursor-pointer transition hover:bg-gray-50 text-xs"
|
||||||
hover:bg-gray-50 text-xs"
|
:class="buildSummary ? 'bg-primary-50 border-primary-300 text-primary-700' : 'border-gray-200 text-gray-600'">
|
||||||
:class="buildSummary
|
|
||||||
? 'bg-primary-50 border-primary-300 text-primary-700'
|
|
||||||
: 'border-gray-200 text-gray-600'">
|
|
||||||
|
|
||||||
<input type="checkbox" v-model="buildSummary" class="hidden">
|
<input type="checkbox" v-model="buildSummary" class="hidden">
|
||||||
|
|
||||||
<div class="w-3.5 h-3.5 rounded border flex items-center justify-center transition"
|
<div class="w-3.5 h-3.5 rounded border flex items-center justify-center transition"
|
||||||
:class="buildSummary
|
:class="buildSummary ? 'bg-primary-600 border-primary-600' : 'border-gray-400 bg-white'">
|
||||||
? 'bg-primary-600 border-primary-600'
|
<svg v-if="buildSummary" class="w-2.5 h-2.5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
: 'border-gray-400 bg-white'">
|
|
||||||
|
|
||||||
<svg v-if="buildSummary"
|
|
||||||
class="w-2.5 h-2.5 text-white"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="font-medium">Summary</span>
|
<span class="font-medium">Summary</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<!-- Активно -->
|
|
||||||
<label
|
<label
|
||||||
class="flex items-center gap-2 px-2.5 h-[30px] rounded-md border cursor-pointer transition
|
class="flex items-center gap-2 px-2.5 h-[30px] rounded-md border cursor-pointer transition hover:bg-gray-50 text-xs"
|
||||||
hover:bg-gray-50 text-xs"
|
:class="active ? 'bg-green-50 border-green-300 text-green-700' : 'border-gray-200 text-gray-600'">
|
||||||
:class="active
|
|
||||||
? 'bg-green-50 border-green-300 text-green-700'
|
|
||||||
: 'border-gray-200 text-gray-600'">
|
|
||||||
|
|
||||||
<input type="checkbox" v-model="active" class="hidden">
|
<input type="checkbox" v-model="active" class="hidden">
|
||||||
|
|
||||||
<div class="w-3.5 h-3.5 rounded border flex items-center justify-center transition"
|
<div class="w-3.5 h-3.5 rounded border flex items-center justify-center transition"
|
||||||
:class="active
|
:class="active ? 'bg-green-600 border-green-600' : 'border-gray-400 bg-white'">
|
||||||
? 'bg-green-600 border-green-600'
|
<svg v-if="active" class="w-2.5 h-2.5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
: 'border-gray-400 bg-white'">
|
|
||||||
|
|
||||||
<svg v-if="active"
|
|
||||||
class="w-2.5 h-2.5 text-white"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="font-medium">Активно</span>
|
<span class="font-medium">Активно</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Дополнительные настройки: имя запроса, рестораны, БД -->
|
||||||
|
<div class="mt-4 pt-3 border-t border-gray-100">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<!-- Имя запроса -->
|
||||||
|
<div>
|
||||||
|
<label class="text-xs text-gray-500">Имя запроса</label>
|
||||||
|
<input type="text" v-model="queryName" placeholder="Например: Продажи по дням" class="input-field py-1.5 text-sm w-full" />
|
||||||
|
</div>
|
||||||
|
<!-- Рестораны -->
|
||||||
|
<div>
|
||||||
|
<label class="text-xs text-gray-500">Рестораны (можно несколько)</label>
|
||||||
|
<button @click="openRestaurantModal" class="btn-secondary py-1.5 text-sm w-full flex justify-between items-center">
|
||||||
|
<span>{{ selectedRestaurants.length ? `Выбрано: ${selectedRestaurants.length}` : 'Выбрать рестораны' }}</span>
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div v-if="selectedRestaurants.length" class="flex flex-wrap gap-1 mt-1">
|
||||||
|
<span v-for="r in selectedRestaurants" :key="r.id" class="text-xs bg-gray-100 px-1.5 py-0.5 rounded">{{ r.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Подключение к БД -->
|
||||||
|
<div>
|
||||||
|
<label class="text-xs text-gray-500">Подключение к БД</label>
|
||||||
|
<button @click="openDbConnectionModal" class="btn-secondary py-1.5 text-sm w-full flex justify-between items-center">
|
||||||
|
<span>{{ selectedDbConnection ? selectedDbConnection.name : 'Выбрать подключение' }}</span>
|
||||||
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Вкладки -->
|
<!-- Вкладки -->
|
||||||
<div class="card overflow-hidden p-2">
|
<div class="card overflow-hidden p-2">
|
||||||
<div class="flex border-b border-gray-200">
|
<div class="flex border-b border-gray-200">
|
||||||
@@ -385,6 +391,113 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
|
<!-- Модалка выбора ресторанов (множественный) -->
|
||||||
|
<Transition name="fade">
|
||||||
|
<div v-if="restaurantModal.show" class="fixed inset-0 z-50 overflow-y-auto" @click.self="closeRestaurantModal">
|
||||||
|
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
|
||||||
|
<div class="flex items-center justify-center min-h-screen p-4">
|
||||||
|
<div class="relative bg-white rounded-2xl shadow-xl max-w-lg w-full max-h-[90vh] flex flex-col">
|
||||||
|
<div class="flex justify-between items-center p-6 border-b">
|
||||||
|
<h3 class="text-xl font-bold text-gray-900">Выбор ресторанов</h3>
|
||||||
|
<button @click="closeRestaurantModal" class="text-gray-400 hover:text-gray-600">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-b">
|
||||||
|
<div class="relative">
|
||||||
|
<svg class="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||||
|
</svg>
|
||||||
|
<input v-model="restaurantModal.search" type="text" class="input-field pl-9" placeholder="Поиск по названию или хосту" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-y-auto p-2 space-y-2">
|
||||||
|
<div v-for="rest in filteredRestaurantsList" :key="rest.id"
|
||||||
|
@click="toggleRestaurantSelection(rest)"
|
||||||
|
class="flex items-center justify-between p-4 rounded-xl border cursor-pointer transition-all hover:shadow-md"
|
||||||
|
:class="isRestaurantSelected(rest) ? 'border-primary-500 bg-primary-50' : 'border-gray-200'">
|
||||||
|
<div class="flex items-center space-x-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-gray-100 flex items-center justify-center">
|
||||||
|
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="font-medium text-gray-900">{{ rest.name }}</p>
|
||||||
|
<p class="text-sm text-gray-500">{{ rest.host }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="isRestaurantSelected(rest)" class="text-primary-600">
|
||||||
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="filteredRestaurantsList.length === 0" class="text-center py-8 text-gray-500">
|
||||||
|
Рестораны не найдены
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end space-x-3 p-6 border-t bg-gray-50 rounded-b-2xl">
|
||||||
|
<button @click="closeRestaurantModal" class="btn-secondary">Отмена</button>
|
||||||
|
<button @click="confirmRestaurants" class="btn-primary">Подтвердить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
|
||||||
|
<!-- Модалка выбора подключения к БД (одиночный) -->
|
||||||
|
<Transition name="fade">
|
||||||
|
<div v-if="dbConnectionModal.show" class="fixed inset-0 z-50 overflow-y-auto" @click.self="closeDbConnectionModal">
|
||||||
|
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm"></div>
|
||||||
|
<div class="flex items-center justify-center min-h-screen p-4">
|
||||||
|
<div class="relative bg-white rounded-2xl shadow-xl max-w-lg w-full max-h-[90vh] flex flex-col">
|
||||||
|
<div class="flex justify-between items-center p-6 border-b">
|
||||||
|
<h3 class="text-xl font-bold text-gray-900">Подключение к БД</h3>
|
||||||
|
<button @click="closeDbConnectionModal" class="text-gray-400 hover:text-gray-600">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-b">
|
||||||
|
<div class="relative">
|
||||||
|
<svg class="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||||
|
</svg>
|
||||||
|
<input v-model="dbConnectionModal.search" type="text" class="input-field pl-9" placeholder="Поиск по имени" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-y-auto p-2 space-y-2">
|
||||||
|
<div v-for="conn in filteredDbConnectionsList" :key="conn.id"
|
||||||
|
@click="selectDbConnection(conn)"
|
||||||
|
class="flex items-center justify-between p-4 rounded-xl border cursor-pointer transition-all hover:shadow-md"
|
||||||
|
:class="tempSelectedDbConnection?.id === conn.id ? 'border-primary-500 bg-primary-50' : 'border-gray-200'">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p class="font-medium text-gray-900">{{ conn.name }}</p>
|
||||||
|
<p class="text-sm text-gray-500">{{ conn.type }} | {{ conn.host }}:{{ conn.port }}/{{ conn.database }}</p>
|
||||||
|
</div>
|
||||||
|
<div v-if="tempSelectedDbConnection?.id === conn.id" class="text-primary-600">
|
||||||
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="filteredDbConnectionsList.length === 0" class="text-center py-8 text-gray-500">
|
||||||
|
Подключения не найдены
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end space-x-3 p-6 border-t bg-gray-50 rounded-b-2xl">
|
||||||
|
<button @click="closeDbConnectionModal" class="btn-secondary">Отмена</button>
|
||||||
|
<button @click="confirmDbConnection" class="btn-primary">Подтвердить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -395,7 +508,7 @@ import { useNotification } from '@/composables/useNotification'
|
|||||||
|
|
||||||
const { showNotification } = useNotification()
|
const { showNotification } = useNotification()
|
||||||
|
|
||||||
// Типы (без изменений)
|
// Типы
|
||||||
interface ApiColumn {
|
interface ApiColumn {
|
||||||
fieldKey: string
|
fieldKey: string
|
||||||
fieldKeyNormal: string
|
fieldKeyNormal: string
|
||||||
@@ -456,7 +569,23 @@ interface IikoConfig {
|
|||||||
filters: Record<string, IikoConfigFilter>
|
filters: Record<string, IikoConfigFilter>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refs
|
interface Restaurant {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
host: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DbConnection {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
host: string
|
||||||
|
port: number
|
||||||
|
database: string
|
||||||
|
user: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Состояния
|
||||||
const columnsData = ref<ApiColumn[]>([])
|
const columnsData = ref<ApiColumn[]>([])
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
@@ -477,22 +606,126 @@ const reportType = ref<'SALES' | 'DELIVERIES' | 'TRANSACTIONS'>('SALES')
|
|||||||
const buildSummary = ref(false)
|
const buildSummary = ref(false)
|
||||||
const searchQuery = ref('')
|
const searchQuery = ref('')
|
||||||
const activeTab = ref<'table' | 'sql'>('table')
|
const activeTab = ref<'table' | 'sql'>('table')
|
||||||
|
const collapsed = ref({ number: false, category: false, filter: false })
|
||||||
|
|
||||||
// Состояние сворачивания секций
|
const queryName = ref('') // имя запроса
|
||||||
const collapsed = ref({
|
const selectedRestaurants = ref<Restaurant[]>([]) // выбранные рестораны
|
||||||
number: false,
|
const selectedDbConnection = ref<DbConnection | null>(null) // выбранное подключение к БД
|
||||||
category: false,
|
|
||||||
filter: false
|
// Модалка ресторанов
|
||||||
|
const restaurantModal = ref({
|
||||||
|
show: false,
|
||||||
|
search: ''
|
||||||
})
|
})
|
||||||
|
const restaurantsList = ref<Restaurant[]>([])
|
||||||
|
const tempSelectedRestaurants = ref<Restaurant[]>([])
|
||||||
|
|
||||||
|
// Модалка подключения к БД
|
||||||
|
const dbConnectionModal = ref({
|
||||||
|
show: false,
|
||||||
|
search: ''
|
||||||
|
})
|
||||||
|
const dbConnectionsList = ref<DbConnection[]>([])
|
||||||
|
const tempSelectedDbConnection = ref<DbConnection | null>(null)
|
||||||
|
|
||||||
|
// Вспомогательные вычисляемые свойства для модалок
|
||||||
|
const filteredRestaurantsList = computed(() => {
|
||||||
|
if (!restaurantModal.value.search.trim()) return restaurantsList.value
|
||||||
|
const lower = restaurantModal.value.search.toLowerCase()
|
||||||
|
return restaurantsList.value.filter(r =>
|
||||||
|
r.name.toLowerCase().includes(lower) || r.host.toLowerCase().includes(lower)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const filteredDbConnectionsList = computed(() => {
|
||||||
|
if (!dbConnectionModal.value.search.trim()) return dbConnectionsList.value
|
||||||
|
const lower = dbConnectionModal.value.search.toLowerCase()
|
||||||
|
return dbConnectionsList.value.filter(c => c.name.toLowerCase().includes(lower))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Функции для ресторанов
|
||||||
|
const openRestaurantModal = async () => {
|
||||||
|
await loadRestaurants()
|
||||||
|
// Копируем текущие выбранные рестораны во временный массив
|
||||||
|
tempSelectedRestaurants.value = [...selectedRestaurants.value]
|
||||||
|
restaurantModal.value.search = ''
|
||||||
|
restaurantModal.value.show = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeRestaurantModal = () => {
|
||||||
|
restaurantModal.value.show = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRestaurantSelected = (rest: Restaurant) => {
|
||||||
|
return tempSelectedRestaurants.value.some(r => r.id === rest.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleRestaurantSelection = (rest: Restaurant) => {
|
||||||
|
const idx = tempSelectedRestaurants.value.findIndex(r => r.id === rest.id)
|
||||||
|
if (idx === -1) {
|
||||||
|
tempSelectedRestaurants.value.push(rest)
|
||||||
|
} else {
|
||||||
|
tempSelectedRestaurants.value.splice(idx, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmRestaurants = () => {
|
||||||
|
selectedRestaurants.value = [...tempSelectedRestaurants.value]
|
||||||
|
closeRestaurantModal()
|
||||||
|
showNotification('Рестораны выбраны', 'success')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функции для подключения к БД
|
||||||
|
const openDbConnectionModal = async () => {
|
||||||
|
await loadDbConnections()
|
||||||
|
tempSelectedDbConnection.value = selectedDbConnection.value ? { ...selectedDbConnection.value } : null
|
||||||
|
dbConnectionModal.value.search = ''
|
||||||
|
dbConnectionModal.value.show = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeDbConnectionModal = () => {
|
||||||
|
dbConnectionModal.value.show = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectDbConnection = (conn: DbConnection) => {
|
||||||
|
tempSelectedDbConnection.value = conn
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmDbConnection = () => {
|
||||||
|
selectedDbConnection.value = tempSelectedDbConnection.value ? { ...tempSelectedDbConnection.value } : null
|
||||||
|
closeDbConnectionModal()
|
||||||
|
showNotification('Подключение к БД выбрано', 'success')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузка данных для модалок
|
||||||
|
const loadRestaurants = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/admin/restaurants')
|
||||||
|
if (!res.ok) throw new Error('Ошибка загрузки ресторанов')
|
||||||
|
const data = await res.json()
|
||||||
|
restaurantsList.value = data
|
||||||
|
} catch (err: any) {
|
||||||
|
showNotification('Не удалось загрузить список ресторанов', 'error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadDbConnections = async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/admin/database-connections')
|
||||||
|
if (!res.ok) throw new Error('Ошибка загрузки подключений')
|
||||||
|
const data = await res.json()
|
||||||
|
dbConnectionsList.value = data
|
||||||
|
} catch (err: any) {
|
||||||
|
showNotification('Не удалось загрузить список подключений к БД', 'error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const toggleSection = (section: 'number' | 'category' | 'filter') => {
|
const toggleSection = (section: 'number' | 'category' | 'filter') => {
|
||||||
collapsed.value[section] = !collapsed.value[section]
|
collapsed.value[section] = !collapsed.value[section]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Модалка сброса
|
|
||||||
const resetModal = ref({ show: false })
|
const resetModal = ref({ show: false })
|
||||||
|
|
||||||
// Drag & drop state
|
|
||||||
let draggedItem: AvailableField | null = null
|
let draggedItem: AvailableField | null = null
|
||||||
let draggedFromSidebar = true
|
let draggedFromSidebar = true
|
||||||
const dragOverZone = ref<string | null>(null)
|
const dragOverZone = ref<string | null>(null)
|
||||||
@@ -784,6 +1017,9 @@ const confirmReset = () => {
|
|||||||
tableNameTouched.value = false
|
tableNameTouched.value = false
|
||||||
buildSummary.value = false
|
buildSummary.value = false
|
||||||
searchQuery.value = ''
|
searchQuery.value = ''
|
||||||
|
queryName.value = ''
|
||||||
|
selectedRestaurants.value = []
|
||||||
|
selectedDbConnection.value = null
|
||||||
showNotification('Все настройки сброшены', 'success')
|
showNotification('Все настройки сброшены', 'success')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user