feat: Оптимизация навигации AdminJS в логические группы
- Объединены ресурсы в 5 логических групп: Контент сайта, Бронирования, Отзывы и рейтинги, Персонал и гиды, Администрирование - Удалены дублирующие настройки navigation для чистой группировки - Добавлены CSS стили для визуального отображения иерархии с отступами - Добавлены эмодзи-иконки для каждого типа ресурсов через CSS - Улучшена навигация с правильной вложенностью элементов
This commit is contained in:
22
database/guide-schedules-migration.sql
Normal file
22
database/guide-schedules-migration.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Создание таблицы расписания работы гидов
|
||||
CREATE TABLE IF NOT EXISTS guide_schedules (
|
||||
id SERIAL PRIMARY KEY,
|
||||
guide_id INTEGER NOT NULL REFERENCES guides(id) ON DELETE CASCADE,
|
||||
work_date DATE NOT NULL,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Уникальный индекс для предотвращения дублирования
|
||||
UNIQUE(guide_id, work_date)
|
||||
);
|
||||
|
||||
-- Индексы для оптимизации запросов
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_schedules_guide_id ON guide_schedules(guide_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_schedules_work_date ON guide_schedules(work_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_schedules_date_range ON guide_schedules(guide_id, work_date);
|
||||
|
||||
-- Комментарии
|
||||
COMMENT ON TABLE guide_schedules IS 'Расписание рабочих дней гидов';
|
||||
COMMENT ON COLUMN guide_schedules.guide_id IS 'ID гида';
|
||||
COMMENT ON COLUMN guide_schedules.work_date IS 'Дата рабочего дня';
|
||||
COMMENT ON COLUMN guide_schedules.notes IS 'Дополнительные заметки о рабочем дне';
|
||||
22
database/guide-working-days-migration.sql
Normal file
22
database/guide-working-days-migration.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
-- Создание новой таблицы для конкретных рабочих дней гидов
|
||||
CREATE TABLE IF NOT EXISTS guide_working_days (
|
||||
id SERIAL PRIMARY KEY,
|
||||
guide_id INTEGER NOT NULL REFERENCES guides(id) ON DELETE CASCADE,
|
||||
work_date DATE NOT NULL,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Уникальный индекс для предотвращения дублирования
|
||||
UNIQUE(guide_id, work_date)
|
||||
);
|
||||
|
||||
-- Индексы для оптимизации запросов
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_working_days_guide_id ON guide_working_days(guide_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_working_days_work_date ON guide_working_days(work_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_guide_working_days_date_range ON guide_working_days(guide_id, work_date);
|
||||
|
||||
-- Комментарии
|
||||
COMMENT ON TABLE guide_working_days IS 'Конкретные рабочие дни гидов';
|
||||
COMMENT ON COLUMN guide_working_days.guide_id IS 'ID гида';
|
||||
COMMENT ON COLUMN guide_working_days.work_date IS 'Дата рабочего дня';
|
||||
COMMENT ON COLUMN guide_working_days.notes IS 'Дополнительные заметки о рабочем дне';
|
||||
@@ -15,11 +15,55 @@ export async function initDatabase() {
|
||||
await db.query('SELECT 1');
|
||||
console.log('✅ Database connection successful');
|
||||
|
||||
// 1. Create schema
|
||||
// 1. Create schema with trigger safety
|
||||
console.log('📋 Creating database schema...');
|
||||
|
||||
// Сначала создаем или заменяем функцию
|
||||
await db.query(`
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
`);
|
||||
|
||||
const schemaPath = path.join(__dirname, 'schema.sql');
|
||||
const schema = fs.readFileSync(schemaPath, 'utf8');
|
||||
await db.query(schema);
|
||||
|
||||
// Проверяем и создаем триггеры только если не существуют
|
||||
const existingTriggers = await db.query(`
|
||||
SELECT trigger_name
|
||||
FROM information_schema.triggers
|
||||
WHERE event_object_schema = 'public'
|
||||
AND trigger_name LIKE '%update%updated_at%'
|
||||
`);
|
||||
|
||||
const triggerNames = new Set(existingTriggers.rows.map(row => row.trigger_name));
|
||||
|
||||
const triggersToCreate = [
|
||||
{ table: 'admins', name: 'update_admins_updated_at' },
|
||||
{ table: 'routes', name: 'update_routes_updated_at' },
|
||||
{ table: 'articles', name: 'update_articles_updated_at' },
|
||||
{ table: 'guides', name: 'update_guides_updated_at' }
|
||||
];
|
||||
|
||||
for (const { table, name } of triggersToCreate) {
|
||||
if (!triggerNames.has(name)) {
|
||||
await db.query(`
|
||||
CREATE TRIGGER ${name}
|
||||
BEFORE UPDATE ON ${table}
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
`);
|
||||
console.log(`✅ Created trigger ${name}`);
|
||||
} else {
|
||||
console.log(`ℹ️ Trigger ${name} already exists`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('✅ Database schema created successfully');
|
||||
|
||||
// 2. Check if tables are empty (first run)
|
||||
|
||||
Reference in New Issue
Block a user