refactor: Update Mikrotik config validation logic to improve brace counting accuracy and enhance AutoUrlManager UI with consistent card layouts, larger icons, and refined button styles for better user experience.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m50s

This commit is contained in:
2025-12-06 14:57:41 +07:00
parent fee74c377f
commit 8d6d2bbe25
2 changed files with 45 additions and 58 deletions
+5 -2
View File
@@ -39,8 +39,11 @@ function validateMikrotikConfig(config) {
inBlock = true; inBlock = true;
blockName = line.match(/^\/\w+(\s+\w+)*/)?.[0] || ''; blockName = line.match(/^\/\w+(\s+\w+)*/)?.[0] || '';
currentBlockLine = lineNum; currentBlockLine = lineNum;
braceBalance++; // Считаем скобки только один раз для этой строки (чтобы не дублировать подсчёт ниже)
continue; const openBraces = (line.match(/\{/g) || []).length;
const closeBraces = (line.match(/\}/g) || []).length;
braceBalance += openBraces - closeBraces;
continue;
} }
// Подсчет фигурных скобок // Подсчет фигурных скобок
+40 -56
View File
@@ -385,69 +385,53 @@ function AutoUrlManager() {
{!loading && urls.length > 0 && ( {!loading && urls.length > 0 && (
<div className="row g-3 mb-4"> <div className="row g-3 mb-4">
<div className="col-md-3"> <div className="col-md-3">
<div className="card card-sm"> <div className="card h-100">
<div className="card-body"> <div className="card-body d-flex align-items-center">
<div className="row align-items-center"> <span className="avatar avatar-lg me-3 bg-blue-lt text-blue border-0">
<div className="col-auto"> <IconWorld size={32} />
<span className="avatar avatar-lg bg-blue-lt text-blue"> </span>
<IconWorld size={24} /> <div>
</span> <div className="h3 mb-0 fw-bold">{stats.total}</div>
</div> <div className="text-muted small">Всего URL</div>
<div className="col">
<div className="font-weight-medium">{stats.total}</div>
<div className="text-muted small">Всего URL</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="col-md-3"> <div className="col-md-3">
<div className="card card-sm"> <div className="card h-100">
<div className="card-body"> <div className="card-body d-flex align-items-center">
<div className="row align-items-center"> <span className="avatar avatar-lg me-3 bg-green-lt text-green border-0">
<div className="col-auto"> <IconCheck size={32} />
<span className="avatar avatar-lg bg-green-lt text-green"> </span>
<IconCheck size={24} /> <div>
</span> <div className="h3 mb-0 fw-bold">{stats.valid}</div>
</div> <div className="text-muted small">Валидных</div>
<div className="col">
<div className="font-weight-medium">{stats.valid}</div>
<div className="text-muted small">Валидных</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="col-md-3"> <div className="col-md-3">
<div className="card card-sm"> <div className="card h-100">
<div className="card-body"> <div className="card-body d-flex align-items-center">
<div className="row align-items-center"> <span className="avatar avatar-lg me-3 bg-red-lt text-red border-0">
<div className="col-auto"> <IconAlertCircle size={32} />
<span className="avatar avatar-lg bg-red-lt text-red"> </span>
<IconAlertCircle size={24} /> <div>
</span> <div className="h3 mb-0 fw-bold">{stats.invalid}</div>
</div> <div className="text-muted small">Невалидных</div>
<div className="col">
<div className="font-weight-medium">{stats.invalid}</div>
<div className="text-muted small">Невалидных</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="col-md-3"> <div className="col-md-3">
<div className="card card-sm"> <div className="card h-100">
<div className="card-body"> <div className="card-body d-flex align-items-center">
<div className="row align-items-center"> <span className="avatar avatar-lg me-3 bg-azure-lt text-azure border-0">
<div className="col-auto"> <IconLink size={32} />
<span className="avatar avatar-lg bg-orange-lt text-orange"> </span>
<IconLink size={24} /> <div>
</span> <div className="h3 mb-0 fw-bold">{filteredAndSortedUrls.length}</div>
</div> <div className="text-muted small">Отображается</div>
<div className="col">
<div className="font-weight-medium">{filteredAndSortedUrls.length}</div>
<div className="text-muted small">Отображается</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -465,8 +449,8 @@ function AutoUrlManager() {
</h3> </h3>
</div> </div>
<div className="col-auto"> <div className="col-auto">
<div className="input-group" style={{ maxWidth: 300 }}> <div className="input-icon" style={{ maxWidth: 320 }}>
<span className="input-group-text"> <span className="input-icon-addon">
<IconSearch size={16} /> <IconSearch size={16} />
</span> </span>
<input <input
@@ -479,7 +463,7 @@ function AutoUrlManager() {
/> />
{searchTerm && ( {searchTerm && (
<button <button
className="btn btn-outline-secondary" className="btn btn-icon btn-sm btn-outline-secondary position-absolute top-50 end-0 translate-middle-y me-1"
type="button" type="button"
onClick={() => setSearchTerm('')} onClick={() => setSearchTerm('')}
title="Очистить поиск" title="Очистить поиск"
@@ -490,16 +474,16 @@ function AutoUrlManager() {
</div> </div>
</div> </div>
<div className="col-auto"> <div className="col-auto">
<div className="btn-group"> <div className="btn-group btn-group-sm">
<button <button
className={`btn btn-sm ${filterValid === 'all' ? 'btn-primary' : 'btn-outline-secondary'}`} className={`btn ${filterValid === 'all' ? 'btn-primary' : 'btn-outline-secondary'}`}
onClick={() => setFilterValid('all')} onClick={() => setFilterValid('all')}
title="Все записи" title="Все записи"
> >
Все Все
</button> </button>
<button <button
className={`btn btn-sm ${filterValid === 'valid' ? 'btn-success' : 'btn-outline-success'}`} className={`btn ${filterValid === 'valid' ? 'btn-success' : 'btn-outline-success'}`}
onClick={() => setFilterValid('valid')} onClick={() => setFilterValid('valid')}
title="Только валидные" title="Только валидные"
> >
@@ -507,7 +491,7 @@ function AutoUrlManager() {
Валидные Валидные
</button> </button>
<button <button
className={`btn btn-sm ${filterValid === 'invalid' ? 'btn-danger' : 'btn-outline-danger'}`} className={`btn ${filterValid === 'invalid' ? 'btn-danger' : 'btn-outline-danger'}`}
onClick={() => setFilterValid('invalid')} onClick={() => setFilterValid('invalid')}
title="Только невалидные" title="Только невалидные"
> >
@@ -647,7 +631,7 @@ function AutoUrlManager() {
return ( return (
<tr <tr
key={originalIndex} key={originalIndex}
className={`${isSelected ? 'table-active' : ''} ${isInvalid ? 'table-danger' : isValid ? 'table-success' : ''}`} className={isSelected ? 'table-active' : ''}
> >
<td> <td>
<input <input