@open-mercato/scheduler 0.4.6-develop-e321a4e2a1 → 0.4.6-main-24e64eef39

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.
@@ -21,8 +21,8 @@ async function GET(req) {
21
21
  }
22
22
  }
23
23
  }
24
- const queues = Array.from(queueSet).sort((a, b) => a.localeCompare(b)).map((queue) => ({ value: queue, label: queue }));
25
- const commands = commandRegistry.list().sort((a, b) => a.localeCompare(b)).map((id) => ({ value: id, label: id }));
24
+ const queues = Array.from(queueSet).sort().map((queue) => ({ value: queue, label: queue }));
25
+ const commands = commandRegistry.list().sort().map((id) => ({ value: id, label: id }));
26
26
  return NextResponse.json({ queues, commands });
27
27
  }
28
28
  const targetOptionSchema = z.object({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/scheduler/api/targets/route.ts"],
4
- "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { getModules } from '@open-mercato/shared/lib/modules/registry'\nimport { commandRegistry } from '@open-mercato/shared/lib/commands'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['scheduler.jobs.view'],\n}\n\n/**\n * GET /api/scheduler/targets\n * Returns available queue names and command IDs for schedule target selection.\n */\nexport async function GET(req: NextRequest) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const modules = getModules()\n\n const queueSet = new Set<string>()\n for (const mod of modules) {\n if (mod.workers) {\n for (const worker of mod.workers) {\n queueSet.add(worker.queue)\n }\n }\n }\n\n const queues = Array.from(queueSet)\n .sort((a, b) => a.localeCompare(b))\n .map((queue) => ({ value: queue, label: queue }))\n\n const commands = commandRegistry\n .list()\n .sort((a, b) => a.localeCompare(b))\n .map((id) => ({ value: id, label: id }))\n\n return NextResponse.json({ queues, commands })\n}\n\n// Response schemas\nconst targetOptionSchema = z.object({\n value: z.string(),\n label: z.string(),\n})\n\nconst targetsResponseSchema = z.object({\n queues: z.array(targetOptionSchema),\n commands: z.array(targetOptionSchema),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Scheduler',\n summary: 'List available schedule targets',\n description: 'Returns available queue names and registered command IDs for schedule target selection.',\n methods: {\n GET: {\n operationId: 'listScheduleTargets',\n summary: 'List available queues and commands',\n description: 'Returns all registered queue names (from module workers) and command IDs (from the command registry) that can be used as schedule targets.',\n responses: [\n {\n status: 200,\n description: 'Available targets',\n schema: targetsResponseSchema,\n },\n ],\n errors: [\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "AAAA,SAAsB,oBAAoB;AAC1C,SAAS,SAAS;AAClB,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAGzB,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,qBAAqB;AACzC;AAMA,eAAsB,IAAI,KAAkB;AAC1C,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM;AACT,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,UAAU,WAAW;AAE3B,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,OAAO,SAAS;AACzB,QAAI,IAAI,SAAS;AACf,iBAAW,UAAU,IAAI,SAAS;AAChC,iBAAS,IAAI,OAAO,KAAK;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,KAAK,QAAQ,EAC/B,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC,EACjC,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,OAAO,MAAM,EAAE;AAElD,QAAM,WAAW,gBACd,KAAK,EACL,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC,EACjC,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;AAEzC,SAAO,aAAa,KAAK,EAAE,QAAQ,SAAS,CAAC;AAC/C;AAGA,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,OAAO,EAAE,OAAO;AAAA,EAChB,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,QAAQ,EAAE,MAAM,kBAAkB;AAAA,EAClC,UAAU,EAAE,MAAM,kBAAkB;AACtC,CAAC;AAED,MAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,OAAO,EAAE,OAAO;AAClB,CAAC;AAEM,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,IACP,KAAK;AAAA,MACH,aAAa;AAAA,MACb,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,oBAAoB;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { getModules } from '@open-mercato/shared/lib/modules/registry'\nimport { commandRegistry } from '@open-mercato/shared/lib/commands'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['scheduler.jobs.view'],\n}\n\n/**\n * GET /api/scheduler/targets\n * Returns available queue names and command IDs for schedule target selection.\n */\nexport async function GET(req: NextRequest) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const modules = getModules()\n\n const queueSet = new Set<string>()\n for (const mod of modules) {\n if (mod.workers) {\n for (const worker of mod.workers) {\n queueSet.add(worker.queue)\n }\n }\n }\n\n const queues = Array.from(queueSet)\n .sort()\n .map((queue) => ({ value: queue, label: queue }))\n\n const commands = commandRegistry\n .list()\n .sort()\n .map((id) => ({ value: id, label: id }))\n\n return NextResponse.json({ queues, commands })\n}\n\n// Response schemas\nconst targetOptionSchema = z.object({\n value: z.string(),\n label: z.string(),\n})\n\nconst targetsResponseSchema = z.object({\n queues: z.array(targetOptionSchema),\n commands: z.array(targetOptionSchema),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Scheduler',\n summary: 'List available schedule targets',\n description: 'Returns available queue names and registered command IDs for schedule target selection.',\n methods: {\n GET: {\n operationId: 'listScheduleTargets',\n summary: 'List available queues and commands',\n description: 'Returns all registered queue names (from module workers) and command IDs (from the command registry) that can be used as schedule targets.',\n responses: [\n {\n status: 200,\n description: 'Available targets',\n schema: targetsResponseSchema,\n },\n ],\n errors: [\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAsB,oBAAoB;AAC1C,SAAS,SAAS;AAClB,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAGzB,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,qBAAqB;AACzC;AAMA,eAAsB,IAAI,KAAkB;AAC1C,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM;AACT,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,UAAU,WAAW;AAE3B,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,OAAO,SAAS;AACzB,QAAI,IAAI,SAAS;AACf,iBAAW,UAAU,IAAI,SAAS;AAChC,iBAAS,IAAI,OAAO,KAAK;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,KAAK,QAAQ,EAC/B,KAAK,EACL,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,OAAO,MAAM,EAAE;AAElD,QAAM,WAAW,gBACd,KAAK,EACL,KAAK,EACL,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;AAEzC,SAAO,aAAa,KAAK,EAAE,QAAQ,SAAS,CAAC;AAC/C;AAGA,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,OAAO,EAAE,OAAO;AAAA,EAChB,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,QAAQ,EAAE,MAAM,kBAAkB;AAAA,EAClC,UAAU,EAAE,MAAM,kBAAkB;AACtC,CAAC;AAED,MAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,OAAO,EAAE,OAAO;AAClB,CAAC;AAEM,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,IACP,KAAK;AAAA,MACH,aAAa;AAAA,MACb,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,oBAAoB;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -77,14 +77,6 @@ function ExecutionDetailsDialog({
77
77
  className: "mt-1 text-xs font-mono truncate cursor-pointer hover:text-primary transition-colors",
78
78
  title: run.queueJobId,
79
79
  onClick: () => navigator.clipboard.writeText(run.queueJobId),
80
- onKeyDown: (e) => {
81
- if (e.key === "Enter" || e.key === " ") {
82
- e.preventDefault();
83
- navigator.clipboard.writeText(run.queueJobId);
84
- }
85
- },
86
- role: "button",
87
- tabIndex: 0,
88
80
  children: run.queueJobId
89
81
  }
90
82
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/scheduler/components/ExecutionDetailsDialog.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { formatDistanceToNow } from 'date-fns'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype ExecutionRun = {\n id: string\n startedAt: string\n finishedAt?: string\n status: 'running' | 'completed' | 'failed' | 'skipped'\n triggerType: 'scheduled' | 'manual'\n queueJobId?: string\n queueName?: string\n errorMessage?: string\n errorStack?: string\n durationMs?: number\n}\n\ntype ExecutionDetailsDialogProps = {\n open: boolean\n onClose: () => void\n run: ExecutionRun | null\n scheduleName: string\n}\n\nexport function ExecutionDetailsDialog({\n open,\n onClose,\n run,\n scheduleName,\n}: ExecutionDetailsDialogProps) {\n const t = useT()\n\n const getStatusBadgeVariant = (status: string): 'destructive' | 'secondary' | 'default' | 'outline' => {\n switch (status) {\n case 'completed':\n return 'default'\n case 'failed':\n return 'destructive'\n case 'running':\n return 'outline'\n case 'skipped':\n return 'secondary'\n default:\n return 'secondary'\n }\n }\n\n const formatDuration = (durationMs?: number) => {\n if (!durationMs) return t('scheduler.execution.na', 'N/A')\n return `${(durationMs / 1000).toFixed(2)}s`\n }\n\n if (!run) return null\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"max-w-2xl max-h-[80vh] overflow-auto\">\n <DialogHeader>\n <DialogTitle>\n {t('scheduler.execution.details_title', 'Execution Details')}: {scheduleName}\n </DialogTitle>\n <p className=\"text-sm text-muted-foreground\">\n {t('scheduler.execution.run_id', 'Run ID')}: {run.id}\n </p>\n </DialogHeader>\n\n <div className=\"space-y-6\">\n {/* Overview Section */}\n <div className=\"grid grid-cols-2 gap-4 overflow-hidden\">\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.status', 'Status')}</Label>\n <div className=\"mt-1\">\n <Badge variant={getStatusBadgeVariant(run.status)}>\n {t(`scheduler.execution_status.${run.status}`, run.status)}\n </Badge>\n </div>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.trigger_type', 'Trigger Type')}</Label>\n <p className=\"mt-1 text-sm\">{t(`scheduler.trigger_type.${run.triggerType}`, run.triggerType)}</p>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.started_at', 'Started At')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(run.startedAt).toLocaleString()}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatDistanceToNow(new Date(run.startedAt), { addSuffix: true })}\n </p>\n </div>\n\n {run.finishedAt && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.finished_at', 'Finished At')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(run.finishedAt).toLocaleString()}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatDistanceToNow(new Date(run.finishedAt), { addSuffix: true })}\n </p>\n </div>\n )}\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.duration', 'Duration')}</Label>\n <p className=\"mt-1 text-sm\">{formatDuration(run.durationMs)}</p>\n </div>\n\n {run.queueJobId && (\n <div className=\"min-w-0 overflow-hidden\">\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.queue_job_id', 'Queue Job ID')}</Label>\n <p\n className=\"mt-1 text-xs font-mono truncate cursor-pointer hover:text-primary transition-colors\"\n title={run.queueJobId}\n onClick={() => navigator.clipboard.writeText(run.queueJobId!)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n navigator.clipboard.writeText(run.queueJobId!)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {run.queueJobId}\n </p>\n </div>\n )}\n\n {run.queueName && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.queue_name', 'Queue Name')}</Label>\n <p className=\"mt-1 text-sm\">{run.queueName}</p>\n </div>\n )}\n </div>\n\n {/* Error Message Section */}\n {run.status === 'failed' && run.errorMessage && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.error_message', 'Error Message')}</Label>\n <Alert variant=\"destructive\" className=\"mt-2\">\n <AlertDescription>\n <div className=\"flex items-start gap-2\">\n <span className=\"text-lg\">\u26A0\uFE0F</span>\n <div className=\"flex-1\">\n <pre className=\"whitespace-pre-wrap text-sm font-mono\">\n {run.errorMessage}\n </pre>\n </div>\n </div>\n </AlertDescription>\n </Alert>\n </div>\n )}\n\n {/* Stack Trace Section */}\n {run.status === 'failed' && run.errorStack && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.stack_trace', 'Stack Trace')}</Label>\n <pre className=\"mt-2 bg-muted p-3 rounded text-xs overflow-auto max-h-64 font-mono\">\n {run.errorStack}\n </pre>\n </div>\n )}\n\n {/* Info Message for Successful Runs */}\n {run.status === 'completed' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u2713</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.completed_message', 'This execution completed successfully without errors.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Info Message for Running */}\n {run.status === 'running' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u23F3</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.running_message', 'This execution is currently in progress.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Info Message for Skipped */}\n {run.status === 'skipped' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u2298</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.skipped_message', 'This execution was skipped.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { formatDistanceToNow } from 'date-fns'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype ExecutionRun = {\n id: string\n startedAt: string\n finishedAt?: string\n status: 'running' | 'completed' | 'failed' | 'skipped'\n triggerType: 'scheduled' | 'manual'\n queueJobId?: string\n queueName?: string\n errorMessage?: string\n errorStack?: string\n durationMs?: number\n}\n\ntype ExecutionDetailsDialogProps = {\n open: boolean\n onClose: () => void\n run: ExecutionRun | null\n scheduleName: string\n}\n\nexport function ExecutionDetailsDialog({\n open,\n onClose,\n run,\n scheduleName,\n}: ExecutionDetailsDialogProps) {\n const t = useT()\n\n const getStatusBadgeVariant = (status: string): 'destructive' | 'secondary' | 'default' | 'outline' => {\n switch (status) {\n case 'completed':\n return 'default'\n case 'failed':\n return 'destructive'\n case 'running':\n return 'outline'\n case 'skipped':\n return 'secondary'\n default:\n return 'secondary'\n }\n }\n\n const formatDuration = (durationMs?: number) => {\n if (!durationMs) return t('scheduler.execution.na', 'N/A')\n return `${(durationMs / 1000).toFixed(2)}s`\n }\n\n if (!run) return null\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"max-w-2xl max-h-[80vh] overflow-auto\">\n <DialogHeader>\n <DialogTitle>\n {t('scheduler.execution.details_title', 'Execution Details')}: {scheduleName}\n </DialogTitle>\n <p className=\"text-sm text-muted-foreground\">\n {t('scheduler.execution.run_id', 'Run ID')}: {run.id}\n </p>\n </DialogHeader>\n\n <div className=\"space-y-6\">\n {/* Overview Section */}\n <div className=\"grid grid-cols-2 gap-4 overflow-hidden\">\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.status', 'Status')}</Label>\n <div className=\"mt-1\">\n <Badge variant={getStatusBadgeVariant(run.status)}>\n {t(`scheduler.execution_status.${run.status}`, run.status)}\n </Badge>\n </div>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.trigger_type', 'Trigger Type')}</Label>\n <p className=\"mt-1 text-sm\">{t(`scheduler.trigger_type.${run.triggerType}`, run.triggerType)}</p>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.started_at', 'Started At')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(run.startedAt).toLocaleString()}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatDistanceToNow(new Date(run.startedAt), { addSuffix: true })}\n </p>\n </div>\n\n {run.finishedAt && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.finished_at', 'Finished At')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(run.finishedAt).toLocaleString()}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {formatDistanceToNow(new Date(run.finishedAt), { addSuffix: true })}\n </p>\n </div>\n )}\n\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.duration', 'Duration')}</Label>\n <p className=\"mt-1 text-sm\">{formatDuration(run.durationMs)}</p>\n </div>\n\n {run.queueJobId && (\n <div className=\"min-w-0 overflow-hidden\">\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.queue_job_id', 'Queue Job ID')}</Label>\n <p \n className=\"mt-1 text-xs font-mono truncate cursor-pointer hover:text-primary transition-colors\" \n title={run.queueJobId}\n onClick={() => navigator.clipboard.writeText(run.queueJobId!)}\n >\n {run.queueJobId}\n </p>\n </div>\n )}\n\n {run.queueName && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.queue_name', 'Queue Name')}</Label>\n <p className=\"mt-1 text-sm\">{run.queueName}</p>\n </div>\n )}\n </div>\n\n {/* Error Message Section */}\n {run.status === 'failed' && run.errorMessage && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.error_message', 'Error Message')}</Label>\n <Alert variant=\"destructive\" className=\"mt-2\">\n <AlertDescription>\n <div className=\"flex items-start gap-2\">\n <span className=\"text-lg\">\u26A0\uFE0F</span>\n <div className=\"flex-1\">\n <pre className=\"whitespace-pre-wrap text-sm font-mono\">\n {run.errorMessage}\n </pre>\n </div>\n </div>\n </AlertDescription>\n </Alert>\n </div>\n )}\n\n {/* Stack Trace Section */}\n {run.status === 'failed' && run.errorStack && (\n <div>\n <Label className=\"text-sm font-medium text-muted-foreground\">{t('scheduler.execution.stack_trace', 'Stack Trace')}</Label>\n <pre className=\"mt-2 bg-muted p-3 rounded text-xs overflow-auto max-h-64 font-mono\">\n {run.errorStack}\n </pre>\n </div>\n )}\n\n {/* Info Message for Successful Runs */}\n {run.status === 'completed' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u2713</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.completed_message', 'This execution completed successfully without errors.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Info Message for Running */}\n {run.status === 'running' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u23F3</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.running_message', 'This execution is currently in progress.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n\n {/* Info Message for Skipped */}\n {run.status === 'skipped' && (\n <Alert>\n <AlertDescription>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-lg\">\u2298</span>\n <span className=\"text-sm\">\n {t('scheduler.execution.skipped_message', 'This execution was skipped.')}\n </span>\n </div>\n </AlertDescription>\n </Alert>\n )}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -73,14 +73,6 @@ function JobLogsModal({
73
73
  className: "text-sm text-muted-foreground font-mono truncate cursor-pointer hover:text-primary transition-colors",
74
74
  title: queueJobId ?? void 0,
75
75
  onClick: () => queueJobId && navigator.clipboard.writeText(queueJobId),
76
- onKeyDown: (e) => {
77
- if (e.key === "Enter" || e.key === " ") {
78
- e.preventDefault();
79
- if (queueJobId) navigator.clipboard.writeText(queueJobId);
80
- }
81
- },
82
- role: "button",
83
- tabIndex: 0,
84
76
  children: [
85
77
  t("scheduler.job_logs.job_id", "Job ID"),
86
78
  ": ",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/scheduler/components/JobLogsModal.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\n\ntype BullMQJob = {\n id: string\n name: string\n data: Record<string, unknown>\n state: 'waiting' | 'active' | 'completed' | 'failed' | 'delayed'\n progress?: number\n returnvalue?: unknown\n failedReason?: string\n stacktrace?: string[]\n attemptsMade: number\n processedOn?: string\n finishedOn?: string\n logs: string[]\n}\n\ntype JobLogsModalProps = {\n open: boolean\n onClose: () => void\n queueJobId: string | null\n queueName: string | null\n scheduleName: string\n}\n\nexport function JobLogsModal({\n open,\n onClose,\n queueJobId,\n queueName,\n scheduleName,\n}: JobLogsModalProps) {\n const t = useT()\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [job, setJob] = React.useState<BullMQJob | null>(null)\n\n React.useEffect(() => {\n if (open && queueJobId && queueName) {\n fetchJobDetails()\n } else {\n setLoading(false)\n setError(null)\n setJob(null)\n }\n }, [open, queueJobId, queueName])\n\n const fetchJobDetails = async () => {\n setLoading(true)\n setError(null)\n \n try {\n const { result } = await apiCallOrThrow(\n `/api/scheduler/queue-jobs/${queueJobId}?queue=${queueName}`\n )\n setJob(result as BullMQJob)\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : t('scheduler.job_logs.load_failed', 'Failed to load job details'))\n } finally {\n setLoading(false)\n }\n }\n\n const getStateBadgeVariant = (state: string): 'destructive' | 'secondary' | 'default' | 'outline' => {\n switch (state) {\n case 'completed':\n return 'default'\n case 'failed':\n return 'destructive'\n case 'active':\n return 'outline'\n default:\n return 'secondary'\n }\n }\n\n const formatDuration = (processedOn?: string, finishedOn?: string) => {\n if (!processedOn || !finishedOn) return null\n const duration = new Date(finishedOn).getTime() - new Date(processedOn).getTime()\n return `${(duration / 1000).toFixed(2)}s`\n }\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"max-w-4xl max-h-[80vh] overflow-auto\">\n <DialogHeader className=\"overflow-hidden\">\n <DialogTitle>\n {t('scheduler.job_logs.title', 'Queue Job')}: {scheduleName}\n </DialogTitle>\n <p\n className=\"text-sm text-muted-foreground font-mono truncate cursor-pointer hover:text-primary transition-colors\"\n title={queueJobId ?? undefined}\n onClick={() => queueJobId && navigator.clipboard.writeText(queueJobId)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n if (queueJobId) navigator.clipboard.writeText(queueJobId)\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {t('scheduler.job_logs.job_id', 'Job ID')}: {queueJobId}\n </p>\n </DialogHeader>\n\n {loading && (\n <div className=\"flex justify-center items-center py-8\">\n <Spinner />\n </div>\n )}\n\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {!loading && !error && job && (\n <Tabs defaultValue=\"overview\" className=\"w-full\">\n <TabsList>\n <TabsTrigger value=\"overview\">{t('scheduler.job_logs.tab_overview', 'Overview')}</TabsTrigger>\n <TabsTrigger value=\"logs\">{t('scheduler.job_logs.tab_logs', 'Logs')}</TabsTrigger>\n <TabsTrigger value=\"data\">{t('scheduler.job_logs.tab_payload', 'Payload')}</TabsTrigger>\n {job.failedReason && (\n <TabsTrigger value=\"error\">{t('scheduler.job_logs.tab_error', 'Error Details')}</TabsTrigger>\n )}\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.state', 'State')}</Label>\n <div className=\"mt-1\">\n <Badge variant={getStateBadgeVariant(job.state)}>\n {job.state}\n </Badge>\n </div>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.attempts', 'Attempts')}</Label>\n <p className=\"mt-1 text-sm\">{job.attemptsMade}</p>\n </div>\n\n {job.processedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.processed', 'Processed')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(job.processedOn).toLocaleString()}\n </p>\n </div>\n )}\n\n {job.finishedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.finished', 'Finished')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(job.finishedOn).toLocaleString()}\n </p>\n </div>\n )}\n\n {job.processedOn && job.finishedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.duration', 'Duration')}</Label>\n <p className=\"mt-1 text-sm\">\n {formatDuration(job.processedOn, job.finishedOn)}\n </p>\n </div>\n )}\n\n {job.progress !== undefined && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.progress', 'Progress')}</Label>\n <p className=\"mt-1 text-sm\">{job.progress}%</p>\n </div>\n )}\n </div>\n\n {job.returnvalue !== undefined && job.returnvalue !== null && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.return_value', 'Return Value')}</Label>\n <pre className=\"mt-1 bg-muted p-3 rounded text-xs overflow-auto max-h-64\">\n {String(typeof job.returnvalue === 'string' ? job.returnvalue : JSON.stringify(job.returnvalue, null, 2))}\n </pre>\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"logs\">\n {job.logs.length > 0 ? (\n <pre className=\"bg-muted p-4 rounded text-xs overflow-auto max-h-96 font-mono\">\n {job.logs.join('\\n')}\n </pre>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('scheduler.job_logs.no_logs', 'No logs available')}</p>\n )}\n </TabsContent>\n\n <TabsContent value=\"data\">\n <pre className=\"bg-muted p-4 rounded text-xs overflow-auto max-h-96\">\n {JSON.stringify(job.data, null, 2)}\n </pre>\n </TabsContent>\n\n {job.failedReason && (\n <TabsContent value=\"error\" className=\"space-y-4\">\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.error_message', 'Error Message')}</Label>\n <pre className=\"mt-1 bg-red-50 dark:bg-red-950 p-3 rounded text-sm text-red-900 dark:text-red-100\">\n {job.failedReason}\n </pre>\n </div>\n\n {job.stacktrace && job.stacktrace.length > 0 && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.stack_trace', 'Stack Trace')}</Label>\n <pre className=\"mt-1 bg-muted p-3 rounded text-xs overflow-auto max-h-64 font-mono\">\n {job.stacktrace.join('\\n')}\n </pre>\n </div>\n )}\n </TabsContent>\n )}\n </Tabs>\n )}\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\n\ntype BullMQJob = {\n id: string\n name: string\n data: Record<string, unknown>\n state: 'waiting' | 'active' | 'completed' | 'failed' | 'delayed'\n progress?: number\n returnvalue?: unknown\n failedReason?: string\n stacktrace?: string[]\n attemptsMade: number\n processedOn?: string\n finishedOn?: string\n logs: string[]\n}\n\ntype JobLogsModalProps = {\n open: boolean\n onClose: () => void\n queueJobId: string | null\n queueName: string | null\n scheduleName: string\n}\n\nexport function JobLogsModal({\n open,\n onClose,\n queueJobId,\n queueName,\n scheduleName,\n}: JobLogsModalProps) {\n const t = useT()\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [job, setJob] = React.useState<BullMQJob | null>(null)\n\n React.useEffect(() => {\n if (open && queueJobId && queueName) {\n fetchJobDetails()\n } else {\n setLoading(false)\n setError(null)\n setJob(null)\n }\n }, [open, queueJobId, queueName])\n\n const fetchJobDetails = async () => {\n setLoading(true)\n setError(null)\n \n try {\n const { result } = await apiCallOrThrow(\n `/api/scheduler/queue-jobs/${queueJobId}?queue=${queueName}`\n )\n setJob(result as BullMQJob)\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : t('scheduler.job_logs.load_failed', 'Failed to load job details'))\n } finally {\n setLoading(false)\n }\n }\n\n const getStateBadgeVariant = (state: string): 'destructive' | 'secondary' | 'default' | 'outline' => {\n switch (state) {\n case 'completed':\n return 'default'\n case 'failed':\n return 'destructive'\n case 'active':\n return 'outline'\n default:\n return 'secondary'\n }\n }\n\n const formatDuration = (processedOn?: string, finishedOn?: string) => {\n if (!processedOn || !finishedOn) return null\n const duration = new Date(finishedOn).getTime() - new Date(processedOn).getTime()\n return `${(duration / 1000).toFixed(2)}s`\n }\n\n return (\n <Dialog open={open} onOpenChange={onClose}>\n <DialogContent className=\"max-w-4xl max-h-[80vh] overflow-auto\">\n <DialogHeader className=\"overflow-hidden\">\n <DialogTitle>\n {t('scheduler.job_logs.title', 'Queue Job')}: {scheduleName}\n </DialogTitle>\n <p \n className=\"text-sm text-muted-foreground font-mono truncate cursor-pointer hover:text-primary transition-colors\"\n title={queueJobId ?? undefined}\n onClick={() => queueJobId && navigator.clipboard.writeText(queueJobId)}\n >\n {t('scheduler.job_logs.job_id', 'Job ID')}: {queueJobId}\n </p>\n </DialogHeader>\n\n {loading && (\n <div className=\"flex justify-center items-center py-8\">\n <Spinner />\n </div>\n )}\n\n {error && (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {!loading && !error && job && (\n <Tabs defaultValue=\"overview\" className=\"w-full\">\n <TabsList>\n <TabsTrigger value=\"overview\">{t('scheduler.job_logs.tab_overview', 'Overview')}</TabsTrigger>\n <TabsTrigger value=\"logs\">{t('scheduler.job_logs.tab_logs', 'Logs')}</TabsTrigger>\n <TabsTrigger value=\"data\">{t('scheduler.job_logs.tab_payload', 'Payload')}</TabsTrigger>\n {job.failedReason && (\n <TabsTrigger value=\"error\">{t('scheduler.job_logs.tab_error', 'Error Details')}</TabsTrigger>\n )}\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.state', 'State')}</Label>\n <div className=\"mt-1\">\n <Badge variant={getStateBadgeVariant(job.state)}>\n {job.state}\n </Badge>\n </div>\n </div>\n\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.attempts', 'Attempts')}</Label>\n <p className=\"mt-1 text-sm\">{job.attemptsMade}</p>\n </div>\n\n {job.processedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.processed', 'Processed')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(job.processedOn).toLocaleString()}\n </p>\n </div>\n )}\n\n {job.finishedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.finished', 'Finished')}</Label>\n <p className=\"mt-1 text-sm\">\n {new Date(job.finishedOn).toLocaleString()}\n </p>\n </div>\n )}\n\n {job.processedOn && job.finishedOn && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.duration', 'Duration')}</Label>\n <p className=\"mt-1 text-sm\">\n {formatDuration(job.processedOn, job.finishedOn)}\n </p>\n </div>\n )}\n\n {job.progress !== undefined && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.progress', 'Progress')}</Label>\n <p className=\"mt-1 text-sm\">{job.progress}%</p>\n </div>\n )}\n </div>\n\n {job.returnvalue !== undefined && job.returnvalue !== null && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.return_value', 'Return Value')}</Label>\n <pre className=\"mt-1 bg-muted p-3 rounded text-xs overflow-auto max-h-64\">\n {String(typeof job.returnvalue === 'string' ? job.returnvalue : JSON.stringify(job.returnvalue, null, 2))}\n </pre>\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"logs\">\n {job.logs.length > 0 ? (\n <pre className=\"bg-muted p-4 rounded text-xs overflow-auto max-h-96 font-mono\">\n {job.logs.join('\\n')}\n </pre>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('scheduler.job_logs.no_logs', 'No logs available')}</p>\n )}\n </TabsContent>\n\n <TabsContent value=\"data\">\n <pre className=\"bg-muted p-4 rounded text-xs overflow-auto max-h-96\">\n {JSON.stringify(job.data, null, 2)}\n </pre>\n </TabsContent>\n\n {job.failedReason && (\n <TabsContent value=\"error\" className=\"space-y-4\">\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.error_message', 'Error Message')}</Label>\n <pre className=\"mt-1 bg-red-50 dark:bg-red-950 p-3 rounded text-sm text-red-900 dark:text-red-100\">\n {job.failedReason}\n </pre>\n </div>\n\n {job.stacktrace && job.stacktrace.length > 0 && (\n <div>\n <Label className=\"text-sm font-medium\">{t('scheduler.job_logs.stack_trace', 'Stack Trace')}</Label>\n <pre className=\"mt-1 bg-muted p-3 rounded text-xs overflow-auto max-h-64 font-mono\">\n {job.stacktrace.join('\\n')}\n </pre>\n </div>\n )}\n </TabsContent>\n )}\n </Tabs>\n )}\n </DialogContent>\n </Dialog>\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.4.6-develop-e321a4e2a1",
3
+ "version": "0.4.6-main-24e64eef39",
4
4
  "description": "Database-managed scheduled jobs with admin UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -58,9 +58,9 @@
58
58
  "./*/*/*/*/*/*.json": "./src/*/*/*/*/*/*.json"
59
59
  },
60
60
  "dependencies": {
61
- "@open-mercato/events": "0.4.6-develop-e321a4e2a1",
62
- "@open-mercato/queue": "0.4.6-develop-e321a4e2a1",
63
- "@open-mercato/shared": "0.4.6-develop-e321a4e2a1",
61
+ "@open-mercato/events": "0.4.6-main-24e64eef39",
62
+ "@open-mercato/queue": "0.4.6-main-24e64eef39",
63
+ "@open-mercato/shared": "0.4.6-main-24e64eef39",
64
64
  "cron-parser": "^4.9.0"
65
65
  },
66
66
  "peerDependencies": {
@@ -32,12 +32,12 @@ export async function GET(req: NextRequest) {
32
32
  }
33
33
 
34
34
  const queues = Array.from(queueSet)
35
- .sort((a, b) => a.localeCompare(b))
35
+ .sort()
36
36
  .map((queue) => ({ value: queue, label: queue }))
37
37
 
38
38
  const commands = commandRegistry
39
39
  .list()
40
- .sort((a, b) => a.localeCompare(b))
40
+ .sort()
41
41
  .map((id) => ({ value: id, label: id }))
42
42
 
43
43
  return NextResponse.json({ queues, commands })
@@ -117,18 +117,10 @@ export function ExecutionDetailsDialog({
117
117
  {run.queueJobId && (
118
118
  <div className="min-w-0 overflow-hidden">
119
119
  <Label className="text-sm font-medium text-muted-foreground">{t('scheduler.execution.queue_job_id', 'Queue Job ID')}</Label>
120
- <p
121
- className="mt-1 text-xs font-mono truncate cursor-pointer hover:text-primary transition-colors"
120
+ <p
121
+ className="mt-1 text-xs font-mono truncate cursor-pointer hover:text-primary transition-colors"
122
122
  title={run.queueJobId}
123
123
  onClick={() => navigator.clipboard.writeText(run.queueJobId!)}
124
- onKeyDown={(e) => {
125
- if (e.key === 'Enter' || e.key === ' ') {
126
- e.preventDefault()
127
- navigator.clipboard.writeText(run.queueJobId!)
128
- }
129
- }}
130
- role="button"
131
- tabIndex={0}
132
124
  >
133
125
  {run.queueJobId}
134
126
  </p>
@@ -98,18 +98,10 @@ export function JobLogsModal({
98
98
  <DialogTitle>
99
99
  {t('scheduler.job_logs.title', 'Queue Job')}: {scheduleName}
100
100
  </DialogTitle>
101
- <p
101
+ <p
102
102
  className="text-sm text-muted-foreground font-mono truncate cursor-pointer hover:text-primary transition-colors"
103
103
  title={queueJobId ?? undefined}
104
104
  onClick={() => queueJobId && navigator.clipboard.writeText(queueJobId)}
105
- onKeyDown={(e) => {
106
- if (e.key === 'Enter' || e.key === ' ') {
107
- e.preventDefault()
108
- if (queueJobId) navigator.clipboard.writeText(queueJobId)
109
- }
110
- }}
111
- role="button"
112
- tabIndex={0}
113
105
  >
114
106
  {t('scheduler.job_logs.job_id', 'Job ID')}: {queueJobId}
115
107
  </p>