@open-mercato/scheduler 0.6.8-develop.7030.1.b84302d973 → 0.6.8-develop.7032.1.70d74d4bfe
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -44,6 +44,7 @@ function SchedulerPage() {
|
|
|
44
44
|
const [pageSize] = React.useState(20);
|
|
45
45
|
const [total, setTotal] = React.useState(0);
|
|
46
46
|
const [totalPages, setTotalPages] = React.useState(1);
|
|
47
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false);
|
|
47
48
|
const [search, setSearch] = React.useState("");
|
|
48
49
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
49
50
|
const scopeVersion = useOrganizationScopeVersion();
|
|
@@ -63,6 +64,7 @@ function SchedulerPage() {
|
|
|
63
64
|
setRows(mapped);
|
|
64
65
|
setTotal(result?.total ?? 0);
|
|
65
66
|
setTotalPages(result?.totalPages ?? 1);
|
|
67
|
+
setTotalIsCapped(result?.totalIsCapped === true);
|
|
66
68
|
} catch (error) {
|
|
67
69
|
flash(t("scheduler.error.fetch_failed", "Failed to load schedules"), "error");
|
|
68
70
|
setRows([]);
|
|
@@ -212,7 +214,7 @@ function SchedulerPage() {
|
|
|
212
214
|
createLabel: t("scheduler.action.create", "New Schedule")
|
|
213
215
|
}
|
|
214
216
|
),
|
|
215
|
-
pagination: { page, pageSize, total, totalPages, onPageChange: setPage },
|
|
217
|
+
pagination: { page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage },
|
|
216
218
|
isLoading,
|
|
217
219
|
searchValue: search,
|
|
218
220
|
onSearchChange: (value) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/scheduler/backend/config/scheduled-jobs/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'\n\ntype ScheduleRow = {\n id: string\n name: string\n description?: string | null\n scopeType: 'system' | 'organization' | 'tenant'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n targetType: 'queue' | 'command'\n targetQueue?: string | null\n targetCommand?: string | null\n isEnabled: boolean\n sourceType: 'user' | 'module'\n sourceModule?: string | null\n nextRunAt?: string | null\n lastRunAt?: string | null\n}\n\ntype SchedulesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n page?: number\n totalPages?: number\n}\n\nfunction mapApiItem(item: Record<string, unknown>): ScheduleRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n\n return {\n id,\n name: typeof item.name === 'string' ? item.name : '',\n description: typeof item.description === 'string' ? item.description : null,\n scopeType: (item.scopeType === 'system' || item.scopeType === 'organization' || item.scopeType === 'tenant')\n ? item.scopeType\n : 'tenant',\n scheduleType: (item.scheduleType === 'cron' || item.scheduleType === 'interval')\n ? item.scheduleType\n : 'cron',\n scheduleValue: typeof item.scheduleValue === 'string' ? item.scheduleValue : '',\n timezone: typeof item.timezone === 'string' ? item.timezone : 'UTC',\n targetType: (item.targetType === 'queue' || item.targetType === 'command')\n ? item.targetType\n : 'queue',\n targetQueue: typeof item.targetQueue === 'string' ? item.targetQueue : null,\n targetCommand: typeof item.targetCommand === 'string' ? item.targetCommand : null,\n isEnabled: item.isEnabled === true,\n sourceType: (item.sourceType === 'user' || item.sourceType === 'module')\n ? item.sourceType\n : 'user',\n sourceModule: typeof item.sourceModule === 'string' ? item.sourceModule : null,\n nextRunAt: typeof item.nextRunAt === 'string' ? item.nextRunAt : null,\n lastRunAt: typeof item.lastRunAt === 'string' ? item.lastRunAt : null,\n }\n}\n\n\nexport default function SchedulerPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const [rows, setRows] = React.useState<ScheduleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n\n const fetchSchedules = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n pageSize: pageSize.toString(),\n })\n if (search) params.set('search', search)\n\n const { result } = await apiCallOrThrow<SchedulesResponse>(\n `/api/scheduler/jobs?${params.toString()}`\n )\n\n const items = result?.items ?? []\n const mapped = items.map(mapApiItem).filter((x): x is ScheduleRow => x !== null)\n setRows(mapped)\n setTotal(result?.total ?? 0)\n setTotalPages(result?.totalPages ?? 1)\n } catch (error) {\n flash(t('scheduler.error.fetch_failed', 'Failed to load schedules'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [page, pageSize, search, scopeVersion, t])\n\n React.useEffect(() => {\n fetchSchedules()\n }, [fetchSchedules])\n\n const handleDelete = React.useCallback(\n async (row: ScheduleRow) => {\n const confirmed = await confirm({\n title: t('scheduler.confirm.delete', 'Are you sure you want to delete this schedule?'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n try {\n await apiCallOrThrow(`/api/scheduler/jobs`, {\n method: 'DELETE',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.deleted', 'Schedule deleted successfully'), 'success')\n fetchSchedules()\n } catch (error) {\n flash(t('scheduler.error.delete_failed', 'Failed to delete schedule'), 'error')\n }\n },\n [confirm, t, fetchSchedules]\n )\n\n const handleTrigger = React.useCallback(\n async (row: ScheduleRow) => {\n try {\n await apiCallOrThrow(`/api/scheduler/trigger`, {\n method: 'POST',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.triggered', 'Schedule triggered successfully'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('scheduler.error.trigger_failed', 'Failed to trigger schedule')\n flash(message, 'error')\n }\n },\n [t]\n )\n\n const columns = React.useMemo<ColumnDef<ScheduleRow>[]>(\n () => [\n {\n id: 'name',\n accessorKey: 'name',\n header: t('scheduler.field.name', 'Name'),\n cell: ({ row }) => (\n <span className=\"font-medium\">{row.original.name}</span>\n ),\n },\n {\n id: 'scheduleType',\n accessorKey: 'scheduleType',\n header: t('scheduler.field.schedule_type', 'Type'),\n cell: ({ row }) => (\n <span className=\"capitalize\">{row.original.scheduleType}</span>\n ),\n },\n {\n id: 'scheduleValue',\n accessorKey: 'scheduleValue',\n header: t('scheduler.field.schedule', 'Schedule'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {row.original.scheduleValue}\n </span>\n ),\n },\n {\n id: 'targetType',\n accessorKey: 'targetType',\n header: t('scheduler.field.target', 'Target'),\n cell: ({ row }) => {\n const target = row.original.targetType === 'queue'\n ? row.original.targetQueue\n : row.original.targetCommand\n return (\n <div className=\"flex flex-col\">\n <span className=\"text-xs text-muted-foreground capitalize\">{row.original.targetType}</span>\n <span className=\"text-sm\">{target || '-'}</span>\n </div>\n )\n },\n },\n {\n id: 'nextRunAt',\n accessorKey: 'nextRunAt',\n header: t('scheduler.field.next_run', 'Next Run'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateTime(row.original.nextRunAt) || '-'}\n </span>\n ),\n },\n {\n id: 'isEnabled',\n accessorKey: 'isEnabled',\n header: t('scheduler.field.active', 'Active'),\n cell: ({ row }) => <BooleanIcon value={row.original.isEnabled} />,\n },\n {\n id: 'sourceType',\n accessorKey: 'sourceType',\n header: t('scheduler.field.source', 'Source'),\n cell: ({ row }) => (\n <span className=\"text-xs capitalize\">\n {row.original.sourceType}\n {row.original.sourceModule && ` (${row.original.sourceModule})`}\n </span>\n ),\n },\n ],\n [t]\n )\n\n const rowActions = React.useCallback(\n (row: ScheduleRow): RowActionItem[] => [\n {\n id: 'view',\n label: t('scheduler.action.view', 'View Details'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}`),\n },\n {\n id: 'edit',\n label: t('scheduler.action.edit', 'Edit'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}/edit`),\n },\n {\n id: 'trigger',\n label: t('scheduler.action.trigger', 'Run Now'),\n onSelect: () => handleTrigger(row),\n },\n {\n id: 'delete',\n label: t('scheduler.action.delete', 'Delete'),\n onSelect: () => handleDelete(row),\n destructive: true,\n },\n ],\n [t, router, handleDelete, handleTrigger]\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<ScheduleRow>\n title={t('scheduler.title', 'Scheduled Jobs')}\n actions={\n <Button onClick={() => router.push('/backend/config/scheduled-jobs/new')}>\n {t('scheduler.action.create', 'New Schedule')}\n </Button>\n }\n columns={columns}\n data={rows}\n onRowClick={(row) => router.push(`/backend/config/scheduled-jobs/${row.id}`)}\n rowActions={(row) => <RowActions items={rowActions(row)} />}\n emptyState={(\n <ListEmptyState\n entityName={t('scheduler.title', 'Scheduled Jobs')}\n createHref=\"/backend/config/scheduled-jobs/new\"\n createLabel={t('scheduler.action.create', 'New Schedule')}\n />\n )}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('scheduler.search.placeholder', 'Search schedules...')}\n refreshButton={{\n label: t('scheduler.action.refresh', 'Refresh'),\n onRefresh: fetchSchedules,\n }}\n />\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'\n\ntype ScheduleRow = {\n id: string\n name: string\n description?: string | null\n scopeType: 'system' | 'organization' | 'tenant'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n targetType: 'queue' | 'command'\n targetQueue?: string | null\n targetCommand?: string | null\n isEnabled: boolean\n sourceType: 'user' | 'module'\n sourceModule?: string | null\n nextRunAt?: string | null\n lastRunAt?: string | null\n}\n\ntype SchedulesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n page?: number\n totalPages?: number\n totalIsCapped?: boolean\n}\n\nfunction mapApiItem(item: Record<string, unknown>): ScheduleRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n\n return {\n id,\n name: typeof item.name === 'string' ? item.name : '',\n description: typeof item.description === 'string' ? item.description : null,\n scopeType: (item.scopeType === 'system' || item.scopeType === 'organization' || item.scopeType === 'tenant')\n ? item.scopeType\n : 'tenant',\n scheduleType: (item.scheduleType === 'cron' || item.scheduleType === 'interval')\n ? item.scheduleType\n : 'cron',\n scheduleValue: typeof item.scheduleValue === 'string' ? item.scheduleValue : '',\n timezone: typeof item.timezone === 'string' ? item.timezone : 'UTC',\n targetType: (item.targetType === 'queue' || item.targetType === 'command')\n ? item.targetType\n : 'queue',\n targetQueue: typeof item.targetQueue === 'string' ? item.targetQueue : null,\n targetCommand: typeof item.targetCommand === 'string' ? item.targetCommand : null,\n isEnabled: item.isEnabled === true,\n sourceType: (item.sourceType === 'user' || item.sourceType === 'module')\n ? item.sourceType\n : 'user',\n sourceModule: typeof item.sourceModule === 'string' ? item.sourceModule : null,\n nextRunAt: typeof item.nextRunAt === 'string' ? item.nextRunAt : null,\n lastRunAt: typeof item.lastRunAt === 'string' ? item.lastRunAt : null,\n }\n}\n\n\nexport default function SchedulerPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const [rows, setRows] = React.useState<ScheduleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n\n const fetchSchedules = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n pageSize: pageSize.toString(),\n })\n if (search) params.set('search', search)\n\n const { result } = await apiCallOrThrow<SchedulesResponse>(\n `/api/scheduler/jobs?${params.toString()}`\n )\n\n const items = result?.items ?? []\n const mapped = items.map(mapApiItem).filter((x): x is ScheduleRow => x !== null)\n setRows(mapped)\n setTotal(result?.total ?? 0)\n setTotalPages(result?.totalPages ?? 1)\n setTotalIsCapped(result?.totalIsCapped === true)\n } catch (error) {\n flash(t('scheduler.error.fetch_failed', 'Failed to load schedules'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [page, pageSize, search, scopeVersion, t])\n\n React.useEffect(() => {\n fetchSchedules()\n }, [fetchSchedules])\n\n const handleDelete = React.useCallback(\n async (row: ScheduleRow) => {\n const confirmed = await confirm({\n title: t('scheduler.confirm.delete', 'Are you sure you want to delete this schedule?'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n try {\n await apiCallOrThrow(`/api/scheduler/jobs`, {\n method: 'DELETE',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.deleted', 'Schedule deleted successfully'), 'success')\n fetchSchedules()\n } catch (error) {\n flash(t('scheduler.error.delete_failed', 'Failed to delete schedule'), 'error')\n }\n },\n [confirm, t, fetchSchedules]\n )\n\n const handleTrigger = React.useCallback(\n async (row: ScheduleRow) => {\n try {\n await apiCallOrThrow(`/api/scheduler/trigger`, {\n method: 'POST',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.triggered', 'Schedule triggered successfully'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('scheduler.error.trigger_failed', 'Failed to trigger schedule')\n flash(message, 'error')\n }\n },\n [t]\n )\n\n const columns = React.useMemo<ColumnDef<ScheduleRow>[]>(\n () => [\n {\n id: 'name',\n accessorKey: 'name',\n header: t('scheduler.field.name', 'Name'),\n cell: ({ row }) => (\n <span className=\"font-medium\">{row.original.name}</span>\n ),\n },\n {\n id: 'scheduleType',\n accessorKey: 'scheduleType',\n header: t('scheduler.field.schedule_type', 'Type'),\n cell: ({ row }) => (\n <span className=\"capitalize\">{row.original.scheduleType}</span>\n ),\n },\n {\n id: 'scheduleValue',\n accessorKey: 'scheduleValue',\n header: t('scheduler.field.schedule', 'Schedule'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {row.original.scheduleValue}\n </span>\n ),\n },\n {\n id: 'targetType',\n accessorKey: 'targetType',\n header: t('scheduler.field.target', 'Target'),\n cell: ({ row }) => {\n const target = row.original.targetType === 'queue'\n ? row.original.targetQueue\n : row.original.targetCommand\n return (\n <div className=\"flex flex-col\">\n <span className=\"text-xs text-muted-foreground capitalize\">{row.original.targetType}</span>\n <span className=\"text-sm\">{target || '-'}</span>\n </div>\n )\n },\n },\n {\n id: 'nextRunAt',\n accessorKey: 'nextRunAt',\n header: t('scheduler.field.next_run', 'Next Run'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateTime(row.original.nextRunAt) || '-'}\n </span>\n ),\n },\n {\n id: 'isEnabled',\n accessorKey: 'isEnabled',\n header: t('scheduler.field.active', 'Active'),\n cell: ({ row }) => <BooleanIcon value={row.original.isEnabled} />,\n },\n {\n id: 'sourceType',\n accessorKey: 'sourceType',\n header: t('scheduler.field.source', 'Source'),\n cell: ({ row }) => (\n <span className=\"text-xs capitalize\">\n {row.original.sourceType}\n {row.original.sourceModule && ` (${row.original.sourceModule})`}\n </span>\n ),\n },\n ],\n [t]\n )\n\n const rowActions = React.useCallback(\n (row: ScheduleRow): RowActionItem[] => [\n {\n id: 'view',\n label: t('scheduler.action.view', 'View Details'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}`),\n },\n {\n id: 'edit',\n label: t('scheduler.action.edit', 'Edit'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}/edit`),\n },\n {\n id: 'trigger',\n label: t('scheduler.action.trigger', 'Run Now'),\n onSelect: () => handleTrigger(row),\n },\n {\n id: 'delete',\n label: t('scheduler.action.delete', 'Delete'),\n onSelect: () => handleDelete(row),\n destructive: true,\n },\n ],\n [t, router, handleDelete, handleTrigger]\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<ScheduleRow>\n title={t('scheduler.title', 'Scheduled Jobs')}\n actions={\n <Button onClick={() => router.push('/backend/config/scheduled-jobs/new')}>\n {t('scheduler.action.create', 'New Schedule')}\n </Button>\n }\n columns={columns}\n data={rows}\n onRowClick={(row) => router.push(`/backend/config/scheduled-jobs/${row.id}`)}\n rowActions={(row) => <RowActions items={rowActions(row)} />}\n emptyState={(\n <ListEmptyState\n entityName={t('scheduler.title', 'Scheduled Jobs')}\n createHref=\"/backend/config/scheduled-jobs/new\"\n createLabel={t('scheduler.action.create', 'New Schedule')}\n />\n )}\n pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('scheduler.search.placeholder', 'Search schedules...')}\n refreshButton={{\n label: t('scheduler.action.refresh', 'Refresh'),\n onRefresh: fetchSchedules,\n }}\n />\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/scheduler",
|
|
3
|
-
"version": "0.6.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Database-managed scheduled jobs with admin UI",
|
|
6
6
|
"type": "module",
|
|
@@ -59,13 +59,13 @@
|
|
|
59
59
|
"./*/*/*/*/*/*.json": "./src/*/*/*/*/*/*.json"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@open-mercato/events": "0.6.8-develop.
|
|
63
|
-
"@open-mercato/queue": "0.6.8-develop.
|
|
62
|
+
"@open-mercato/events": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
63
|
+
"@open-mercato/queue": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
64
64
|
"cron-parser": "^5.6.2"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@mikro-orm/core": "^7.0.14",
|
|
68
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
68
|
+
"@open-mercato/shared": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
69
69
|
"bullmq": "^5.0.0 || ^6.0.0",
|
|
70
70
|
"ioredis": "^5.0.0 || ^6.0.0",
|
|
71
71
|
"zod": ">=3.23.0"
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
82
|
+
"@open-mercato/shared": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
83
83
|
"@types/jest": "^30.0.0",
|
|
84
84
|
"@types/node": "^26.1.2",
|
|
85
85
|
"jest": "^30.4.2",
|
|
@@ -39,6 +39,7 @@ type SchedulesResponse = {
|
|
|
39
39
|
total?: number
|
|
40
40
|
page?: number
|
|
41
41
|
totalPages?: number
|
|
42
|
+
totalIsCapped?: boolean
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function mapApiItem(item: Record<string, unknown>): ScheduleRow | null {
|
|
@@ -82,6 +83,7 @@ export default function SchedulerPage() {
|
|
|
82
83
|
const [pageSize] = React.useState(20)
|
|
83
84
|
const [total, setTotal] = React.useState(0)
|
|
84
85
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
86
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
85
87
|
const [search, setSearch] = React.useState('')
|
|
86
88
|
const [isLoading, setIsLoading] = React.useState(false)
|
|
87
89
|
const scopeVersion = useOrganizationScopeVersion()
|
|
@@ -104,6 +106,7 @@ export default function SchedulerPage() {
|
|
|
104
106
|
setRows(mapped)
|
|
105
107
|
setTotal(result?.total ?? 0)
|
|
106
108
|
setTotalPages(result?.totalPages ?? 1)
|
|
109
|
+
setTotalIsCapped(result?.totalIsCapped === true)
|
|
107
110
|
} catch (error) {
|
|
108
111
|
flash(t('scheduler.error.fetch_failed', 'Failed to load schedules'), 'error')
|
|
109
112
|
setRows([])
|
|
@@ -282,7 +285,7 @@ export default function SchedulerPage() {
|
|
|
282
285
|
createLabel={t('scheduler.action.create', 'New Schedule')}
|
|
283
286
|
/>
|
|
284
287
|
)}
|
|
285
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
288
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
286
289
|
isLoading={isLoading}
|
|
287
290
|
searchValue={search}
|
|
288
291
|
onSearchChange={(value) => { setSearch(value); setPage(1) }}
|