This commit is contained in:
+9
-3
@@ -1100,7 +1100,7 @@ def api_categories():
|
|||||||
try:
|
try:
|
||||||
with db.conn.cursor() as cursor:
|
with db.conn.cursor() as cursor:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT AUTO_ID, ID, TITLE, description
|
SELECT AUTO_ID, ID, TITLE, description, marked_for_publication, is_tg_published
|
||||||
FROM categories
|
FROM categories
|
||||||
ORDER BY TITLE, ID
|
ORDER BY TITLE, ID
|
||||||
""")
|
""")
|
||||||
@@ -1112,7 +1112,9 @@ def api_categories():
|
|||||||
'auto_id': cat['AUTO_ID'],
|
'auto_id': cat['AUTO_ID'],
|
||||||
'id': cat['ID'],
|
'id': cat['ID'],
|
||||||
'title': cat['TITLE'] or '',
|
'title': cat['TITLE'] or '',
|
||||||
'description': cat['description'] or ''
|
'description': cat['description'] or '',
|
||||||
|
'marked_for_publication': bool(cat['marked_for_publication']) if cat['marked_for_publication'] is not None else False,
|
||||||
|
'is_tg_published': bool(cat['is_tg_published']) if cat['is_tg_published'] is not None else False
|
||||||
})
|
})
|
||||||
|
|
||||||
return jsonify(categories_list)
|
return jsonify(categories_list)
|
||||||
@@ -1129,7 +1131,7 @@ def api_category_details(category_id):
|
|||||||
try:
|
try:
|
||||||
with db.conn.cursor() as cursor:
|
with db.conn.cursor() as cursor:
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT AUTO_ID, ID, TITLE, description, image_url
|
SELECT AUTO_ID, ID, TITLE, description, image_url, tg_id, is_tg_published, tg_published_date, marked_for_publication
|
||||||
FROM categories
|
FROM categories
|
||||||
WHERE ID = %s
|
WHERE ID = %s
|
||||||
""", (category_id,))
|
""", (category_id,))
|
||||||
@@ -1153,6 +1155,10 @@ def api_category_details(category_id):
|
|||||||
'title': category['TITLE'] or '',
|
'title': category['TITLE'] or '',
|
||||||
'description': category['description'] or '',
|
'description': category['description'] or '',
|
||||||
'image_url': category['image_url'] or '',
|
'image_url': category['image_url'] or '',
|
||||||
|
'tg_id': category['tg_id'],
|
||||||
|
'is_tg_published': bool(category['is_tg_published']) if category['is_tg_published'] is not None else False,
|
||||||
|
'tg_published_date': category['tg_published_date'].isoformat() if category['tg_published_date'] else None,
|
||||||
|
'marked_for_publication': bool(category['marked_for_publication']) if category['marked_for_publication'] is not None else False,
|
||||||
'event_count': event_count
|
'event_count': event_count
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
+8
-2
@@ -164,7 +164,10 @@ def ensure_database_structure():
|
|||||||
TITLE VARCHAR(2048),
|
TITLE VARCHAR(2048),
|
||||||
description TEXT,
|
description TEXT,
|
||||||
tg_id BIGINT NULL,
|
tg_id BIGINT NULL,
|
||||||
image_url VARCHAR(2048)
|
image_url VARCHAR(2048),
|
||||||
|
is_tg_published BOOLEAN DEFAULT 0,
|
||||||
|
tg_published_date DATETIME NULL,
|
||||||
|
marked_for_publication BOOLEAN DEFAULT 0
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
@@ -228,7 +231,10 @@ def ensure_database_structure():
|
|||||||
'categories': [
|
'categories': [
|
||||||
{'column': 'description', 'type': 'TEXT'},
|
{'column': 'description', 'type': 'TEXT'},
|
||||||
{'column': 'tg_id', 'type': 'BIGINT NULL'},
|
{'column': 'tg_id', 'type': 'BIGINT NULL'},
|
||||||
{'column': 'image_url', 'type': 'VARCHAR(2048)'}
|
{'column': 'image_url', 'type': 'VARCHAR(2048)'},
|
||||||
|
{'column': 'is_tg_published', 'type': 'BOOLEAN DEFAULT 0'},
|
||||||
|
{'column': 'tg_published_date', 'type': 'DATETIME NULL'},
|
||||||
|
{'column': 'marked_for_publication', 'type': 'BOOLEAN DEFAULT 0'}
|
||||||
],
|
],
|
||||||
'events': [
|
'events': [
|
||||||
{'column': 'authors', 'type': 'VARCHAR(255)'}
|
{'column': 'authors', 'type': 'VARCHAR(255)'}
|
||||||
|
|||||||
+36
-3
@@ -700,6 +700,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th class="sortable-header">ID</th>
|
<th class="sortable-header">ID</th>
|
||||||
<th class="sortable-header">Название</th>
|
<th class="sortable-header">Название</th>
|
||||||
|
<th class="sortable-header">Статус</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
@@ -709,7 +710,7 @@
|
|||||||
<table class="table table-hover mb-0">
|
<table class="table table-hover mb-0">
|
||||||
<tbody id="categories-table">
|
<tbody id="categories-table">
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="text-center py-5">
|
<td colspan="3" class="text-center py-5">
|
||||||
<div class="spinner-border text-primary" role="status">
|
<div class="spinner-border text-primary" role="status">
|
||||||
<span class="visually-hidden">Загрузка...</span>
|
<span class="visually-hidden">Загрузка...</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -1846,7 +1847,7 @@
|
|||||||
if (categories.length === 0) {
|
if (categories.length === 0) {
|
||||||
tableBody.innerHTML = `
|
tableBody.innerHTML = `
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="text-center py-5 text-muted">
|
<td colspan="3" class="text-center py-5 text-muted">
|
||||||
<i class="fas fa-inbox fa-3x mb-3"></i>
|
<i class="fas fa-inbox fa-3x mb-3"></i>
|
||||||
<p>Нет доступных площадок</p>
|
<p>Нет доступных площадок</p>
|
||||||
</td>
|
</td>
|
||||||
@@ -1855,10 +1856,17 @@
|
|||||||
}
|
}
|
||||||
tableBody.innerHTML = '';
|
tableBody.innerHTML = '';
|
||||||
categories.forEach(category => {
|
categories.forEach(category => {
|
||||||
|
const publicationBadge = category.marked_for_publication
|
||||||
|
? '<span class="badge bg-warning status-badge">Для публикации</span>'
|
||||||
|
: '';
|
||||||
|
const publishedBadge = category.is_tg_published
|
||||||
|
? '<span class="badge bg-primary status-badge ms-1">Опубликовано</span>'
|
||||||
|
: '';
|
||||||
const row = `
|
const row = `
|
||||||
<tr class="category-row" data-id="${category.id}">
|
<tr class="category-row" data-id="${category.id}">
|
||||||
<td>${category.id || '-'}</td>
|
<td>${category.id || '-'}</td>
|
||||||
<td class="category-name-preview" title="${category.title || ''}">${category.title || 'Без названия'}</td>
|
<td class="category-name-preview" title="${category.title || ''}">${category.title || 'Без названия'}</td>
|
||||||
|
<td>${publicationBadge}${publishedBadge}</td>
|
||||||
</tr>`;
|
</tr>`;
|
||||||
tableBody.innerHTML += row;
|
tableBody.innerHTML += row;
|
||||||
});
|
});
|
||||||
@@ -1878,7 +1886,7 @@
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
tableBody.innerHTML = `
|
tableBody.innerHTML = `
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="text-center py-5 text-danger">
|
<td colspan="3" class="text-center py-5 text-danger">
|
||||||
<i class="fas fa-exclamation-triangle fa-2x mb-3"></i>
|
<i class="fas fa-exclamation-triangle fa-2x mb-3"></i>
|
||||||
<p>Ошибка загрузки данных</p>
|
<p>Ошибка загрузки данных</p>
|
||||||
<button class="btn btn-sm btn-outline-primary mt-2" onclick="loadCategoriesList()">
|
<button class="btn btn-sm btn-outline-primary mt-2" onclick="loadCategoriesList()">
|
||||||
@@ -1922,6 +1930,20 @@
|
|||||||
throw new Error('Площадка не найдена');
|
throw new Error('Площадка не найдена');
|
||||||
}
|
}
|
||||||
const category = await response.json();
|
const category = await response.json();
|
||||||
|
// Форматируем дату из UTC в локальное время
|
||||||
|
const formatDateTime = (dateStr) => {
|
||||||
|
if (!dateStr) return '';
|
||||||
|
// Парсим дату как UTC и конвертируем в локальное время
|
||||||
|
const date = new Date(dateStr + (dateStr.includes('Z') ? '' : 'Z'));
|
||||||
|
return date.toLocaleString('ru-RU', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
timeZoneName: 'short'
|
||||||
|
});
|
||||||
|
};
|
||||||
// Создаем HTML для деталей
|
// Создаем HTML для деталей
|
||||||
let detailsHtml = `
|
let detailsHtml = `
|
||||||
<div style="position: relative;">
|
<div style="position: relative;">
|
||||||
@@ -1939,6 +1961,17 @@
|
|||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<strong>Название:</strong> ${category.title || 'Не указано'}
|
<strong>Название:</strong> ${category.title || 'Не указано'}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>Статус:</strong>
|
||||||
|
${category.marked_for_publication && !category.is_tg_published ? '<span class="badge bg-warning">Для публикации</span>' : ''}
|
||||||
|
${!category.marked_for_publication && !category.is_tg_published ? '<span class="badge bg-secondary">Не для публикации</span>' : ''}
|
||||||
|
${category.is_tg_published ? '<span class="badge bg-primary">Опубликовано</span>' : ''}
|
||||||
|
</div>
|
||||||
|
${category.is_tg_published ? `
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>Опубликовано в TG</strong> ${category.tg_id ? `[ID ${category.tg_id}]` : ''} ${category.tg_published_date ? formatDateTime(category.tg_published_date) : ''}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<strong>Количество событий:</strong> ${category.event_count || 0}
|
<strong>Количество событий:</strong> ${category.event_count || 0}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user