Implement pagination for modification history retrieval and update frontend to support paginated data

This commit is contained in:
Dominik Schröter 2025-01-27 13:24:30 +01:00
parent 32cc3d2794
commit 969bacc137
3 changed files with 116 additions and 22 deletions

View file

@ -248,13 +248,34 @@ func (app *App) getDocumentHandler() gin.HandlerFunc {
// Section for local-db actions
func (app *App) getModificationHistoryHandler(c *gin.Context) {
modifications, err := GetAllModifications(app.Database)
// Parse pagination parameters
page := 1
pageSize := 20
if p, err := strconv.Atoi(c.DefaultQuery("page", "1")); err == nil && p > 0 {
page = p
}
if ps, err := strconv.Atoi(c.DefaultQuery("pageSize", "20")); err == nil && ps > 0 && ps <= 100 {
pageSize = ps
}
// Get paginated modifications and total count
modifications, total, err := GetPaginatedModifications(app.Database, page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve modification history"})
log.Errorf("Failed to retrieve modification history: %v", err)
return
}
c.JSON(http.StatusOK, modifications)
totalPages := (int(total) + pageSize - 1) / pageSize
c.JSON(http.StatusOK, gin.H{
"items": modifications,
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"pageSize": pageSize,
})
}
func (app *App) undoModificationHandler(c *gin.Context) {

View file

@ -63,13 +63,35 @@ func GetModification(db *gorm.DB, id uint) (*ModificationHistory, error) {
return &record, result.Error
}
// GetAllModifications retrieves all modification records from the database
// GetAllModifications retrieves all modification records from the database (deprecated - use GetPaginatedModifications instead)
func GetAllModifications(db *gorm.DB) ([]ModificationHistory, error) {
var records []ModificationHistory
result := db.Order("date_changed DESC").Find(&records) // GORM's Find method retrieves all records
result := db.Order("date_changed DESC").Find(&records)
return records, result.Error
}
// GetPaginatedModifications retrieves a page of modification records with total count
func GetPaginatedModifications(db *gorm.DB, page int, pageSize int) ([]ModificationHistory, int64, error) {
var records []ModificationHistory
var total int64
// Get total count
if err := db.Model(&ModificationHistory{}).Count(&total).Error; err != nil {
return nil, 0, err
}
// Calculate offset
offset := (page - 1) * pageSize
// Get paginated records
result := db.Order("date_changed DESC").
Offset(offset).
Limit(pageSize).
Find(&records)
return records, total, result.Error
}
// UndoModification marks a modification record as undone and sets the undo date
func SetModificationUndone(db *gorm.DB, record *ModificationHistory) error {
record.Undone = true

View file

@ -12,11 +12,23 @@ interface ModificationHistory {
UndoneDate: string | null;
}
interface PaginatedResponse {
items: ModificationHistory[];
totalItems: number;
totalPages: number;
currentPage: number;
pageSize: number;
}
const History: React.FC = () => {
const [modifications, setModifications] = useState<ModificationHistory[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [paperlessUrl, setPaperlessUrl] = useState<string>('');
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [totalItems, setTotalItems] = useState(0);
const pageSize = 20;
// Get Paperless URL
useEffect(() => {
@ -36,19 +48,22 @@ const History: React.FC = () => {
fetchUrl();
}, []);
// Get all modifications
// Get modifications with pagination
useEffect(() => {
fetchModifications();
}, []);
fetchModifications(currentPage);
}, [currentPage]);
const fetchModifications = async () => {
const fetchModifications = async (page: number) => {
setLoading(true);
try {
const response = await fetch('/api/modifications');
const response = await fetch(`/api/modifications?page=${page}&pageSize=${pageSize}`);
if (!response.ok) {
throw new Error('Failed to fetch modifications');
}
const data = await response.json();
setModifications(data);
const data: PaginatedResponse = await response.json();
setModifications(data.items);
setTotalPages(data.totalPages);
setTotalItems(data.totalItems);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error occurred');
} finally {
@ -108,7 +123,8 @@ const History: React.FC = () => {
No modifications found
</p>
) : (
<div className="grid gap-4 md:grid-cols-1 lg:grid-cols-1">
<>
<div className="grid gap-4 md:grid-cols-1 lg:grid-cols-1 mb-6">
{modifications.map((modification) => (
<UndoCard
key={modification.ID}
@ -118,6 +134,41 @@ const History: React.FC = () => {
/>
))}
</div>
<div className="flex items-center justify-between border-t border-gray-200 dark:border-gray-700 pt-4">
<div className="flex items-center text-sm text-gray-500 dark:text-gray-400">
<span>
Showing {((currentPage - 1) * pageSize) + 1} to {Math.min(currentPage * pageSize, totalItems)} of {totalItems} results
</span>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => setCurrentPage(page => Math.max(1, page - 1))}
disabled={currentPage === 1}
className={`px-3 py-1 rounded-md ${
currentPage === 1
? 'bg-gray-100 text-gray-400 cursor-not-allowed dark:bg-gray-800'
: 'bg-blue-500 text-white hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700'
}`}
>
Previous
</button>
<span className="text-sm text-gray-600 dark:text-gray-300">
Page {currentPage} of {totalPages}
</span>
<button
onClick={() => setCurrentPage(page => Math.min(totalPages, page + 1))}
disabled={currentPage === totalPages}
className={`px-3 py-1 rounded-md ${
currentPage === totalPages
? 'bg-gray-100 text-gray-400 cursor-not-allowed dark:bg-gray-800'
: 'bg-blue-500 text-white hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700'
}`}
>
Next
</button>
</div>
</div>
</>
)}
</div>
);