v1.8.6: сортировка таблиц, спиннеры number input, единый стиль — fix broken HTML, modal-actions → form-actions, card-wrapper
This commit is contained in:
@@ -235,6 +235,8 @@ docker logs aegisone-app --tail 10
|
|||||||
- **Модалки:** `.modal-overlay` + `.modal`, открытие через `classList.add('open')`
|
- **Модалки:** `.modal-overlay` + `.modal`, открытие через `classList.add('open')`
|
||||||
- **Структура страницы:** `card` > `card-header` > `filter-bar` > `table-wrap` > `table`
|
- **Структура страницы:** `card` > `card-header` > `filter-bar` > `table-wrap` > `table`
|
||||||
- **CSS классы кнопок:** `.btn-primary` (создать), `.btn-secondary` (редактировать), `.btn-danger` (удалить), `.btn-success` (выполнено)
|
- **CSS классы кнопок:** `.btn-primary` (создать), `.btn-secondary` (редактировать), `.btn-danger` (удалить), `.btn-success` (выполнено)
|
||||||
|
- **Сортировка таблиц:** `sort-table.js` подключён глобально в `base.html`, автоматически сортирует все `<table>` по клику на `<th>` (текст/число/дата)
|
||||||
|
- **Number input:** спиннеры скрыты глобально через CSS (`service.css`), `type="number"` выглядит как обычный input
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
1.8.5
|
1.8.6
|
||||||
@@ -1,5 +1,19 @@
|
|||||||
# Changelog — AegisOne Service Portal
|
# Changelog — AegisOne Service Portal
|
||||||
|
|
||||||
|
## 1.8.6 (02.06.2026)
|
||||||
|
### Новые функции
|
||||||
|
- **sort-table.js:** универсальный модуль сортировки таблиц по столбцам (текст/число/дата), подключён глобально
|
||||||
|
- **Number input:** спиннеры скрыты через CSS (`appearance: textfield`) на всех страницах
|
||||||
|
|
||||||
|
### Исправления
|
||||||
|
- **customers.html:** восстановлена сломанная HTML-структура — `.card` > `.card-header`, поиск в `.filter-bar`
|
||||||
|
- **bot_dialogues.html:** обёрнут в `.card` > `.card-header`, фильтры в `.filter-bar`, удалены кастомные `.page-header`/`.header-controls`
|
||||||
|
- **checklist.html:** `<h3>` обёрнут в `.card-header`
|
||||||
|
- **18 страниц:** `modal-actions` → `form-actions` (единый класс для кнопок в модалках)
|
||||||
|
- **charts.html:** `btn-xs` → `btn-sm`
|
||||||
|
- **assignments.html:** добавлена модалка подтверждения отвязки сотрудника
|
||||||
|
- **4 AJAX-страницы:** `sortTables()` вызывается после загрузки данных (bot_kb, bot_unknown, bot_consent, bot_tickets)
|
||||||
|
|
||||||
## 1.8.5 (02.06.2026)
|
## 1.8.5 (02.06.2026)
|
||||||
### Новые функции
|
### Новые функции
|
||||||
- **AGENTS.md (раздел 12):** правила по Идеям — агент может видеть, добавлять, менять статус, предлагать к реализации, реализовывать
|
- **AGENTS.md (раздел 12):** правила по Идеям — агент может видеть, добавлять, менять статус, предлагать к реализации, реализовывать
|
||||||
|
|||||||
@@ -227,4 +227,6 @@ showNotification('Текст уведомления', 'info'); // сине
|
|||||||
- [ ] Кнопки редактирования: `✎` (btn-secondary)
|
- [ ] Кнопки редактирования: `✎` (btn-secondary)
|
||||||
- [ ] Порядок кнопок в модалках: Действие → Отмена
|
- [ ] Порядок кнопок в модалках: Действие → Отмена
|
||||||
- [ ] Уведомления через `showNotification()`
|
- [ ] Уведомления через `showNotification()`
|
||||||
|
- [ ] Таблицы используют `sort-table.js` (автоматически через base.html)
|
||||||
|
- [ ] Number input без спиннеров (CSS в service.css)
|
||||||
- [ ] CSS-классы модалок: `.modal-overlay` / `.modal`
|
- [ ] CSS-классы модалок: `.modal-overlay` / `.modal`
|
||||||
|
|||||||
@@ -164,6 +164,17 @@ img { max-width:100%; height:auto; }
|
|||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Скрытие стандартных спиннеров на number input */
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* sort-table.js — Универсальный модуль сортировки таблиц.
|
||||||
|
*
|
||||||
|
* Автоматически находит все <table> на странице и делает
|
||||||
|
* заголовки <th> кликабельными для сортировки по столбцам.
|
||||||
|
*
|
||||||
|
* Использование:
|
||||||
|
* 1. Подключить <script src="/service/static/js/sort-table.js"></script>
|
||||||
|
* 2. Таблицы автоматически получают сортировку при загрузке
|
||||||
|
* 3. Для AJAX-таблиц: вызвать sortTables() после заполнения <tbody>
|
||||||
|
*/
|
||||||
|
(function(){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var SORT_CSS = [
|
||||||
|
'.sort-th { cursor:pointer; user-select:none; position:relative; padding-right:18px !important; }',
|
||||||
|
'.sort-th:hover { color:var(--accent); }',
|
||||||
|
'.sort-th::after { content:""; position:absolute; right:6px; top:50%; transform:translateY(-50%); width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent; border-top:5px solid var(--text-muted); opacity:0.4; }',
|
||||||
|
'.sort-th.sort-asc::after { border-top:none; border-bottom:5px solid var(--accent); opacity:1; }',
|
||||||
|
'.sort-th.sort-desc::after { border-top:5px solid var(--accent); opacity:1; }'
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
/* Встраиваем стили один раз */
|
||||||
|
function injectStyles(){
|
||||||
|
if(document.getElementById('sort-table-styles')) return;
|
||||||
|
var style = document.createElement('style');
|
||||||
|
style.id = 'sort-table-styles';
|
||||||
|
style.textContent = SORT_CSS;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Определение типа значения ячейки */
|
||||||
|
function getCellValue(tr, idx){
|
||||||
|
var td = tr.children[idx];
|
||||||
|
if(!td) return '';
|
||||||
|
var text = (td.textContent || '').trim();
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Парсинг числа из текста */
|
||||||
|
function parseNumber(text){
|
||||||
|
if(!text || text === '—' || text === '-') return NaN;
|
||||||
|
/* Убираем пробелы,.currency-символы, % */
|
||||||
|
var cleaned = text.replace(/[^\d,\.\-]/g, '').replace(',', '.');
|
||||||
|
var num = parseFloat(cleaned);
|
||||||
|
return isNaN(num) ? NaN : num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Парсинг даты из текста (DD.MM.YYYY или YYYY-MM-DD) */
|
||||||
|
function parseDate(text){
|
||||||
|
if(!text) return NaN;
|
||||||
|
/* DD.MM.YYYY HH:MM */
|
||||||
|
var m = text.match(/(\d{2})\.(\d{2})\.(\d{4})/);
|
||||||
|
if(m) return new Date(m[3], m[2]-1, m[1]).getTime();
|
||||||
|
/* YYYY-MM-DD */
|
||||||
|
m = text.match(/(\d{4})-(\d{2})-(\d{2})/);
|
||||||
|
if(m) return new Date(m[1], m[2]-1, m[3]).getTime();
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Сравнение двух значений */
|
||||||
|
function compare(a, b, type){
|
||||||
|
if(type === 'number'){
|
||||||
|
var na = parseNumber(a), nb = parseNumber(b);
|
||||||
|
if(isNaN(na) && isNaN(nb)) return 0;
|
||||||
|
if(isNaN(na)) return 1;
|
||||||
|
if(isNaN(nb)) return -1;
|
||||||
|
return na - nb;
|
||||||
|
}
|
||||||
|
if(type === 'date'){
|
||||||
|
var da = parseDate(a), db = parseDate(b);
|
||||||
|
if(isNaN(da) && isNaN(db)) return 0;
|
||||||
|
if(isNaN(da)) return 1;
|
||||||
|
if(isNaN(db)) return -1;
|
||||||
|
return da - db;
|
||||||
|
}
|
||||||
|
/* Текст */
|
||||||
|
return a.localeCompare(b, 'ru');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Определение типа столбца по первым строкам */
|
||||||
|
function detectColumnType(tbody, idx){
|
||||||
|
var rows = tbody.children;
|
||||||
|
var samples = [];
|
||||||
|
var limit = Math.min(rows.length, 10);
|
||||||
|
for(var i = 0; i < limit; i++){
|
||||||
|
samples.push(getCellValue(rows[i], idx));
|
||||||
|
}
|
||||||
|
var numCount = 0, dateCount = 0;
|
||||||
|
for(var j = 0; j < samples.length; j++){
|
||||||
|
if(parseNumber(samples[j]) !== NaN && samples[j] !== '') numCount++;
|
||||||
|
if(parseDate(samples[j]) !== NaN && samples[j] !== '') dateCount++;
|
||||||
|
}
|
||||||
|
if(samples.length > 0 && numCount / samples.length > 0.6) return 'number';
|
||||||
|
if(samples.length > 0 && dateCount / samples.length > 0.6) return 'date';
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Привязка сортировки к таблице */
|
||||||
|
function attachSort(table){
|
||||||
|
if(table.dataset.sortAttached) return;
|
||||||
|
table.dataset.sortAttached = '1';
|
||||||
|
|
||||||
|
var thead = table.querySelector('thead');
|
||||||
|
var tbody = table.querySelector('tbody');
|
||||||
|
if(!thead || !tbody) return;
|
||||||
|
|
||||||
|
var headers = thead.querySelectorAll('th');
|
||||||
|
headers.forEach(function(th, idx){
|
||||||
|
/* Пропускаем колонку действий */
|
||||||
|
if(th.classList.contains('actions')) return;
|
||||||
|
|
||||||
|
th.classList.add('sort-th');
|
||||||
|
th.dataset.sortIdx = idx;
|
||||||
|
th.dataset.sortDir = 'none';
|
||||||
|
|
||||||
|
th.addEventListener('click', function(){
|
||||||
|
var colIdx = parseInt(this.dataset.sortIdx);
|
||||||
|
var currentDir = this.dataset.sortDir;
|
||||||
|
var newDir = currentDir === 'asc' ? 'desc' : 'asc';
|
||||||
|
|
||||||
|
/* Сброс других столбцов */
|
||||||
|
headers.forEach(function(h){ h.classList.remove('sort-asc', 'sort-desc'); h.dataset.sortDir = 'none'; });
|
||||||
|
this.classList.remove('sort-asc', 'sort-desc');
|
||||||
|
this.classList.add('sort-' + newDir);
|
||||||
|
this.dataset.sortDir = newDir;
|
||||||
|
|
||||||
|
/* Определение типа данных */
|
||||||
|
var colType = detectColumnType(tbody, colIdx);
|
||||||
|
|
||||||
|
/* Сбор строк с значениями */
|
||||||
|
var rowsArray = Array.prototype.slice.call(tbody.querySelectorAll('tr'));
|
||||||
|
rowsArray.sort(function(rowA, rowB){
|
||||||
|
var valA = getCellValue(rowA, colIdx);
|
||||||
|
var valB = getCellValue(rowB, colIdx);
|
||||||
|
var result = compare(valA, valB, colType);
|
||||||
|
return newDir === 'asc' ? result : -result;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Перестановка строк */
|
||||||
|
rowsArray.forEach(function(row){ tbody.appendChild(row); });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Публичная функция: инициализация/переинициализация всех таблиц */
|
||||||
|
function sortTables(){
|
||||||
|
injectStyles();
|
||||||
|
var tables = document.querySelectorAll('table');
|
||||||
|
for(var i = 0; i < tables.length; i++){
|
||||||
|
attachSort(tables[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Автозапуск после загрузки DOM */
|
||||||
|
if(document.readyState === 'loading'){
|
||||||
|
document.addEventListener('DOMContentLoaded', sortTables);
|
||||||
|
} else {
|
||||||
|
sortTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Экспорт в глобальную область */
|
||||||
|
window.sortTables = sortTables;
|
||||||
|
})();
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<div class="toast-container" id="toast-container"></div>
|
<div class="toast-container" id="toast-container"></div>
|
||||||
<script src="/service/static/js/theme.js"></script>
|
<script src="/service/static/js/theme.js"></script>
|
||||||
<script src="/service/static/js/role-switcher.js"></script>
|
<script src="/service/static/js/role-switcher.js"></script>
|
||||||
|
<script src="/service/static/js/sort-table.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function showNotification(msg, type){
|
function showNotification(msg, type){
|
||||||
type = type || 'success';
|
type = type || 'success';
|
||||||
|
|||||||
@@ -10,10 +10,7 @@
|
|||||||
<td><span class="badge badge-{{ a.role }}">{{ {'engineer':'Инженер','technician':'Техник'}[a.role] }}</span></td>
|
<td><span class="badge badge-{{ a.role }}">{{ {'engineer':'Инженер','technician':'Техник'}[a.role] }}</span></td>
|
||||||
<td>{{ a.assigned_at.strftime('%d.%m.%Y %H:%M') if a.assigned_at else '' }}</td>
|
<td>{{ a.assigned_at.strftime('%d.%m.%Y %H:%M') if a.assigned_at else '' }}</td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<form method="post" action="/service/assignments/unassign" style="display:inline">
|
<button class="btn btn-danger btn-sm" onclick="openConfirmUnassign({{ a.id }},'{{ (a.user.full_name if a.user else '')|e }}','{{ (a.object.name if a.object else '')|e }}')" title="Отвязать">✕</button>
|
||||||
<input type="hidden" name="id" value="{{ a.id }}">
|
|
||||||
<button class="btn btn-danger btn-sm">Отвязать</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>{% endfor %}</tbody></table>
|
</tr>{% endfor %}</tbody></table>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,7 +22,38 @@
|
|||||||
<div class="form-group"><label>Объект</label><select name="object_id" required>{% for o in objects %}<option value="{{ o.id }}">{{ o.name }}</option>{% endfor %}</select></div>
|
<div class="form-group"><label>Объект</label><select name="object_id" required>{% for o in objects %}<option value="{{ o.id }}">{{ o.name }}</option>{% endfor %}</select></div>
|
||||||
<div class="form-group"><label>Сотрудник</label><select name="user_id" required>{% for u in users %}<option value="{{ u.id }}">{{ u.full_name }} ({{ u.role }})</option>{% endfor %}</select></div>
|
<div class="form-group"><label>Сотрудник</label><select name="user_id" required>{% for u in users %}<option value="{{ u.id }}">{{ u.full_name }} ({{ u.role }})</option>{% endfor %}</select></div>
|
||||||
<div class="form-actions"><button type="submit" class="btn btn-primary">Назначить</button>
|
<div class="form-actions"><button type="submit" class="btn btn-primary">Назначить</button>
|
||||||
<button type="button" class="btn btn-secondary" onclick="this.closest('.modal-overlay').classList.remove('open')">Отмена</button></div>
|
<button type="button" class="btn" onclick="this.closest('.modal-overlay').classList.remove('open')">Отмена</button></div>
|
||||||
</form>
|
</form>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
<div class="modal-overlay" id="confirm-unassign">
|
||||||
|
<div class="modal" style="max-width:420px;">
|
||||||
|
<h2 style="font-size:16px;margin-bottom:8px;">Отвязать сотрудника?</h2>
|
||||||
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
|
Назначение <strong id="unassign-info"></strong> будет удалено. Это действие нельзя отменить.
|
||||||
|
</p>
|
||||||
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
|
<button type="button" class="btn btn-danger" onclick="confirmUnassign()">Отвязать</button>
|
||||||
|
<button type="button" class="btn" onclick="document.getElementById('confirm-unassign').classList.remove('open')">Отмена</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var unassignId = null;
|
||||||
|
function openConfirmUnassign(id, userName, objectName){
|
||||||
|
unassignId = id;
|
||||||
|
document.getElementById('unassign-info').textContent = userName + ' → ' + objectName;
|
||||||
|
document.getElementById('confirm-unassign').classList.add('open');
|
||||||
|
}
|
||||||
|
function confirmUnassign(){
|
||||||
|
if(!unassignId) return;
|
||||||
|
var form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = '/service/assignments/unassign';
|
||||||
|
var input = document.createElement('input');
|
||||||
|
input.type = 'hidden'; input.name = 'id'; input.value = unassignId;
|
||||||
|
form.appendChild(input);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-blog-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-blog-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteBlog()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteBlog()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteBlog()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteBlog()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
.modal { background:var(--bg-card); border:1px solid var(--border); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
.modal { background:var(--bg-card); border:1px solid var(--border); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
||||||
.modal h2 { color:var(--text-primary); }
|
.modal h2 { color:var(--text-primary); }
|
||||||
.modal p { color:var(--text-secondary); }
|
.modal p { color:var(--text-secondary); }
|
||||||
.modal-actions { display:flex; gap:10px; }
|
.form-actions { display:flex; gap:10px; }
|
||||||
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
||||||
.btn { background:var(--bg-input); color:var(--text-primary); border:1px solid var(--border); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
.btn { background:var(--bg-input); color:var(--text-primary); border:1px solid var(--border); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
||||||
</style>
|
</style>
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
Все его диалоги и сообщения будут удалены. Заявки останутся.
|
Все его диалоги и сообщения будут удалены. Заявки останутся.
|
||||||
Это действие нельзя отменить.
|
Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteUser()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteUser()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteUser()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteUser()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -165,6 +165,7 @@ function renderConsents(list){
|
|||||||
html += '</tr>';
|
html += '</tr>';
|
||||||
});
|
});
|
||||||
tbody.innerHTML = html;
|
tbody.innerHTML = html;
|
||||||
|
if(typeof sortTables === 'function') sortTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterConsents(){
|
function filterConsents(){
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
{% extends "page.html" %}
|
{% extends "page.html" %}
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="page-header">
|
<div class="card">
|
||||||
<h1>Диалоги чат-бота</h1>
|
<div class="card-header"><h2>Диалоги чат-бота</h2>
|
||||||
<div class="header-controls">
|
<button onclick="loadConversations()" class="btn btn-primary btn-sm">Обновить</button>
|
||||||
<input type="text" id="search-input" placeholder="Поиск по ID или имени..." oninput="filterConversations()" class="filter-input">
|
|
||||||
<button onclick="loadConversations()" class="btn btn-primary">Обновить</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="filter-bar">
|
||||||
<script>var USER_ROLE = '{{ user.role }}';</script>
|
<input type="text" id="search-input" placeholder="Поиск по ID или имени..." oninput="filterConversations()">
|
||||||
<div style="margin-bottom:12px;display:flex;gap:8px;flex-wrap:wrap;">
|
|
||||||
<select id="status-filter" onchange="filterConversations()" class="filter-select">
|
<select id="status-filter" onchange="filterConversations()" class="filter-select">
|
||||||
<option value="">Все статусы</option>
|
<option value="">Все статусы</option>
|
||||||
<option value="greeting">Приветствие</option>
|
<option value="greeting">Приветствие</option>
|
||||||
@@ -19,9 +16,11 @@
|
|||||||
<option value="question">Вопрос</option>
|
<option value="question">Вопрос</option>
|
||||||
<option value="done">Завершён</option>
|
<option value="done">Завершён</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="conversations-container">
|
<script>var USER_ROLE = '{{ user.role }}';</script>
|
||||||
|
<div id="conversations-container">
|
||||||
<div class="loading"><div class="spinner"></div></div>
|
<div class="loading"><div class="spinner"></div></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-overlay" id="dialog-modal">
|
<div class="modal-overlay" id="dialog-modal">
|
||||||
@@ -44,7 +43,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
Диалог с <strong id="delete-conv-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
Диалог с <strong id="delete-conv-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDelete()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDelete()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeDeleteModal()">Отмена</button>
|
<button type="button" class="btn" onclick="closeDeleteModal()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,13 +75,8 @@
|
|||||||
.log-time { font-size:10px; color:var(--text-muted,#6B8299); }
|
.log-time { font-size:10px; color:var(--text-muted,#6B8299); }
|
||||||
.tab-btn { padding:6px 14px; border:1px solid var(--border,#253248); background:transparent; color:var(--text-primary,#E8EDF2); border-radius:4px; cursor:pointer; font-size:12px; }
|
.tab-btn { padding:6px 14px; border:1px solid var(--border,#253248); background:transparent; color:var(--text-primary,#E8EDF2); border-radius:4px; cursor:pointer; font-size:12px; }
|
||||||
.tab-btn.active { background:var(--accent,#00ADEF); border-color:var(--accent,#00ADEF); color:#fff; }
|
.tab-btn.active { background:var(--accent,#00ADEF); border-color:var(--accent,#00ADEF); color:#fff; }
|
||||||
.page-header { display:flex; justify-content:space-between; align-items:center; margin-bottom:16px; flex-wrap:wrap; gap:8px; }
|
|
||||||
.header-controls { display:flex; gap:8px; align-items:center; }
|
|
||||||
.filter-input { padding:6px 10px; border:1px solid var(--border,#253248); border-radius:4px; background:var(--bg-body,#1B2838); color:var(--text-primary,#E8EDF2); font-size:12px; width:200px; }
|
|
||||||
.filter-select { padding:6px 10px; border:1px solid var(--border,#253248); border-radius:4px; background:var(--bg-body,#1B2838); color:var(--text-primary,#E8EDF2); font-size:12px; }
|
|
||||||
.conv-delete { background:none; border:none; cursor:pointer; font-size:14px; padding:2px 6px; border-radius:4px; opacity:0.5; transition:opacity 0.2s; margin-left:auto; }
|
.conv-delete { background:none; border:none; cursor:pointer; font-size:14px; padding:2px 6px; border-radius:4px; opacity:0.5; transition:opacity 0.2s; margin-left:auto; }
|
||||||
.conv-delete:hover { opacity:1; background:rgba(232,107,107,0.15); }
|
.conv-delete:hover { opacity:1; background:rgba(232,107,107,0.15); }
|
||||||
.conv-header { display:flex; align-items:center; gap:8px; }
|
|
||||||
#delete-modal .modal { max-width:420px; }
|
#delete-modal .modal { max-width:420px; }
|
||||||
#delete-modal h2 { font-size:16px; margin-bottom:8px; }
|
#delete-modal h2 { font-size:16px; margin-bottom:8px; }
|
||||||
#delete-modal p { color:var(--text-secondary); font-size:14px; }
|
#delete-modal p { color:var(--text-secondary); font-size:14px; }
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
<input type="url" name="source_url" id="kb-source-url" placeholder="https://aegisone.ru/...">
|
<input type="url" name="source_url" id="kb-source-url" placeholder="https://aegisone.ru/...">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check"><input type="checkbox" name="is_active" id="kb-is-active" checked><label for="kb-is-active">Активная карточка</label></div>
|
<div class="form-check"><input type="checkbox" name="is_active" id="kb-is-active" checked><label for="kb-is-active">Активная карточка</label></div>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||||
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
Карточка <strong id="delete-kb-name"></strong> будет удалена навсегда. Это действие нельзя отменить.
|
Карточка <strong id="delete-kb-name"></strong> будет удалена навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteKB()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteKB()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteKB()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteKB()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,6 +129,7 @@ function renderKB(cards){
|
|||||||
'</tr>';
|
'</tr>';
|
||||||
});
|
});
|
||||||
tbody.innerHTML = html;
|
tbody.innerHTML = html;
|
||||||
|
if(typeof sortTables === 'function') sortTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterKB(){
|
function filterKB(){
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ body { font-family:'Inter','Segoe UI',sans-serif; background:var(--bg-body, #1B2
|
|||||||
.modal { background:var(--bg-card, #0A1628); border:1px solid var(--border, #253248); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
.modal { background:var(--bg-card, #0A1628); border:1px solid var(--border, #253248); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
||||||
.modal h2 { color:var(--text-primary, #E8EDF2); }
|
.modal h2 { color:var(--text-primary, #E8EDF2); }
|
||||||
.modal p { color:var(--text-muted, #6B8299); }
|
.modal p { color:var(--text-muted, #6B8299); }
|
||||||
.modal-actions { display:flex; gap:10px; }
|
.form-actions { display:flex; gap:10px; }
|
||||||
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
||||||
.btn { background:var(--bg-input, #253248); color:var(--text-primary, #E8EDF2); border:1px solid var(--border, #3a4a60); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
.btn { background:var(--bg-input, #253248); color:var(--text-primary, #E8EDF2); border:1px solid var(--border, #3a4a60); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
||||||
</style>
|
</style>
|
||||||
@@ -72,7 +72,7 @@ body { font-family:'Inter','Segoe UI',sans-serif; background:var(--bg-body, #1B2
|
|||||||
Удалить все тестовые диалоги, сообщения и логи обработки?
|
Удалить все тестовые диалоги, сообщения и логи обработки?
|
||||||
Это действие нельзя отменить.
|
Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmClearTest()">Сбросить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmClearTest()">Сбросить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmClearTest()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmClearTest()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ function renderTickets(tickets){
|
|||||||
'</tr>';
|
'</tr>';
|
||||||
});
|
});
|
||||||
tbody.innerHTML = html;
|
tbody.innerHTML = html;
|
||||||
|
if(typeof sortTables === 'function') sortTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterTickets(){
|
function filterTickets(){
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<option value="8">Отрасли и кейсы</option>
|
<option value="8">Отрасли и кейсы</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="submit" class="btn btn-primary">Опубликовать в базу знаний</button>
|
<button type="submit" class="btn btn-primary">Опубликовать в базу знаний</button>
|
||||||
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
<button type="button" class="btn" onclick="closeModal()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
Вопрос <strong id="ignore-uq-text"></strong> будет отмечен как игнорированный.
|
Вопрос <strong id="ignore-uq-text"></strong> будет отмечен как игнорированный.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmIgnoreUQ()">Игнорировать</button>
|
<button type="button" class="btn btn-danger" onclick="confirmIgnoreUQ()">Игнорировать</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmIgnoreUQ()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmIgnoreUQ()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,6 +142,7 @@ function renderUQ(items){
|
|||||||
html += '</td></tr>';
|
html += '</td></tr>';
|
||||||
});
|
});
|
||||||
tbody.innerHTML = html;
|
tbody.innerHTML = html;
|
||||||
|
if(typeof sortTables === 'function') sortTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openReview(id){
|
function openReview(id){
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-case-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-case-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteCase()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteCase()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteCase()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteCase()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
.modal { background:var(--bg-card); border:1px solid var(--border); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
.modal { background:var(--bg-card); border:1px solid var(--border); border-radius:12px; padding:24px; width:420px; max-width:90vw; }
|
||||||
.modal h2 { color:var(--text-primary); }
|
.modal h2 { color:var(--text-primary); }
|
||||||
.modal p { color:var(--text-secondary); }
|
.modal p { color:var(--text-secondary); }
|
||||||
.modal-actions { display:flex; gap:10px; }
|
.form-actions { display:flex; gap:10px; }
|
||||||
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
.btn-danger { background:var(--danger, #dc3545); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
||||||
.btn-primary { background:var(--accent, #00ADEF); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
.btn-primary { background:var(--accent, #00ADEF); color:#fff; border:none; padding:8px 16px; border-radius:6px; cursor:pointer; font-weight:600; }
|
||||||
.btn { background:var(--bg-input); color:var(--text-primary); border:1px solid var(--border); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
.btn { background:var(--bg-input); color:var(--text-primary); border:1px solid var(--border); padding:8px 16px; border-radius:6px; cursor:pointer; }
|
||||||
@@ -42,11 +42,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="filter-bar" style="margin-top:8px;flex-wrap:wrap;gap:6px;">
|
<div class="filter-bar" style="margin-top:8px;flex-wrap:wrap;gap:6px;">
|
||||||
<span style="font-size:12px;color:var(--text-muted);">Пользовательские графики:</span>
|
<span style="font-size:12px;color:var(--text-muted);">Пользовательские графики:</span>
|
||||||
<button class="btn btn-secondary btn-xs" onclick="saveCustomChart()">Сохранить текущий</button>
|
<button class="btn btn-secondary btn-sm" onclick="saveCustomChart()">Сохранить текущий</button>
|
||||||
<select id="custom-chart-select" onchange="loadCustomChart(this.value)">
|
<select id="custom-chart-select" onchange="loadCustomChart(this.value)">
|
||||||
<option value="">— Загрузить —</option>
|
<option value="">— Загрузить —</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-danger btn-xs" onclick="deleteCustomChart()">Удалить</button>
|
<button class="btn btn-danger btn-sm" onclick="deleteCustomChart()">Удалить</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="position:relative;height:400px;">
|
<div style="position:relative;height:400px;">
|
||||||
<canvas id="chart-canvas"></canvas>
|
<canvas id="chart-canvas"></canvas>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" id="chart-name-input" placeholder="Введите название..." style="width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:14px;background:var(--bg-card);color:var(--text);box-sizing:border-box;">
|
<input type="text" id="chart-name-input" placeholder="Введите название..." style="width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:6px;font-size:14px;background:var(--bg-card);color:var(--text);box-sizing:border-box;">
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;margin-top:16px;">
|
<div class="form-actions" style="justify-content:flex-end;margin-top:16px;">
|
||||||
<button type="button" class="btn btn-primary" onclick="confirmSaveChart()">Сохранить</button>
|
<button type="button" class="btn btn-primary" onclick="confirmSaveChart()">Сохранить</button>
|
||||||
<button type="button" class="btn" onclick="closeChartNameModal()">Отмена</button>
|
<button type="button" class="btn" onclick="closeChartNameModal()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<strong id="delete-chart-name"></strong> будет удалён навсегда.
|
<strong id="delete-chart-name"></strong> будет удалён навсегда.
|
||||||
Это действие нельзя отменить.
|
Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteChart()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteChart()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteChart()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteChart()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
{% for t in tasks %}
|
{% for t in tasks %}
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>{{ t.title }}</h3>
|
<div class="card-header"><h3>{{ t.title }}</h3></div>
|
||||||
<div style="font-size:12px;color:var(--text-muted);margin-bottom:12px;">
|
<div style="font-size:12px;color:var(--text-muted);margin-bottom:12px;">
|
||||||
{{ t.object.name if t.object else '' }} — {{ t.object.address if t.object else '' }}
|
{{ t.object.name if t.object else '' }} — {{ t.object.address if t.object else '' }}
|
||||||
<span class="badge badge-{{ {'P1':'critical','P2':'high','P3':'medium','P4':'low'}[t.priority] }}" style="margin-left:8px;">{{ t.priority }}</span>
|
<span class="badge badge-{{ {'P1':'critical','P2':'high','P3':'medium','P4':'low'}[t.priority] }}" style="margin-left:8px;">{{ t.priority }}</span>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-coeff-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-coeff-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteCoeff()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteCoeff()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteCoeff()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteCoeff()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,10 +3,9 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header"><h2>Клиенты</h2>
|
<div class="card-header"><h2>Клиенты</h2>
|
||||||
{% if error %}<div class="alert alert-error" style="margin-bottom:12px;padding:8px 12px;background:rgba(239,68,68,0.1);border:1px solid rgba(239,68,68,0.3);border-radius:6px;color:var(--danger);font-size:13px;">{{ error }}</div>{% endif %}
|
{% if error %}<div class="alert alert-error" style="margin-bottom:12px;padding:8px 12px;background:rgba(239,68,68,0.1);border:1px solid rgba(239,68,68,0.3);border-radius:6px;color:var(--danger);font-size:13px;">{{ error }}</div>{% endif %}
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary btn-sm" onclick="document.getElementById('modal-customer').classList.add('open')">+ Добавить</button>
|
<button class="btn btn-primary btn-sm" onclick="document.getElementById('modal-customer').classList.add('open')">+ Добавить</button>
|
||||||
</div>
|
</div>
|
||||||
<form method="get" class="search-box"><input type="text" name="search" placeholder="Поиск по названию или ИНН..." value="{{ search }}"><button class="btn btn-primary btn-sm">Найти</button></form>
|
<form method="get" class="filter-bar"><input type="text" name="search" placeholder="Поиск по названию или ИНН..." value="{{ search }}"><button class="btn btn-primary btn-sm">Найти</button></form>
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table><thead><tr><th>Название</th><th>ИНН</th><th>Контакты</th><th>Статус</th><th>Объекты</th><th>Активные SLA</th><th class="actions"></th></tr></thead>
|
<table><thead><tr><th>Название</th><th>ИНН</th><th>Контакты</th><th>Статус</th><th>Объекты</th><th>Активные SLA</th><th class="actions"></th></tr></thead>
|
||||||
<tbody>{% for d in customers %}<tr>
|
<tbody>{% for d in customers %}<tr>
|
||||||
@@ -59,7 +58,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-customer-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-customer-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteCustomer()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteCustomer()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteCustomer()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteCustomer()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -205,7 +205,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-formula-coeff-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-formula-coeff-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteFormulaCoeff()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteFormulaCoeff()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteFormulaCoeff()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteFormulaCoeff()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-idea-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-idea-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteIdea()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteIdea()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteIdea()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteIdea()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-object-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-object-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteObject()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteObject()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteObject()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteObject()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-qitem-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-qitem-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteQitem()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteQitem()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteQitem()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteQitem()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-task-name"></strong> будет завершена. Это действие нельзя отменить.
|
<strong id="delete-task-name"></strong> будет завершена. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-success" onclick="confirmCloseTask()">Завершить</button>
|
<button type="button" class="btn btn-success" onclick="confirmCloseTask()">Завершить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmCloseTask()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmCloseTask()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
<p style="color:var(--text-secondary);font-size:14px;margin-bottom:20px;">
|
||||||
<strong id="delete-user-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
<strong id="delete-user-name"></strong> будет удалён навсегда. Это действие нельзя отменить.
|
||||||
</p>
|
</p>
|
||||||
<div class="modal-actions" style="justify-content:flex-end;">
|
<div class="form-actions" style="justify-content:flex-end;">
|
||||||
<button type="button" class="btn btn-danger" onclick="confirmDeleteUser()">Удалить</button>
|
<button type="button" class="btn btn-danger" onclick="confirmDeleteUser()">Удалить</button>
|
||||||
<button type="button" class="btn" onclick="closeConfirmDeleteUser()">Отмена</button>
|
<button type="button" class="btn" onclick="closeConfirmDeleteUser()">Отмена</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.8.5
|
1.8.6
|
||||||
Reference in New Issue
Block a user