This commit is contained in:
+269
-2
@@ -357,6 +357,31 @@
|
|||||||
.scrollable-table-body {
|
.scrollable-table-body {
|
||||||
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
|
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Стили для подсветки результатов поиска */
|
||||||
|
.search-highlight {
|
||||||
|
background-color: #fff3cd !important;
|
||||||
|
border-left: 4px solid #ffc107 !important;
|
||||||
|
animation: searchPulse 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes searchPulse {
|
||||||
|
0% { background-color: #fff3cd; }
|
||||||
|
50% { background-color: #ffeaa7; }
|
||||||
|
100% { background-color: #fff3cd; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для полей поиска */
|
||||||
|
.input-group .form-control:focus {
|
||||||
|
border-color: #86b7fe;
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group .btn-outline-secondary:hover {
|
||||||
|
background-color: #6c757d;
|
||||||
|
border-color: #6c757d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -444,7 +469,16 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
<h5 class="mb-0">Список постов</h5>
|
<h5 class="mb-0">Список постов</h5>
|
||||||
<div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="input-group me-2" style="width: 200px;">
|
||||||
|
<input type="text" class="form-control form-control-sm" id="posts-search" placeholder="Поиск...">
|
||||||
|
<button class="btn btn-outline-secondary btn-sm" type="button" id="posts-search-prev">
|
||||||
|
<i class="fas fa-chevron-up"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-outline-secondary btn-sm" type="button" id="posts-search-next">
|
||||||
|
<i class="fas fa-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<button class="btn btn-sm btn-success" id="add-post-btn">
|
<button class="btn btn-sm btn-success" id="add-post-btn">
|
||||||
<i class="fas fa-plus"></i> Добавить
|
<i class="fas fa-plus"></i> Добавить
|
||||||
</button>
|
</button>
|
||||||
@@ -528,7 +562,16 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
<h5 class="mb-0">Список событий</h5>
|
<h5 class="mb-0">Список событий</h5>
|
||||||
<div>
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="input-group me-2" style="width: 200px;">
|
||||||
|
<input type="text" class="form-control form-control-sm" id="events-search" placeholder="Поиск...">
|
||||||
|
<button class="btn btn-outline-secondary btn-sm" type="button" id="events-search-prev">
|
||||||
|
<i class="fas fa-chevron-up"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-outline-secondary btn-sm" type="button" id="events-search-next">
|
||||||
|
<i class="fas fa-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<button class="btn btn-sm btn-success" id="add-event-btn-sm">
|
<button class="btn btn-sm btn-success" id="add-event-btn-sm">
|
||||||
<i class="fas fa-plus"></i> Добавить
|
<i class="fas fa-plus"></i> Добавить
|
||||||
</button>
|
</button>
|
||||||
@@ -3034,6 +3077,230 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
alert('Ошибка при сохранении изменений');
|
alert('Ошибка при сохранении изменений');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Функции поиска
|
||||||
|
let postsSearchResults = [];
|
||||||
|
let eventsSearchResults = [];
|
||||||
|
let currentPostsSearchIndex = -1;
|
||||||
|
let currentEventsSearchIndex = -1;
|
||||||
|
|
||||||
|
// Поиск по постам
|
||||||
|
function searchPosts(query) {
|
||||||
|
if (!query.trim()) {
|
||||||
|
postsSearchResults = [];
|
||||||
|
currentPostsSearchIndex = -1;
|
||||||
|
clearPostsSearchHighlight();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const posts = document.querySelectorAll('.post-row');
|
||||||
|
postsSearchResults = [];
|
||||||
|
|
||||||
|
posts.forEach((post, index) => {
|
||||||
|
const postId = post.dataset.id;
|
||||||
|
const shortname = post.querySelector('.shortname-preview')?.textContent || '';
|
||||||
|
const textPreview = post.querySelector('.post-text-preview')?.textContent || '';
|
||||||
|
|
||||||
|
const searchText = `${shortname} ${textPreview}`.toLowerCase();
|
||||||
|
if (searchText.includes(query.toLowerCase())) {
|
||||||
|
postsSearchResults.push({
|
||||||
|
element: post,
|
||||||
|
index: index,
|
||||||
|
id: postId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentPostsSearchIndex = postsSearchResults.length > 0 ? 0 : -1;
|
||||||
|
highlightSearchResults('posts');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Поиск по событиям (расширенный с тэгами)
|
||||||
|
async function searchEvents(query) {
|
||||||
|
if (!query.trim()) {
|
||||||
|
eventsSearchResults = [];
|
||||||
|
currentEventsSearchIndex = -1;
|
||||||
|
clearEventsSearchHighlight();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Получаем все события из API для поиска по тэгам
|
||||||
|
const response = await fetch(`${PREFIX}/api/events`);
|
||||||
|
const allEvents = await response.json();
|
||||||
|
|
||||||
|
const events = document.querySelectorAll('.event-row');
|
||||||
|
eventsSearchResults = [];
|
||||||
|
|
||||||
|
events.forEach((event, index) => {
|
||||||
|
const eventId = event.dataset.id;
|
||||||
|
const name = event.querySelector('.event-name-preview')?.textContent || '';
|
||||||
|
const unitName = event.querySelector('.shortname-preview')?.textContent || '';
|
||||||
|
|
||||||
|
// Находим полные данные события для поиска по тэгам
|
||||||
|
const eventData = allEvents.find(e => e.id == eventId);
|
||||||
|
const tags = eventData?.tags || '';
|
||||||
|
|
||||||
|
const searchText = `${name} ${unitName} ${tags}`.toLowerCase();
|
||||||
|
if (searchText.includes(query.toLowerCase())) {
|
||||||
|
eventsSearchResults.push({
|
||||||
|
element: event,
|
||||||
|
index: index,
|
||||||
|
id: eventId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentEventsSearchIndex = eventsSearchResults.length > 0 ? 0 : -1;
|
||||||
|
highlightSearchResults('events');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при поиске событий:', error);
|
||||||
|
// Fallback к простому поиску без тэгов
|
||||||
|
searchEventsSimple(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Простой поиск по событиям (без тэгов)
|
||||||
|
function searchEventsSimple(query) {
|
||||||
|
const events = document.querySelectorAll('.event-row');
|
||||||
|
eventsSearchResults = [];
|
||||||
|
|
||||||
|
events.forEach((event, index) => {
|
||||||
|
const eventId = event.dataset.id;
|
||||||
|
const name = event.querySelector('.event-name-preview')?.textContent || '';
|
||||||
|
const unitName = event.querySelector('.shortname-preview')?.textContent || '';
|
||||||
|
|
||||||
|
const searchText = `${name} ${unitName}`.toLowerCase();
|
||||||
|
if (searchText.includes(query.toLowerCase())) {
|
||||||
|
eventsSearchResults.push({
|
||||||
|
element: event,
|
||||||
|
index: index,
|
||||||
|
id: eventId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentEventsSearchIndex = eventsSearchResults.length > 0 ? 0 : -1;
|
||||||
|
highlightSearchResults('events');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Подсветка результатов поиска
|
||||||
|
function highlightSearchResults(type) {
|
||||||
|
if (type === 'posts') {
|
||||||
|
clearPostsSearchHighlight();
|
||||||
|
if (currentPostsSearchIndex >= 0 && currentPostsSearchIndex < postsSearchResults.length) {
|
||||||
|
const result = postsSearchResults[currentPostsSearchIndex];
|
||||||
|
result.element.classList.add('search-highlight');
|
||||||
|
result.element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
|
||||||
|
// Выделяем найденный пост
|
||||||
|
highlightSelectedPost(result.id);
|
||||||
|
}
|
||||||
|
} else if (type === 'events') {
|
||||||
|
clearEventsSearchHighlight();
|
||||||
|
if (currentEventsSearchIndex >= 0 && currentEventsSearchIndex < eventsSearchResults.length) {
|
||||||
|
const result = eventsSearchResults[currentEventsSearchIndex];
|
||||||
|
result.element.classList.add('search-highlight');
|
||||||
|
result.element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
|
||||||
|
// Выделяем найденное событие
|
||||||
|
highlightSelectedEvent(result.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очистка подсветки поиска постов
|
||||||
|
function clearPostsSearchHighlight() {
|
||||||
|
document.querySelectorAll('.post-row.search-highlight').forEach(row => {
|
||||||
|
row.classList.remove('search-highlight');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Очистка подсветки поиска событий
|
||||||
|
function clearEventsSearchHighlight() {
|
||||||
|
document.querySelectorAll('.event-row.search-highlight').forEach(row => {
|
||||||
|
row.classList.remove('search-highlight');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Навигация по результатам поиска постов
|
||||||
|
function navigatePostsSearch(direction) {
|
||||||
|
if (postsSearchResults.length === 0) return;
|
||||||
|
|
||||||
|
if (direction === 'next') {
|
||||||
|
currentPostsSearchIndex = (currentPostsSearchIndex + 1) % postsSearchResults.length;
|
||||||
|
} else if (direction === 'prev') {
|
||||||
|
currentPostsSearchIndex = currentPostsSearchIndex <= 0 ? postsSearchResults.length - 1 : currentPostsSearchIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightSearchResults('posts');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Навигация по результатам поиска событий
|
||||||
|
function navigateEventsSearch(direction) {
|
||||||
|
if (eventsSearchResults.length === 0) return;
|
||||||
|
|
||||||
|
if (direction === 'next') {
|
||||||
|
currentEventsSearchIndex = (currentEventsSearchIndex + 1) % eventsSearchResults.length;
|
||||||
|
} else if (direction === 'prev') {
|
||||||
|
currentEventsSearchIndex = currentEventsSearchIndex <= 0 ? eventsSearchResults.length - 1 : currentEventsSearchIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightSearchResults('events');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработчики событий для поиска постов
|
||||||
|
document.getElementById('posts-search').addEventListener('input', (e) => {
|
||||||
|
searchPosts(e.target.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('posts-search-prev').addEventListener('click', () => {
|
||||||
|
navigatePostsSearch('prev');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('posts-search-next').addEventListener('click', () => {
|
||||||
|
navigatePostsSearch('next');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчики событий для поиска событий
|
||||||
|
document.getElementById('events-search').addEventListener('input', (e) => {
|
||||||
|
searchEvents(e.target.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('events-search-prev').addEventListener('click', () => {
|
||||||
|
navigateEventsSearch('prev');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('events-search-next').addEventListener('click', () => {
|
||||||
|
navigateEventsSearch('next');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчики клавиш для поиска
|
||||||
|
document.getElementById('posts-search').addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigatePostsSearch('next');
|
||||||
|
} else if (e.key === 'ArrowUp') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigatePostsSearch('prev');
|
||||||
|
} else if (e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigatePostsSearch('next');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('events-search').addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateEventsSearch('next');
|
||||||
|
} else if (e.key === 'ArrowUp') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateEventsSearch('prev');
|
||||||
|
} else if (e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateEventsSearch('next');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
// Убедимся, что функция доступна глобально, если потребуется вызвать из HTML
|
// Убедимся, что функция доступна глобально, если потребуется вызвать из HTML
|
||||||
window.resetLayout = resetLayout;
|
window.resetLayout = resetLayout;
|
||||||
|
|||||||
Reference in New Issue
Block a user