- Implemented the initial version of the web interface. refactor: Begin Telegram bot refactoring - Started restructuring the bot’s code for better maintainability. chore: Migrate to Flask project structure - Reorganized the application to follow Flask's project structure. cleanup: Extensive code cleanup - Removed redundant code and improved readability. Signed-off-by: UdoChudo <stream@udochudo.ru>
649 lines
24 KiB
JavaScript
649 lines
24 KiB
JavaScript
|
||
|
||
const perPage=10
|
||
let currentPage=1
|
||
let totalPages=1
|
||
let regionsCurrentPage=1
|
||
let sortField="region_id"
|
||
let sortOrder="asc"
|
||
let currentFetchController=null
|
||
let currentSystemIdToDelete=null
|
||
let systemsCurrentPage=1
|
||
let systemsTotalPages=1
|
||
let systemsSortField="system_id"
|
||
let systemsSortOrder="asc"
|
||
|
||
|
||
// Предварительно создаём объекты модалей (чтобы не создавать каждый раз заново)
|
||
const editRegionNameModal = new bootstrap.Modal(document.getElementById('editRegionNameModal'));
|
||
const deleteRegionModal = new bootstrap.Modal(document.getElementById('deleteRegionModal'));
|
||
const regionSubscribersModal = new bootstrap.Modal(document.getElementById('regionSubscribersModal'));
|
||
|
||
const editSystemNameModal = new bootstrap.Modal(document.getElementById('editSystemNameModal'));
|
||
const deleteSystemModal = new bootstrap.Modal(document.getElementById('deleteSystemModal'));
|
||
|
||
|
||
function loadRegions(e){
|
||
if(e<1||e>totalPages)return;
|
||
currentPage=e;
|
||
let t=`/telezab/rest/api/regions?page=${currentPage}&per_page=${perPage}&sort_field=${sortField}&sort_order=${sortOrder}`;
|
||
currentFetchController&¤tFetchController.abort(),
|
||
safeFetch(t,{signal:(currentFetchController=new AbortController).signal})
|
||
.then(e=>e.json())
|
||
.then(e=>{
|
||
currentFetchController=null,
|
||
totalPages=e.total_pages,
|
||
updateRegionsTable(e.regions),
|
||
updatePagination(e.current_page,e.total_pages,"pagination-regions")
|
||
})
|
||
.catch(e=>{
|
||
"AbortError"===e.name||console.error("Error fetching regions:",e),
|
||
currentFetchController=null
|
||
})
|
||
}
|
||
|
||
function updateRegionsTable(e){
|
||
let t=document.getElementById("regions-table");
|
||
if(!t) {
|
||
console.error("regions-table element not found!");
|
||
return;
|
||
}
|
||
|
||
t.innerHTML="";
|
||
e.forEach(e=>{
|
||
let n=document.createElement("tr");
|
||
n.innerHTML=`
|
||
<td>${e.region_id}</td>
|
||
<td>${e.name}</td>
|
||
<td>
|
||
<span id="region-status-label-${e.region_id}">${e.active ? "Включен" : "Выключен"}</span>
|
||
</td>
|
||
<td>
|
||
<div class="d-flex align-items-center">
|
||
<div class="form-check form-switch me-2">
|
||
<input class="form-check-input region-status-switch" type="checkbox" role="switch" id="region-status-${e.region_id}" data-id="${e.region_id}" ${e.active ? "checked" : ""}>
|
||
<label class="form-check-label" for="region-status-${e.region_id}"></label>
|
||
</div>
|
||
<button class="btn btn-sm btn-primary edit-name-btn me-2" data-id="${e.region_id}" data-name="${e.name}" title="Редактировать название региона">
|
||
<i class="bi bi-pencil"></i>
|
||
</button>
|
||
<button class="btn btn-sm btn-info subscribers-btn me-2" data-id="${e.region_id}" title="Посмотреть подписчиков региона">
|
||
<i class="bi bi-people"></i>
|
||
</button>
|
||
<button class="btn btn-sm btn-danger delete-btn" data-id="${e.region_id}" title="Удалить регион">
|
||
<i class="bi bi-trash"></i>
|
||
</button>
|
||
</div>
|
||
</td>
|
||
`;
|
||
t.appendChild(n)
|
||
});
|
||
setupRegionActions();
|
||
}
|
||
|
||
function setupRegionActions(){
|
||
// Используем делегирование событий для избежания множественных обработчиков
|
||
const regionsTable = document.getElementById("regions-table");
|
||
if (!regionsTable) return;
|
||
|
||
// Удаляем старые обработчики событий с таблицы
|
||
const newTable = regionsTable.cloneNode(true);
|
||
regionsTable.parentNode.replaceChild(newTable, regionsTable);
|
||
|
||
// Используем делегирование событий
|
||
newTable.addEventListener('click', function(e) {
|
||
const target = e.target.closest('button');
|
||
if (!target) return;
|
||
|
||
if (target.classList.contains('delete-btn')) {
|
||
e.preventDefault();
|
||
deleteRegion(target.dataset.id);
|
||
} else if (target.classList.contains('edit-name-btn')) {
|
||
e.preventDefault();
|
||
handleEditRegionName(target);
|
||
} else if (target.classList.contains('subscribers-btn')) {
|
||
e.preventDefault();
|
||
showRegionSubscribers(target.dataset.id);
|
||
}
|
||
});
|
||
|
||
// Обработчик для переключателей статуса
|
||
newTable.addEventListener('change', function(e) {
|
||
if (e.target.classList.contains('region-status-switch')) {
|
||
let id = e.target.dataset.id;
|
||
let active = e.target.checked;
|
||
toggleRegionStatus(id, active);
|
||
document.getElementById(`region-status-label-${id}`).textContent = active ? "Включен" : "Выключен";
|
||
}
|
||
});
|
||
|
||
// Обновляем заголовки для сортировки
|
||
document.querySelectorAll("th[data-sort]").forEach(e=>{
|
||
const newHeader = e.cloneNode(true);
|
||
e.parentNode.replaceChild(newHeader, e);
|
||
newHeader.addEventListener("click", ()=>{
|
||
let field = newHeader.dataset.sort;
|
||
if(field === sortField) {
|
||
sortOrder = sortOrder === "asc" ? "desc" : "asc";
|
||
} else {
|
||
sortField = field;
|
||
sortOrder = "asc";
|
||
}
|
||
loadRegions(currentPage);
|
||
});
|
||
});
|
||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[title]'));
|
||
tooltipTriggerList.map(el => new bootstrap.Tooltip(el));
|
||
}
|
||
|
||
function handleEditRegionName(e){
|
||
let t = e.dataset.id,
|
||
n = e.dataset.name;
|
||
document.getElementById("old-region-name").value = n;
|
||
document.getElementById("new-region-name").value = n;
|
||
|
||
editRegionNameModal.show();
|
||
|
||
let s = 5;
|
||
document.getElementById("edit-region-name-timer").textContent = s;
|
||
let a = setInterval(() => {
|
||
s--;
|
||
document.getElementById("edit-region-name-timer").textContent = s;
|
||
if (s === 0) {
|
||
clearInterval(a);
|
||
document.getElementById("save-region-name-btn").removeAttribute("disabled");
|
||
}
|
||
}, 1000);
|
||
|
||
let r = document.getElementById("save-region-name-btn"),
|
||
o = r.cloneNode(true);
|
||
r.parentNode.replaceChild(o, r);
|
||
o.addEventListener("click", () => {
|
||
updateRegionName(t, document.getElementById("new-region-name").value);
|
||
editRegionNameModal.hide();
|
||
});
|
||
}
|
||
|
||
function showRegionSubscribers(e){
|
||
safeFetch(`/telezab/rest/api/regions/${e}/subscribers`)
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
let t = document.getElementById("regionSubscribersTableBody");
|
||
t.innerHTML = "";
|
||
if(data.subscribers && data.subscribers.length > 0){
|
||
data.subscribers.forEach(sub => {
|
||
let n = document.createElement("tr");
|
||
n.innerHTML = `
|
||
<td>${sub.telegram_id}</td>
|
||
<td>${sub.email}</td>
|
||
`;
|
||
t.appendChild(n);
|
||
});
|
||
} else {
|
||
let n = document.createElement("tr");
|
||
n.innerHTML = `<td colspan="2">Нет подписчиков для этого региона.</td>`;
|
||
t.appendChild(n);
|
||
}
|
||
regionSubscribersModal.show();
|
||
})
|
||
.catch(err => {
|
||
console.error("Ошибка при получении подписчиков региона:", err);
|
||
toastr.error("Ошибка при получении подписчиков региона. Пожалуйста, попробуйте позже.");
|
||
});
|
||
}
|
||
|
||
|
||
function updateRegionName(regionId, newName) {
|
||
safeFetch("/telezab/rest/api/regions/name", {
|
||
method:"PUT",
|
||
headers:{"Content-Type":"application/json"},
|
||
body:JSON.stringify({region_id:regionId, name:newName})
|
||
})
|
||
.then(()=>{
|
||
loadRegions(currentPage);
|
||
toastr.success("Название региона изменено.");
|
||
})
|
||
.catch(e=>{
|
||
console.error("Ошибка при изменении названия региона:",e);
|
||
toastr.error("Ошибка при изменении названия региона. Пожалуйста, попробуйте позже.");
|
||
});
|
||
}
|
||
|
||
function toggleRegionStatus(e,t){
|
||
safeFetch("/telezab/rest/api/regions/status",{
|
||
method:"PUT",
|
||
headers:{"Content-Type":"application/json"},
|
||
body:JSON.stringify({region_id:e,active:t})
|
||
})
|
||
.then(()=>{
|
||
loadRegions(currentPage);
|
||
t?toastr.success("Регион активирован."):toastr.success("Регион деактивирован.");
|
||
})
|
||
.catch(e=>{
|
||
console.error("Ошибка при изменении статуса региона:",e);
|
||
toastr.error("Ошибка при изменении статуса региона. Пожалуйста, попробуйте позже.");
|
||
});
|
||
}
|
||
|
||
function deleteRegion(e){
|
||
deleteRegionModal.show();
|
||
|
||
let t = document.getElementById("deleteConfirmationInput"),
|
||
n = document.getElementById("confirmDeleteButton"),
|
||
s = document.getElementById("deleteRegionModal"),
|
||
a = t.cloneNode(true),
|
||
r = n.cloneNode(true);
|
||
|
||
t.parentNode.replaceChild(a, t);
|
||
n.parentNode.replaceChild(r, n);
|
||
|
||
a.addEventListener("input", function(){
|
||
let val = this.value;
|
||
r.disabled = val === "УДАЛИТЬ" ? false : true;
|
||
});
|
||
|
||
r.addEventListener("click", function(){
|
||
safeFetch(`/telezab/rest/api/regions/${e}`, { method: "DELETE" })
|
||
.then(() => {
|
||
loadRegions(currentPage);
|
||
toastr.success("Регион успешно удален.");
|
||
deleteRegionModal.hide();
|
||
})
|
||
.catch(err => {
|
||
console.error("Ошибка при удалении региона:", err);
|
||
toastr.error("Ошибка при удалении региона. Пожалуйста, попробуйте позже.");
|
||
});
|
||
});
|
||
|
||
s.addEventListener("hidden.bs.modal", function(){
|
||
a.value = "";
|
||
r.disabled = true;
|
||
}, { once: true });
|
||
}
|
||
|
||
function loadSystems(e){
|
||
if(e<1||e>systemsTotalPages)return;
|
||
systemsCurrentPage=e;
|
||
let t=`/telezab/rest/api/systems?page=${systemsCurrentPage}&per_page=10&sort_field=${systemsSortField}&sort_order=${systemsSortOrder}`;
|
||
currentFetchController&¤tFetchController.abort(),
|
||
safeFetch(t,{signal:(currentFetchController=new AbortController).signal})
|
||
.then(e=>e.json())
|
||
.then(e=>{
|
||
currentFetchController=null,
|
||
systemsTotalPages=e.total_pages,
|
||
updateSystemsTable(e.systems),
|
||
updatePagination(e.current_page,e.total_pages,"pagination-systems")
|
||
})
|
||
.catch(e=>{
|
||
"AbortError"===e.name||console.error("Error fetching systems:",e),
|
||
currentFetchController=null
|
||
});
|
||
}
|
||
|
||
function updateSystemsTable(e) {
|
||
let t = document.getElementById("systems-table");
|
||
if (!t) {
|
||
console.error("systems-table element not found!");
|
||
return;
|
||
}
|
||
|
||
t.innerHTML = "";
|
||
e.forEach(e => {
|
||
let n = document.createElement("tr");
|
||
n.innerHTML = `
|
||
<td>${e.system_id}</td>
|
||
<td>${e.system_name}</td>
|
||
<td>${e.name}</td>
|
||
<td>
|
||
<div class="d-flex align-items-center">
|
||
<button class="btn btn-sm btn-primary edit-name-btn me-2"
|
||
data-id="${e.system_id}"
|
||
data-latin-name="${e.system_name}"
|
||
data-name="${e.name}"
|
||
title="Редактировать название системы">
|
||
<i class="bi bi-pencil"></i>
|
||
</button>
|
||
<button class="btn btn-sm btn-danger delete-btn"
|
||
data-id="${e.system_id}"
|
||
title="Удалить систему">
|
||
<i class="bi bi-trash"></i>
|
||
</button>
|
||
</div>
|
||
</td>
|
||
`;
|
||
t.appendChild(n);
|
||
});
|
||
|
||
setupSystemActions();
|
||
|
||
// Инициализация Bootstrap tooltips
|
||
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[title]'));
|
||
tooltipTriggerList.map(el => new bootstrap.Tooltip(el));
|
||
}
|
||
|
||
function setupSystemActions(){
|
||
// Используем делегирование событий для таблицы систем
|
||
const systemsTable = document.getElementById("systems-table");
|
||
if (!systemsTable) return;
|
||
|
||
// Удаляем старые обработчики событий с таблицы
|
||
const newTable = systemsTable.cloneNode(true);
|
||
systemsTable.parentNode.replaceChild(newTable, systemsTable);
|
||
|
||
// Используем делегирование событий
|
||
newTable.addEventListener('click', function(e) {
|
||
const target = e.target.closest('button');
|
||
if (!target) return;
|
||
|
||
if (target.classList.contains('delete-btn')) {
|
||
e.preventDefault();
|
||
deleteSystem(target.dataset.id);
|
||
} else if (target.classList.contains('edit-name-btn')) {
|
||
e.preventDefault();
|
||
handleEditSystemName(target);
|
||
}
|
||
});
|
||
|
||
// Обновляем заголовки для сортировки
|
||
document.querySelectorAll("th[data-sort]").forEach(e=>{
|
||
const newHeader = e.cloneNode(true);
|
||
e.parentNode.replaceChild(newHeader, e);
|
||
newHeader.addEventListener("click", ()=>{
|
||
let field = newHeader.dataset.sort;
|
||
if(field === systemsSortField) {
|
||
systemsSortOrder = systemsSortOrder === "asc" ? "desc" : "asc";
|
||
} else {
|
||
systemsSortField = field;
|
||
systemsSortOrder = "asc";
|
||
}
|
||
loadSystems(systemsCurrentPage);
|
||
});
|
||
});
|
||
}
|
||
|
||
function handleEditSystemName(e){
|
||
let t = e.dataset.id,
|
||
n = e.dataset.latinName,
|
||
s = e.dataset.name;
|
||
|
||
let a = document.getElementById("edit-system-id"),
|
||
r = document.getElementById("edit-system-name-lat"),
|
||
o = document.getElementById("old-system-name"),
|
||
l = document.getElementById("new-system-name");
|
||
|
||
if(!a || !r || !o || !l){
|
||
console.error("❌ Один или несколько элементов не найдены:");
|
||
!a && console.error(" - Не найден элемент #edit-system-id");
|
||
!r && console.error(" - Не найден элемент #edit-system-name-lat");
|
||
!o && console.error(" - Не найден элемент #old-system-name");
|
||
!l && console.error(" - Не найден элемент #new-system-name");
|
||
return;
|
||
}
|
||
|
||
a.value = t;
|
||
r.value = n;
|
||
o.value = s;
|
||
l.value = s;
|
||
|
||
editSystemNameModal.show();
|
||
|
||
let d = 5,
|
||
i = document.getElementById("edit-system-name-timer");
|
||
i.textContent = d;
|
||
|
||
let m = setInterval(() => {
|
||
d--;
|
||
i.textContent = d;
|
||
if(d === 0){
|
||
clearInterval(m);
|
||
document.getElementById("saveSystemNameBtn").removeAttribute("disabled");
|
||
}
|
||
}, 1000);
|
||
|
||
let c = document.getElementById("saveSystemNameBtn"),
|
||
g = c.cloneNode(true);
|
||
c.parentNode.replaceChild(g, c);
|
||
|
||
g.addEventListener("click", () => {
|
||
let id = a.value,
|
||
latinName = r.value,
|
||
newName = l.value.trim();
|
||
|
||
if(!newName){
|
||
toastr.error("Введите новое название системы.");
|
||
return;
|
||
}
|
||
|
||
updateSystemName(id, latinName, newName);
|
||
editSystemNameModal.hide();
|
||
});
|
||
}
|
||
|
||
|
||
|
||
function updateSystemName(systemId, systemNameLat, nameCyr) {
|
||
if (!systemId || !systemNameLat || !nameCyr) {
|
||
toastr.error("Не все параметры заполнены.");
|
||
return;
|
||
}
|
||
|
||
safeFetch("/telezab/rest/api/systems", {
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({
|
||
system_id: systemId,
|
||
system_name: systemNameLat,
|
||
name: nameCyr
|
||
})
|
||
})
|
||
.then(res => res.ok ? res.json() : res.json().then(e => { throw new Error(e.message || "Ошибка сервера") }))
|
||
.then(() => {
|
||
loadSystems(systemsCurrentPage);
|
||
toastr.success("Название системы успешно обновлено.");
|
||
})
|
||
.catch(e => {
|
||
console.error("Ошибка при изменении названия системы:", e);
|
||
toastr.error(e.message || "Ошибка при изменении названия системы. Пожалуйста, попробуйте позже.");
|
||
});
|
||
}
|
||
|
||
function deleteSystem(e){
|
||
deleteSystemModal.show();
|
||
|
||
let t = document.getElementById("deleteSystemConfirmationInput"),
|
||
n = document.getElementById("confirmDeleteSystemButton"),
|
||
s = document.getElementById("deleteSystemModal"),
|
||
a = t.cloneNode(true),
|
||
r = n.cloneNode(true);
|
||
|
||
t.parentNode.replaceChild(a, t);
|
||
n.parentNode.replaceChild(r, n);
|
||
|
||
a.addEventListener("input", function(){
|
||
let val = this.value;
|
||
r.disabled = val === "УДАЛИТЬ" ? false : true;
|
||
});
|
||
|
||
r.addEventListener("click", function(){
|
||
safeFetch(`/telezab/rest/api/systems/${e}`, { method: "DELETE" })
|
||
.then(() => {
|
||
loadSystems(systemsCurrentPage);
|
||
toastr.success("Система успешно удалена.");
|
||
deleteSystemModal.hide();
|
||
})
|
||
.catch(err => {
|
||
console.error("Ошибка при удалении системы:", err);
|
||
toastr.error("Ошибка при удалении системы. Пожалуйста, попробуйте позже.");
|
||
});
|
||
});
|
||
|
||
s.addEventListener("hidden.bs.modal", function(){
|
||
a.value = "";
|
||
r.disabled = true;
|
||
}, { once: true });
|
||
}
|
||
|
||
|
||
function updatePagination(e,t,n){
|
||
let s=document.getElementById(n);
|
||
if(!s){
|
||
console.error(`Container with ID ${n} not found!`);
|
||
return;
|
||
}
|
||
s.innerHTML="";
|
||
|
||
let a=document.createElement("li");
|
||
a.classList.add("page-item");
|
||
a.classList.toggle("disabled",1===e);
|
||
a.innerHTML=`<a class="page-link" href="#" aria-label="Previous" onclick="loadPage(${e-1}, '${n}')">«</a>`;
|
||
s.appendChild(a);
|
||
|
||
for(let r=1;r<=t;r++){
|
||
let o=document.createElement("li");
|
||
o.classList.add("page-item");
|
||
o.classList.toggle("active",r===e);
|
||
let l=document.createElement("a");
|
||
l.classList.add("page-link");
|
||
l.href="#";
|
||
l.textContent=r;
|
||
l.onclick=()=>loadPage(r,n);
|
||
o.appendChild(l);
|
||
s.appendChild(o);
|
||
}
|
||
|
||
let i=document.createElement("li");
|
||
i.classList.add("page-item");
|
||
i.classList.toggle("disabled",e===t);
|
||
i.innerHTML=`<a class="page-link" href="#" aria-label="Next" onclick="loadPage(${e+1}, '${n}')">»</a>`;
|
||
s.appendChild(i);
|
||
}
|
||
|
||
function loadPage(e,t){
|
||
"pagination-regions"===t?loadRegions(e):"pagination-systems"===t&&loadSystems(e);
|
||
}
|
||
|
||
// Настройка toastr
|
||
toastr.options={
|
||
closeButton:!0,
|
||
debug:!1,
|
||
newestOnTop:!1,
|
||
progressBar:!1,
|
||
positionClass:"toast-bottom-right",
|
||
preventDuplicates:!1,
|
||
onclick:null,
|
||
showDuration:"300",
|
||
hideDuration:"1000",
|
||
timeOut:"5000",
|
||
extendedTimeOut:"1000",
|
||
showEasing:"swing",
|
||
hideEasing:"linear",
|
||
showMethod:"fadeIn",
|
||
hideMethod:"fadeOut"
|
||
};
|
||
|
||
// Обработчики форм
|
||
document.getElementById("add-region-form").addEventListener("submit",e=>{
|
||
e.preventDefault();
|
||
let regionId=document.getElementById("region-id").value;
|
||
let regionName=document.getElementById("region-name").value;
|
||
let regionActive=document.getElementById("region-active").checked;
|
||
|
||
if(!/^\d+$/.test(regionId)){
|
||
toastr.error("ID региона должен содержать только числа.");
|
||
console.log("Ошибка: ID региона не является числом.");
|
||
return;
|
||
}
|
||
|
||
safeFetch("/telezab/rest/api/regions",{
|
||
method:"POST",
|
||
headers:{"Content-Type":"application/json"},
|
||
body:JSON.stringify({region_id:regionId,name:regionName,active:regionActive})
|
||
})
|
||
.then(e=>e.ok?e.json():e.json().then(e=>{
|
||
throw console.error("Ошибка от сервера:",e),new Error(e.message||"Ошибка добавления региона");
|
||
}))
|
||
.then(e=>{
|
||
if("success"===e.status){
|
||
console.log("Регион успешно добавлен.");
|
||
document.getElementById("region-id").value="";
|
||
document.getElementById("region-name").value="";
|
||
document.getElementById("region-active").checked=!1;
|
||
loadRegions(regionsCurrentPage);
|
||
toastr.success(e.message);
|
||
$("#addRegionModal").modal("hide");
|
||
}else{
|
||
throw console.log("Ошибка: Статус ответа не 'success'."),new Error(e.message||"Неизвестная ошибка");
|
||
}
|
||
})
|
||
.catch(e=>{
|
||
console.error("Ошибка при добавлении региона:",e);
|
||
toastr.error(e.message||"Ошибка при добавлении региона. Пожалуйста, попробуйте позже.");
|
||
});
|
||
});
|
||
|
||
document.getElementById("add-system-form").addEventListener("submit",e=>{
|
||
e.preventDefault();
|
||
let systemId=document.getElementById("system-id").value;
|
||
let systemNameLat=document.getElementById("system-name-lat").value;
|
||
let systemNameCyr=document.getElementById("system-name-cyr").value;
|
||
|
||
if(!/^\d+$/.test(systemId)){
|
||
toastr.error("ID системы должен содержать только числа.");
|
||
return;
|
||
}
|
||
|
||
safeFetch("/telezab/rest/api/systems",{
|
||
method:"POST",
|
||
headers:{"Content-Type":"application/json"},
|
||
body:JSON.stringify({system_id:systemId,system_name:systemNameLat,name:systemNameCyr})
|
||
})
|
||
.then(e=>e.ok?e.json():e.json().then(e=>{
|
||
throw new Error(e.message||"Ошибка добавления системы");
|
||
}))
|
||
.then(e=>{
|
||
document.getElementById("system-id").value="";
|
||
document.getElementById("system-name-lat").value="";
|
||
document.getElementById("system-name-cyr").value="";
|
||
loadSystems(systemsCurrentPage);
|
||
toastr.success("Система успешно добавлена.");
|
||
$("#addSystemModal").modal("hide");
|
||
})
|
||
.catch(e=>{
|
||
console.error("Ошибка при добавлении системы:",e);
|
||
toastr.error(e.message||"Ошибка при добавлении системы. Пожалуйста, попробуйте позже.");
|
||
});
|
||
});
|
||
|
||
// Инициализация при загрузке страницы
|
||
document.addEventListener("DOMContentLoaded",()=>{
|
||
let regionsTab=document.getElementById("regions-tab");
|
||
let systemsTab=document.getElementById("systems-tab");
|
||
|
||
regionsTab.addEventListener("shown.bs.tab",()=>{
|
||
loadRegions(currentPage);
|
||
});
|
||
|
||
systemsTab.addEventListener("shown.bs.tab",()=>{
|
||
loadSystems(systemsCurrentPage);
|
||
});
|
||
|
||
regionsTab.classList.contains("active")&&loadRegions(currentPage);
|
||
|
||
// Очистка форм при закрытии модальных окон
|
||
let modalsConfig=[
|
||
{modalId:"addRegionModal",formId:"add-region-form"},
|
||
{modalId:"addSystemModal",formId:"add-system-form"},
|
||
{modalId:"editRegionNameModal",formId:"edit-region-name-form"},
|
||
{modalId:"editSystemNameModal",formId:"edit-system-name-form"}
|
||
];
|
||
|
||
modalsConfig.forEach(({modalId,formId})=>{
|
||
let modal=document.getElementById(modalId);
|
||
let form=document.getElementById(formId);
|
||
if(modal&&form){
|
||
modal.addEventListener("hidden.bs.modal",()=>{
|
||
form.reset();
|
||
});
|
||
}
|
||
});
|
||
}); |