feat: Introduce baseAS state management in FilterManager and SettingsModal, enhancing community search normalization and user settings configuration for improved filtering accuracy.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m54s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m54s
This commit is contained in:
@@ -71,7 +71,7 @@ const countryToFlag = (code) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Компонент автокомплита для выбора Community
|
// Компонент автокомплита для выбора Community
|
||||||
function CommunityAutocomplete({ label, value, onChange, communities = [], required = false, placeholder = 'Введите или выберите community...' }) {
|
function CommunityAutocomplete({ label, value, onChange, communities = [], required = false, placeholder = 'Введите или выберите community...', baseAS = '65001' }) {
|
||||||
const [inputValue, setInputValue] = useState(value || '');
|
const [inputValue, setInputValue] = useState(value || '');
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
||||||
@@ -89,9 +89,22 @@ function CommunityAutocomplete({ label, value, onChange, communities = [], requi
|
|||||||
|
|
||||||
const cValue = (c.value || '').toLowerCase();
|
const cValue = (c.value || '').toLowerCase();
|
||||||
|
|
||||||
// Поиск по полному значению
|
// Нормализуем значение из справочника с учётом baseAS
|
||||||
|
// Если в справочнике просто число (например "120"), считаем его как "baseAS:120"
|
||||||
|
const normalizedCValue = cValue.includes(':') ? cValue : `${baseAS}:${cValue}`;
|
||||||
|
|
||||||
|
// Нормализуем поисковый запрос
|
||||||
|
// Если введено просто число, считаем его как "baseAS:число"
|
||||||
|
const normalizedSearch = search.includes(':') ? search : `${baseAS}:${search}`;
|
||||||
|
|
||||||
|
// Поиск по полному значению (с нормализацией)
|
||||||
|
if (normalizedCValue.includes(search)) return true;
|
||||||
if (cValue.includes(search)) return true;
|
if (cValue.includes(search)) return true;
|
||||||
|
|
||||||
|
// Поиск нормализованного значения
|
||||||
|
if (normalizedCValue === normalizedSearch) return true;
|
||||||
|
if (normalizedCValue.includes(normalizedSearch)) return true;
|
||||||
|
|
||||||
// Поиск по части после двоеточия (например, "120" найдёт "65001:120")
|
// Поиск по части после двоеточия (например, "120" найдёт "65001:120")
|
||||||
if (cValue.includes(':')) {
|
if (cValue.includes(':')) {
|
||||||
const parts = cValue.split(':');
|
const parts = cValue.split(':');
|
||||||
@@ -108,6 +121,11 @@ function CommunityAutocomplete({ label, value, onChange, communities = [], requi
|
|||||||
if (searchParts[1] && cValue.includes(searchParts[1])) return true;
|
if (searchParts[1] && cValue.includes(searchParts[1])) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Поиск просто по числу без AS
|
||||||
|
if (!search.includes(':') && !cValue.includes(':')) {
|
||||||
|
if (cValue.includes(search)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Поиск по названию и описанию
|
// Поиск по названию и описанию
|
||||||
if (c.name && c.name.toLowerCase().includes(search)) return true;
|
if (c.name && c.name.toLowerCase().includes(search)) return true;
|
||||||
if (c.description && c.description.toLowerCase().includes(search)) return true;
|
if (c.description && c.description.toLowerCase().includes(search)) return true;
|
||||||
@@ -586,6 +604,8 @@ function FilterManager() {
|
|||||||
|
|
||||||
// Communities directory for autocomplete
|
// Communities directory for autocomplete
|
||||||
const [communities, setCommunities] = useState([]);
|
const [communities, setCommunities] = useState([]);
|
||||||
|
// Базовая AS из настроек
|
||||||
|
const [baseAS, setBaseAS] = useState('65001');
|
||||||
// Inventory servers (from /servers endpoint)
|
// Inventory servers (from /servers endpoint)
|
||||||
const [inventoryServers, setInventoryServers] = useState([]);
|
const [inventoryServers, setInventoryServers] = useState([]);
|
||||||
|
|
||||||
@@ -647,6 +667,17 @@ function FilterManager() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Загружаем базовую AS из настроек
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await api.get('/ui-settings');
|
||||||
|
const data = res?.data || {};
|
||||||
|
if (data?.baseAS) setBaseAS(String(data.baseAS));
|
||||||
|
} catch (e) {
|
||||||
|
// мягко игнорируем, используем значение по умолчанию
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await api.get(`/communities`);
|
const res = await api.get(`/communities`);
|
||||||
@@ -1815,6 +1846,7 @@ function FilterManager() {
|
|||||||
value={newFilter.community}
|
value={newFilter.community}
|
||||||
onChange={(val) => setNewFilter({ ...newFilter, community: val })}
|
onChange={(val) => setNewFilter({ ...newFilter, community: val })}
|
||||||
communities={communities}
|
communities={communities}
|
||||||
|
baseAS={baseAS}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1855,6 +1887,7 @@ function FilterManager() {
|
|||||||
value={editingFilter.community}
|
value={editingFilter.community}
|
||||||
onChange={(val) => setEditingFilter({ ...editingFilter, community: val })}
|
onChange={(val) => setEditingFilter({ ...editingFilter, community: val })}
|
||||||
communities={communities}
|
communities={communities}
|
||||||
|
baseAS={baseAS}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export default function SettingsModal({ open, onClose }) {
|
|||||||
const [etag, setEtag] = useState('');
|
const [etag, setEtag] = useState('');
|
||||||
const [dohServer, setDohServer] = useState('');
|
const [dohServer, setDohServer] = useState('');
|
||||||
const [wsUrl, setWsUrl] = useState('');
|
const [wsUrl, setWsUrl] = useState('');
|
||||||
|
const [baseAS, setBaseAS] = useState('65001');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) return;
|
||||||
@@ -29,6 +30,7 @@ export default function SettingsModal({ open, onClose }) {
|
|||||||
const data = res?.data || {};
|
const data = res?.data || {};
|
||||||
setDohServer(String(data?.dohServer || ''));
|
setDohServer(String(data?.dohServer || ''));
|
||||||
setWsUrl(String(data?.wsUpdateUrl || ''));
|
setWsUrl(String(data?.wsUpdateUrl || ''));
|
||||||
|
setBaseAS(String(data?.baseAS || '65001'));
|
||||||
const e = res?.headers?.etag || res?.headers?.ETag || '';
|
const e = res?.headers?.etag || res?.headers?.ETag || '';
|
||||||
setEtag(e ? String(e) : '');
|
setEtag(e ? String(e) : '');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -87,7 +89,8 @@ export default function SettingsModal({ open, onClose }) {
|
|||||||
const payload = {
|
const payload = {
|
||||||
settings: {
|
settings: {
|
||||||
dohServer: String(dohServer || '').trim(),
|
dohServer: String(dohServer || '').trim(),
|
||||||
wsUpdateUrl: String(wsUrl || '').trim()
|
wsUpdateUrl: String(wsUrl || '').trim(),
|
||||||
|
baseAS: String(baseAS || '65001').trim()
|
||||||
},
|
},
|
||||||
etag
|
etag
|
||||||
};
|
};
|
||||||
@@ -172,6 +175,17 @@ export default function SettingsModal({ open, onClose }) {
|
|||||||
helpText="HTTPS URL для DNS-over-HTTPS"
|
helpText="HTTPS URL для DNS-over-HTTPS"
|
||||||
disabled={loading || saving}
|
disabled={loading || saving}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
label="Базовая AS"
|
||||||
|
name="baseAS"
|
||||||
|
type="text"
|
||||||
|
value={baseAS}
|
||||||
|
onChange={setBaseAS}
|
||||||
|
placeholder="65001"
|
||||||
|
helpText="AS по умолчанию для community (например, 65001). Используется при поиске и нормализации community."
|
||||||
|
disabled={loading || saving}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
|
|||||||
Reference in New Issue
Block a user