feat: Integrate @tanstack/react-query for improved data fetching and state management in HistoryModal; update API error handling and enhance request interceptors for better error notifications
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 5m12s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 5m12s
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
export default function ConfirmDialog({ open, title, message, confirmText = 'Подтвердить', cancelText = 'Отмена', onConfirm, onCancel }) {
|
||||
const ref = useRef(null)
|
||||
useEffect(() => {
|
||||
if (open && ref.current) {
|
||||
try { ref.current.querySelector('button[data-primary]')?.focus() } catch {}
|
||||
}
|
||||
}, [open])
|
||||
if (!open) return null
|
||||
return (
|
||||
<div className="modal show d-block" role="dialog" aria-modal="true" aria-labelledby="confirm-title" aria-describedby="confirm-message" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
|
||||
<div className="modal-dialog" role="document">
|
||||
<div className="modal-content" ref={ref}>
|
||||
<div className="modal-header">
|
||||
<h5 id="confirm-title" className="modal-title">{title || 'Подтверждение'}</h5>
|
||||
<button type="button" className="btn-close" aria-label="Close" onClick={onCancel}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<p id="confirm-message" className="m-0">{message}</p>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-secondary" onClick={onCancel}>{cancelText}</button>
|
||||
<button type="button" className="btn btn-primary" data-primary onClick={onConfirm}>{confirmText}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import api from '../lib/api.js';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNotify } from './NotifyProvider.jsx';
|
||||
import { IconHistory, IconRefresh, IconDeviceFloppy } from '@tabler/icons-react';
|
||||
|
||||
@@ -8,20 +9,18 @@ export default function HistoryModal({ resource, show, onClose, onRolledBack })
|
||||
const [items, setItems] = useState([]);
|
||||
const notify = useNotify();
|
||||
|
||||
const fetchHistory = async () => {
|
||||
if (!resource) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await api.get(`/history/${resource}`);
|
||||
setItems(Array.isArray(res.data?.items) ? res.data.items : []);
|
||||
} catch (e) {
|
||||
notify.error('Не удалось загрузить историю версий');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const { refetch } = useQuery({
|
||||
queryKey: ['history', resource],
|
||||
enabled: false,
|
||||
queryFn: async () => {
|
||||
const res = await api.get(`/history/${resource}`)
|
||||
const data = Array.isArray(res.data?.items) ? res.data.items : []
|
||||
setItems(data)
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(() => { if (show) fetchHistory(); }, [show, resource]);
|
||||
useEffect(() => { if (show) refetch().catch(() => notify.error('Не удалось загрузить историю версий')); }, [show, resource]);
|
||||
|
||||
const rollback = async (versionId) => {
|
||||
if (!versionId) return;
|
||||
@@ -54,7 +53,7 @@ export default function HistoryModal({ resource, show, onClose, onRolledBack })
|
||||
<div className="modal-body">
|
||||
<div className="d-flex justify-content-between align-items-center mb-2">
|
||||
<div className="text-muted small">Ресурс: <code>{resource}</code></div>
|
||||
<button className="btn btn-outline-secondary btn-sm" onClick={fetchHistory} disabled={loading}>
|
||||
<button className="btn btn-outline-secondary btn-sm" onClick={() => refetch()} disabled={loading}>
|
||||
<IconRefresh className={loading ? 'spin' : ''} />
|
||||
<span className="ms-1">Обновить</span>
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user