diff --git a/frontend/src/routes/(loggedin)/app/crons/+page.svelte b/frontend/src/routes/(loggedin)/app/crons/+page.svelte
index 2290970..207ea8c 100644
--- a/frontend/src/routes/(loggedin)/app/crons/+page.svelte
+++ b/frontend/src/routes/(loggedin)/app/crons/+page.svelte
@@ -10,7 +10,7 @@
DtSrAutoRefresh
} from '$lib/components/datatables/server';
- const handler = new DataHandler([], { rowsPerPage: 1000, totalRows: 0 });
+ const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 });
let rows = handler.getRows();
/** @type {string | number} */
@@ -73,8 +73,8 @@
}}
>
-
-
+
+
@@ -89,8 +89,8 @@
}}
>
-
-
+
+
|
diff --git a/frontend/src/routes/(loggedin)/app/crons/api-handler.js b/frontend/src/routes/(loggedin)/app/crons/api-handler.js
index 3f095df..f8dc121 100644
--- a/frontend/src/routes/(loggedin)/app/crons/api-handler.js
+++ b/frontend/src/routes/(loggedin)/app/crons/api-handler.js
@@ -1,18 +1,23 @@
import { apiUri } from '$lib/utils/common';
+import { goto } from '$app/navigation';
/** @param {import('@vincjo/datatables/remote/state')} state */
export const loadData = async (state) => {
const response = await fetch(apiUri(`/api/v1/crons?${getParams(state)}`));
const json = await response.json();
+ if (json.data === null) {
+ goto('/login');
+ return;
+ }
state.setTotalRows(json.data.length ?? 0);
- return json.data ?? [];
+ return json.data.items ?? [];
};
const getParams = ({ pageNumber, rowsPerPage, sort, filters }) => {
let params = `page=${pageNumber}&limit=${rowsPerPage}`;
if (sort) {
- params += `&orderBy=${sort.orderBy}&orderDir=${sort.direction}`;
+ params += `&sort_by=${sort.orderBy}&sort_direction=${sort.direction}`;
}
if (filters) {
params += filters.map(({ filterBy, value }) => `&${filterBy}=${value}`).join('');
diff --git a/handler/response.go b/handler/response.go
index 4b572c2..77ed8a3 100644
--- a/handler/response.go
+++ b/handler/response.go
@@ -355,8 +355,18 @@ func ProcessJob(c *fiber.Ctx) error {
func Crons(c *fiber.Ctx) error {
cronRepo := repo.NewCron(database.GetDB())
+ query := repo.CronQueryParams{
+ RowsPerPage: c.QueryInt("limit", 10),
+ Page: c.QueryInt("page", 1),
+ SortBy: c.Query("sort_by", "id"),
+ SortDirection: c.Query("sort_direction", "desc"),
+ Title: c.Query("title"),
+ Description: c.Query("description"),
+ IsEnabled: c.QueryInt("is_enabled", -1),
+ CronState: c.QueryInt("cron_state", -1),
+ }
- crons, err := cronRepo.Crons()
+ crons, err := cronRepo.Crons(query)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"status": "error",
@@ -367,7 +377,7 @@ func Crons(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": "ok",
- "message": "Crons",
+ "message": "Success",
"data": crons,
})
}
diff --git a/handler/routes.go b/handler/routes.go
index 1dff19f..052210d 100644
--- a/handler/routes.go
+++ b/handler/routes.go
@@ -16,6 +16,7 @@ func V1Api(app *fiber.App) {
v1.Post("/prober", CookieProtected, Prober)
v1.Patch("/prober/:id", CookieProtected, Prober)
v1.Delete("/prober/:id", CookieProtected, Prober)
+ v1.Get("/crons", CookieProtected, Crons)
v1.Get("/nodes", MoneroNodes)
v1.Post("/nodes", AddNode)
v1.Get("/nodes/id/:id", MoneroNode)
@@ -24,5 +25,4 @@ func V1Api(app *fiber.App) {
v1.Get("/countries", Countries)
v1.Get("/job", CheckProber, GiveJob)
v1.Post("/job", CheckProber, ProcessJob)
- v1.Get("/crons", Crons)
}
diff --git a/internal/repo/cron.go b/internal/repo/cron.go
index aec1f57..30798e7 100644
--- a/internal/repo/cron.go
+++ b/internal/repo/cron.go
@@ -3,6 +3,8 @@ package repo
import (
"fmt"
"math"
+ "slices"
+ "strings"
"time"
"github.com/ditatompel/xmr-nodes/internal/database"
@@ -10,14 +12,14 @@ import (
type CronRepository interface {
RunCronProcess()
- Crons() ([]CronTask, error)
+ Crons(q CronQueryParams) (CronTasks, error)
}
type CronRepo struct {
db *database.DB
}
-type CronTask struct {
+type Cron struct {
Id int `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Slug string `json:"slug" db:"slug"`
@@ -68,15 +70,77 @@ func (repo *CronRepo) RunCronProcess() {
}
}
-func (repo *CronRepo) Crons() ([]CronTask, error) {
- tasks := []CronTask{}
- query := `SELECT * FROM tbl_cron`
- err := repo.db.Select(&tasks, query)
- return tasks, err
+type CronQueryParams struct {
+ Title string
+ Description string
+ IsEnabled int
+ CronState int
+ RowsPerPage int
+ Page int
+ SortBy string
+ SortDirection string
}
-func (repo *CronRepo) queueList() ([]CronTask, error) {
- tasks := []CronTask{}
+type CronTasks struct {
+ TotalRows int `json:"total_rows"`
+ RowsPerPage int `json:"rows_per_page"`
+ Items []*Cron `json:"items"`
+}
+
+func (repo *CronRepo) Crons(q CronQueryParams) (CronTasks, error) {
+ queryParams := []interface{}{}
+ whereQueries := []string{}
+ where := ""
+
+ if q.Title != "" {
+ whereQueries = append(whereQueries, "title LIKE ?")
+ queryParams = append(queryParams, "%"+q.Title+"%")
+ }
+ if q.Description != "" {
+ whereQueries = append(whereQueries, "description LIKE ?")
+ queryParams = append(queryParams, "%"+q.Description+"%")
+ }
+ if q.IsEnabled != -1 {
+ whereQueries = append(whereQueries, "is_enabled = ?")
+ queryParams = append(queryParams, q.IsEnabled)
+ }
+ if q.CronState != -1 {
+ whereQueries = append(whereQueries, "cron_state = ?")
+ queryParams = append(queryParams, q.CronState)
+ }
+ if len(whereQueries) > 0 {
+ where = "WHERE " + strings.Join(whereQueries, " AND ")
+ }
+ tasks := CronTasks{}
+
+ queryTotalRows := fmt.Sprintf("SELECT COUNT(id) FROM tbl_cron %s", where)
+ err := repo.db.QueryRow(queryTotalRows, queryParams...).Scan(&tasks.TotalRows)
+ if err != nil {
+ return tasks, err
+ }
+ queryParams = append(queryParams, q.RowsPerPage, (q.Page-1)*q.RowsPerPage)
+ allowedSort := []string{"id", "run_every", "last_run", "next_run", "run_time"}
+ sortBy := "id"
+ if slices.Contains(allowedSort, q.SortBy) {
+ sortBy = q.SortBy
+ }
+ sortDirection := "DESC"
+ if q.SortDirection == "asc" {
+ sortDirection = "ASC"
+ }
+
+ query := fmt.Sprintf("SELECT id, title, slug, description, run_every, last_run, next_run, run_time, cron_state, is_enabled FROM tbl_cron %s ORDER BY %s %s LIMIT ? OFFSET ?", where, sortBy, sortDirection)
+ err = repo.db.Select(&tasks.Items, query, queryParams...)
+ if err != nil {
+ return tasks, err
+ }
+ tasks.RowsPerPage = q.RowsPerPage
+
+ return tasks, nil
+}
+
+func (repo *CronRepo) queueList() ([]Cron, error) {
+ tasks := []Cron{}
query := `SELECT id, run_every, last_run, slug, next_run, cron_state FROM tbl_cron
WHERE is_enabled = ? AND next_run <= ?`
err := repo.db.Select(&tasks, query, 1, time.Now().Unix())