@arronqzy/react-blueprint 1.0.3 → 1.0.4
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.
- package/index.ts +2 -1
- package/package.json +4 -3
- package/src/BlueprintContextMenu.tsx +5 -3
- package/src/BlueprintNodeConfigSidebar.tsx +56 -57
- package/src/components/BlueprintExecutionLogPanel.tsx +30 -28
- package/src/components/BlueprintLibrarySelect.tsx +11 -4
- package/src/components/BlueprintMetaDialog.tsx +20 -10
- package/src/components/BlueprintNodeSwitchTaskDialog.tsx +14 -8
- package/src/components/BlueprintPanelToolbar.tsx +50 -42
- package/src/components/ClockNodeConfigPanel.tsx +19 -12
- package/src/components/FetchNodeConfigPanel.tsx +36 -33
- package/src/components/FetchUrlAutocomplete.tsx +3 -1
- package/src/components/JsonNodeConfigPanel.tsx +15 -7
- package/src/components/LogicNodeConfigPanel.tsx +13 -7
- package/src/components/ViewElementMultiSelect.tsx +25 -18
- package/src/dev-seed.ts +2 -2
- package/src/fetch-config-task-store.ts +8 -2
- package/src/graph/document.ts +51 -14
- package/src/graph/node-summary.ts +32 -18
- package/src/hooks/useBlueprintPageLifecycle.ts +29 -1
- package/src/library/blueprint-io.ts +12 -3
- package/src/library/swagger-docs.ts +15 -5
- package/src/main.tsx +12 -5
- package/src/nodes/AndFlowNode.tsx +7 -5
- package/src/nodes/BlueprintFlowNode.tsx +4 -2
- package/src/nodes/BlueprintNodeCard.tsx +4 -2
- package/src/nodes/BlueprintNodeShell.tsx +4 -2
- package/src/nodes/ClockFlowNode.tsx +5 -3
- package/src/nodes/FetchFlowNode.tsx +4 -2
- package/src/nodes/JsonFlowNode.tsx +4 -2
- package/src/nodes/LifecycleFlowNode.tsx +5 -3
- package/src/nodes/LogicFlowNode.tsx +4 -2
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Label,
|
|
12
12
|
Textarea,
|
|
13
13
|
} from "@arronqzy/ui";
|
|
14
|
+
import { useI18n } from "@arronqzy/i18n/react";
|
|
14
15
|
|
|
15
16
|
import type { BlueprintMetaDraft } from "../library/types";
|
|
16
17
|
|
|
@@ -29,6 +30,7 @@ export function BlueprintMetaDialog({
|
|
|
29
30
|
onOpenChange,
|
|
30
31
|
onConfirm,
|
|
31
32
|
}: BlueprintMetaDialogProps) {
|
|
33
|
+
const { t } = useI18n();
|
|
32
34
|
const [name, setName] = useState(initialMeta.name);
|
|
33
35
|
const [remark, setRemark] = useState(initialMeta.remark);
|
|
34
36
|
|
|
@@ -38,16 +40,20 @@ export function BlueprintMetaDialog({
|
|
|
38
40
|
setRemark(initialMeta.remark);
|
|
39
41
|
}, [initialMeta.name, initialMeta.remark, open]);
|
|
40
42
|
|
|
41
|
-
const title =
|
|
43
|
+
const title =
|
|
44
|
+
mode === "export"
|
|
45
|
+
? t("blueprint.dialog.exportTitle")
|
|
46
|
+
: t("blueprint.dialog.saveTitle");
|
|
42
47
|
const description =
|
|
43
48
|
mode === "export"
|
|
44
|
-
? "
|
|
45
|
-
: "
|
|
46
|
-
const confirmLabel =
|
|
49
|
+
? t("blueprint.dialog.exportDescription")
|
|
50
|
+
: t("blueprint.dialog.saveDescription");
|
|
51
|
+
const confirmLabel =
|
|
52
|
+
mode === "export" ? t("blueprint.dialog.export") : t("blueprint.dialog.save");
|
|
47
53
|
|
|
48
54
|
const handleConfirm = () => {
|
|
49
55
|
onConfirm({
|
|
50
|
-
name: name.trim() || "
|
|
56
|
+
name: name.trim() || t("blueprint.dialog.unnamedBlueprint"),
|
|
51
57
|
remark: remark.trim(),
|
|
52
58
|
});
|
|
53
59
|
onOpenChange(false);
|
|
@@ -62,29 +68,33 @@ export function BlueprintMetaDialog({
|
|
|
62
68
|
</DialogHeader>
|
|
63
69
|
<div className="space-y-3 py-1">
|
|
64
70
|
<div className="space-y-1.5">
|
|
65
|
-
<Label htmlFor="blueprint-meta-name"
|
|
71
|
+
<Label htmlFor="blueprint-meta-name">
|
|
72
|
+
{t("blueprint.dialog.blueprintName")}
|
|
73
|
+
</Label>
|
|
66
74
|
<Input
|
|
67
75
|
id="blueprint-meta-name"
|
|
68
76
|
value={name}
|
|
69
77
|
onChange={(e) => setName(e.target.value)}
|
|
70
|
-
placeholder="
|
|
78
|
+
placeholder={t("blueprint.dialog.namePlaceholder")}
|
|
71
79
|
autoFocus
|
|
72
80
|
/>
|
|
73
81
|
</div>
|
|
74
82
|
<div className="space-y-1.5">
|
|
75
|
-
<Label htmlFor="blueprint-meta-remark"
|
|
83
|
+
<Label htmlFor="blueprint-meta-remark">
|
|
84
|
+
{t("blueprint.dialog.remark")}
|
|
85
|
+
</Label>
|
|
76
86
|
<Textarea
|
|
77
87
|
id="blueprint-meta-remark"
|
|
78
88
|
value={remark}
|
|
79
89
|
onChange={(e) => setRemark(e.target.value)}
|
|
80
|
-
placeholder="
|
|
90
|
+
placeholder={t("blueprint.dialog.remarkPlaceholder")}
|
|
81
91
|
rows={3}
|
|
82
92
|
/>
|
|
83
93
|
</div>
|
|
84
94
|
</div>
|
|
85
95
|
<DialogFooter>
|
|
86
96
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
|
87
|
-
|
|
97
|
+
{t("common.cancel")}
|
|
88
98
|
</Button>
|
|
89
99
|
<Button type="button" onClick={handleConfirm}>
|
|
90
100
|
{confirmLabel}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
DialogHeader,
|
|
8
8
|
DialogTitle,
|
|
9
9
|
} from "@arronqzy/ui";
|
|
10
|
+
import { useI18n } from "@arronqzy/i18n/react";
|
|
10
11
|
|
|
11
12
|
export type BlueprintNodeSwitchTaskDialogProps = {
|
|
12
13
|
open: boolean;
|
|
@@ -25,31 +26,36 @@ export function BlueprintNodeSwitchTaskDialog({
|
|
|
25
26
|
onKeepTaskAndSwitch,
|
|
26
27
|
onCancelTaskAndSwitch,
|
|
27
28
|
}: BlueprintNodeSwitchTaskDialogProps) {
|
|
29
|
+
const { t } = useI18n();
|
|
28
30
|
const targetLabel =
|
|
29
|
-
toNodeId === null
|
|
31
|
+
toNodeId === null
|
|
32
|
+
? t("blueprint.dialog.cancelSelection")
|
|
33
|
+
: t("blueprint.dialog.nodeTarget", { id: toNodeId });
|
|
30
34
|
|
|
31
35
|
return (
|
|
32
36
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
33
37
|
<DialogContent className="sm:max-w-md">
|
|
34
38
|
<DialogHeader>
|
|
35
|
-
<DialogTitle
|
|
39
|
+
<DialogTitle>{t("blueprint.dialog.taskRunningTitle")}</DialogTitle>
|
|
36
40
|
<DialogDescription>
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
{t("blueprint.dialog.taskRunningDescription", {
|
|
42
|
+
fromNodeId,
|
|
43
|
+
target: targetLabel,
|
|
44
|
+
})}
|
|
39
45
|
</DialogDescription>
|
|
40
46
|
</DialogHeader>
|
|
41
47
|
<p className="text-xs text-muted-foreground">
|
|
42
|
-
|
|
48
|
+
{t("blueprint.dialog.taskSwitchHint")}
|
|
43
49
|
</p>
|
|
44
50
|
<DialogFooter className="gap-2 sm:gap-0">
|
|
45
51
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
|
46
|
-
|
|
52
|
+
{t("blueprint.dialog.stayOnNode")}
|
|
47
53
|
</Button>
|
|
48
54
|
<Button type="button" variant="secondary" onClick={onCancelTaskAndSwitch}>
|
|
49
|
-
|
|
55
|
+
{t("blueprint.dialog.cancelAndSwitch")}
|
|
50
56
|
</Button>
|
|
51
57
|
<Button type="button" onClick={onKeepTaskAndSwitch}>
|
|
52
|
-
|
|
58
|
+
{t("blueprint.dialog.keepAndSwitch")}
|
|
53
59
|
</Button>
|
|
54
60
|
</DialogFooter>
|
|
55
61
|
</DialogContent>
|
|
@@ -17,7 +17,9 @@ import {
|
|
|
17
17
|
|
|
18
18
|
import type { BlueprintLibraryListItem } from "../library/types";
|
|
19
19
|
import type { LifecycleNodeOption } from "../hooks/useBlueprintDebugSession";
|
|
20
|
-
import {
|
|
20
|
+
import { type PageLifecyclePhase } from "@arronqzy/blueprint-dsl";
|
|
21
|
+
import { useI18n } from "@arronqzy/i18n/react";
|
|
22
|
+
import { getLifecyclePhaseLabel } from "../graph/document";
|
|
21
23
|
|
|
22
24
|
export type BlueprintRenameDialogProps = {
|
|
23
25
|
open: boolean;
|
|
@@ -32,6 +34,7 @@ export function BlueprintRenameDialog({
|
|
|
32
34
|
onOpenChange,
|
|
33
35
|
onConfirm,
|
|
34
36
|
}: BlueprintRenameDialogProps) {
|
|
37
|
+
const { t } = useI18n();
|
|
35
38
|
const [name, setName] = useState(initialName);
|
|
36
39
|
|
|
37
40
|
useEffect(() => {
|
|
@@ -50,11 +53,11 @@ export function BlueprintRenameDialog({
|
|
|
50
53
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
51
54
|
<DialogContent className="sm:max-w-sm">
|
|
52
55
|
<DialogHeader>
|
|
53
|
-
<DialogTitle
|
|
54
|
-
<DialogDescription
|
|
56
|
+
<DialogTitle>{t("blueprint.dialog.renameTitle")}</DialogTitle>
|
|
57
|
+
<DialogDescription>{t("blueprint.dialog.renameDescription")}</DialogDescription>
|
|
55
58
|
</DialogHeader>
|
|
56
59
|
<div className="space-y-1.5 py-1">
|
|
57
|
-
<Label htmlFor="blueprint-rename-input"
|
|
60
|
+
<Label htmlFor="blueprint-rename-input">{t("blueprint.dialog.blueprintName")}</Label>
|
|
58
61
|
<Input
|
|
59
62
|
id="blueprint-rename-input"
|
|
60
63
|
value={name}
|
|
@@ -67,10 +70,10 @@ export function BlueprintRenameDialog({
|
|
|
67
70
|
</div>
|
|
68
71
|
<DialogFooter>
|
|
69
72
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
|
70
|
-
|
|
73
|
+
{t("common.cancel")}
|
|
71
74
|
</Button>
|
|
72
75
|
<Button type="button" onClick={handleConfirm} disabled={!name.trim()}>
|
|
73
|
-
|
|
76
|
+
{t("common.confirm")}
|
|
74
77
|
</Button>
|
|
75
78
|
</DialogFooter>
|
|
76
79
|
</DialogContent>
|
|
@@ -174,18 +177,19 @@ export function BlueprintDeleteDialog({
|
|
|
174
177
|
onOpenChange,
|
|
175
178
|
onConfirm,
|
|
176
179
|
}: BlueprintDeleteDialogProps) {
|
|
180
|
+
const { t } = useI18n();
|
|
177
181
|
return (
|
|
178
182
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
179
183
|
<DialogContent className="sm:max-w-sm">
|
|
180
184
|
<DialogHeader>
|
|
181
|
-
<DialogTitle
|
|
185
|
+
<DialogTitle>{t("blueprint.dialog.deleteTitle")}</DialogTitle>
|
|
182
186
|
<DialogDescription>
|
|
183
|
-
|
|
187
|
+
{t("blueprint.dialog.deleteDescription", { name: blueprintName })}
|
|
184
188
|
</DialogDescription>
|
|
185
189
|
</DialogHeader>
|
|
186
190
|
<DialogFooter>
|
|
187
191
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
|
188
|
-
|
|
192
|
+
{t("common.cancel")}
|
|
189
193
|
</Button>
|
|
190
194
|
<Button
|
|
191
195
|
type="button"
|
|
@@ -195,7 +199,7 @@ export function BlueprintDeleteDialog({
|
|
|
195
199
|
onOpenChange(false);
|
|
196
200
|
}}
|
|
197
201
|
>
|
|
198
|
-
|
|
202
|
+
{t("common.delete")}
|
|
199
203
|
</Button>
|
|
200
204
|
</DialogFooter>
|
|
201
205
|
</DialogContent>
|
|
@@ -335,6 +339,7 @@ function LibraryRow({
|
|
|
335
339
|
onRename: () => void;
|
|
336
340
|
onDelete: () => void;
|
|
337
341
|
}) {
|
|
342
|
+
const { t } = useI18n();
|
|
338
343
|
const nameButton = (
|
|
339
344
|
<button
|
|
340
345
|
type="button"
|
|
@@ -352,17 +357,17 @@ function LibraryRow({
|
|
|
352
357
|
}`}
|
|
353
358
|
>
|
|
354
359
|
{active ? (
|
|
355
|
-
<ToolbarTooltip content="
|
|
360
|
+
<ToolbarTooltip content={t("blueprint.toolbar.clickAgainReturnWorkspace")}>
|
|
356
361
|
{nameButton}
|
|
357
362
|
</ToolbarTooltip>
|
|
358
363
|
) : (
|
|
359
364
|
nameButton
|
|
360
365
|
)}
|
|
361
|
-
<ToolbarTooltip content={
|
|
366
|
+
<ToolbarTooltip content={t("blueprint.toolbar.renameTooltip", { name: item.name })}>
|
|
362
367
|
<button
|
|
363
368
|
type="button"
|
|
364
369
|
className="shrink-0 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
365
|
-
aria-label={
|
|
370
|
+
aria-label={t("blueprint.toolbar.renameAriaLabel", { name: item.name })}
|
|
366
371
|
onClick={(e) => {
|
|
367
372
|
e.stopPropagation();
|
|
368
373
|
onRename();
|
|
@@ -371,11 +376,11 @@ function LibraryRow({
|
|
|
371
376
|
<IconPencil />
|
|
372
377
|
</button>
|
|
373
378
|
</ToolbarTooltip>
|
|
374
|
-
<ToolbarTooltip content={
|
|
379
|
+
<ToolbarTooltip content={t("blueprint.toolbar.deleteTooltip", { name: item.name })}>
|
|
375
380
|
<button
|
|
376
381
|
type="button"
|
|
377
382
|
className="shrink-0 rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
|
378
|
-
aria-label={
|
|
383
|
+
aria-label={t("blueprint.toolbar.deleteAriaLabel", { name: item.name })}
|
|
379
384
|
onClick={(e) => {
|
|
380
385
|
e.stopPropagation();
|
|
381
386
|
onDelete();
|
|
@@ -400,6 +405,7 @@ export function BlueprintPanelToolbar({
|
|
|
400
405
|
canSync = false,
|
|
401
406
|
debug,
|
|
402
407
|
}: BlueprintPanelToolbarProps) {
|
|
408
|
+
const { t } = useI18n();
|
|
403
409
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
404
410
|
const [renameTarget, setRenameTarget] = useState<BlueprintLibraryListItem | null>(
|
|
405
411
|
null
|
|
@@ -413,7 +419,9 @@ export function BlueprintPanelToolbar({
|
|
|
413
419
|
const triggerLabel =
|
|
414
420
|
activeItem?.name ??
|
|
415
421
|
(currentBlueprintLabel?.trim() ||
|
|
416
|
-
(items.length > 0
|
|
422
|
+
(items.length > 0
|
|
423
|
+
? t("blueprint.toolbar.library")
|
|
424
|
+
: t("blueprint.toolbar.libraryEmpty")));
|
|
417
425
|
|
|
418
426
|
const handleRenameConfirm = (name: string) => {
|
|
419
427
|
if (!renameTarget) return;
|
|
@@ -426,7 +434,7 @@ export function BlueprintPanelToolbar({
|
|
|
426
434
|
<TooltipProvider delayDuration={200}>
|
|
427
435
|
<div className="flex min-w-0 flex-1 items-center gap-1.5">
|
|
428
436
|
<div className="relative shrink-0">
|
|
429
|
-
<ToolbarTooltip content="
|
|
437
|
+
<ToolbarTooltip content={t("blueprint.toolbar.openLibraryTooltip")}>
|
|
430
438
|
<span className={items.length === 0 ? "inline-flex" : undefined}>
|
|
431
439
|
<Button
|
|
432
440
|
type="button"
|
|
@@ -452,7 +460,7 @@ export function BlueprintPanelToolbar({
|
|
|
452
460
|
{saved.length > 0 ? (
|
|
453
461
|
<div className="mb-1">
|
|
454
462
|
<div className="px-2 py-1 text-[10px] font-semibold text-muted-foreground">
|
|
455
|
-
|
|
463
|
+
{t("blueprint.toolbar.saved")}
|
|
456
464
|
</div>
|
|
457
465
|
{saved.map((item) => (
|
|
458
466
|
<LibraryRow
|
|
@@ -472,7 +480,7 @@ export function BlueprintPanelToolbar({
|
|
|
472
480
|
{imported.length > 0 ? (
|
|
473
481
|
<div>
|
|
474
482
|
<div className="px-2 py-1 text-[10px] font-semibold text-muted-foreground">
|
|
475
|
-
|
|
483
|
+
{t("blueprint.toolbar.imported")}
|
|
476
484
|
</div>
|
|
477
485
|
{imported.map((item) => (
|
|
478
486
|
<LibraryRow
|
|
@@ -499,8 +507,8 @@ export function BlueprintPanelToolbar({
|
|
|
499
507
|
variant="outline"
|
|
500
508
|
size="icon"
|
|
501
509
|
className="h-7 w-7 shrink-0"
|
|
502
|
-
content="
|
|
503
|
-
aria-label="
|
|
510
|
+
content={t("blueprint.toolbar.saveToLocalLibrary")}
|
|
511
|
+
aria-label={t("blueprint.toolbar.saveToLocalAriaLabel")}
|
|
504
512
|
onClick={onSave}
|
|
505
513
|
>
|
|
506
514
|
<IconSave />
|
|
@@ -515,13 +523,13 @@ export function BlueprintPanelToolbar({
|
|
|
515
523
|
content={
|
|
516
524
|
canSync
|
|
517
525
|
? activeItem
|
|
518
|
-
?
|
|
519
|
-
: "
|
|
526
|
+
? t("blueprint.toolbar.syncUpdateNamed", { name: activeItem.name })
|
|
527
|
+
: t("blueprint.toolbar.syncToLibrary")
|
|
520
528
|
: activeItem
|
|
521
|
-
?
|
|
522
|
-
: "
|
|
529
|
+
? t("blueprint.toolbar.alreadyInSyncNamed", { name: activeItem.name })
|
|
530
|
+
: t("blueprint.toolbar.selectBlueprintFirst")
|
|
523
531
|
}
|
|
524
|
-
aria-label="
|
|
532
|
+
aria-label={t("blueprint.toolbar.syncAriaLabel")}
|
|
525
533
|
disabled={!canSync}
|
|
526
534
|
onClick={onSync}
|
|
527
535
|
>
|
|
@@ -531,19 +539,19 @@ export function BlueprintPanelToolbar({
|
|
|
531
539
|
|
|
532
540
|
{debug && debug.lifecycleNodes.length > 0 ? (
|
|
533
541
|
<>
|
|
534
|
-
<ToolbarTooltip content="
|
|
542
|
+
<ToolbarTooltip content={t("blueprint.toolbar.simulateSceneTooltip")}>
|
|
535
543
|
<select
|
|
536
544
|
value={debug.selectedLifecycleNodeId ?? ""}
|
|
537
545
|
onChange={(e) => debug.onSelectLifecycleNode(e.target.value || null)}
|
|
538
546
|
className="h-7 max-w-[180px] shrink-0 rounded-md border border-input bg-background px-2 text-[11px] text-foreground outline-none focus-visible:ring-1 focus-visible:ring-primary"
|
|
539
|
-
aria-label="
|
|
547
|
+
aria-label={t("blueprint.toolbar.simulateSceneAriaLabel")}
|
|
540
548
|
>
|
|
541
|
-
<option value=""
|
|
549
|
+
<option value="">{t("blueprint.toolbar.simulateScene")}</option>
|
|
542
550
|
{debug.lifecycleNodes.map((node) => (
|
|
543
551
|
<option key={node.id} value={node.id}>
|
|
544
552
|
{node.label}
|
|
545
553
|
{node.phase
|
|
546
|
-
? ` · ${
|
|
554
|
+
? ` · ${getLifecyclePhaseLabel(t, node.phase as PageLifecyclePhase)}`
|
|
547
555
|
: ""}
|
|
548
556
|
</option>
|
|
549
557
|
))}
|
|
@@ -555,8 +563,8 @@ export function BlueprintPanelToolbar({
|
|
|
555
563
|
variant="outline"
|
|
556
564
|
size="icon"
|
|
557
565
|
className="h-7 w-7 shrink-0"
|
|
558
|
-
content="
|
|
559
|
-
aria-label="
|
|
566
|
+
content={t("blueprint.toolbar.runAllTooltip")}
|
|
567
|
+
aria-label={t("blueprint.toolbar.runAllAriaLabel")}
|
|
560
568
|
disabled={!debug.selectedLifecycleNodeId || debug.running}
|
|
561
569
|
onClick={() => void debug.onRunAll()}
|
|
562
570
|
>
|
|
@@ -568,8 +576,8 @@ export function BlueprintPanelToolbar({
|
|
|
568
576
|
variant="outline"
|
|
569
577
|
size="icon"
|
|
570
578
|
className="h-7 w-7 shrink-0"
|
|
571
|
-
content="
|
|
572
|
-
aria-label="
|
|
579
|
+
content={t("blueprint.toolbar.resetToStartTooltip")}
|
|
580
|
+
aria-label={t("blueprint.toolbar.resetToStartAriaLabel")}
|
|
573
581
|
disabled={
|
|
574
582
|
!debug.selectedLifecycleNodeId ||
|
|
575
583
|
debug.running ||
|
|
@@ -585,8 +593,8 @@ export function BlueprintPanelToolbar({
|
|
|
585
593
|
variant="outline"
|
|
586
594
|
size="icon"
|
|
587
595
|
className="h-7 w-7 shrink-0"
|
|
588
|
-
content="
|
|
589
|
-
aria-label="
|
|
596
|
+
content={t("blueprint.toolbar.stepBackTooltip")}
|
|
597
|
+
aria-label={t("blueprint.toolbar.stepBackAriaLabel")}
|
|
590
598
|
disabled={
|
|
591
599
|
!debug.selectedLifecycleNodeId ||
|
|
592
600
|
debug.running ||
|
|
@@ -604,12 +612,12 @@ export function BlueprintPanelToolbar({
|
|
|
604
612
|
className="h-7 w-7 shrink-0"
|
|
605
613
|
content={
|
|
606
614
|
debug.falseSignalHalt
|
|
607
|
-
? "
|
|
615
|
+
? t("blueprint.toolbar.stepNextFalseHalt")
|
|
608
616
|
: debug.chainComplete
|
|
609
|
-
? "
|
|
610
|
-
: "
|
|
617
|
+
? t("blueprint.toolbar.stepNextChainComplete")
|
|
618
|
+
: t("blueprint.toolbar.stepNextTooltip")
|
|
611
619
|
}
|
|
612
|
-
aria-label="
|
|
620
|
+
aria-label={t("blueprint.toolbar.stepNextAriaLabel")}
|
|
613
621
|
disabled={
|
|
614
622
|
!debug.selectedLifecycleNodeId ||
|
|
615
623
|
debug.running ||
|
|
@@ -620,13 +628,13 @@ export function BlueprintPanelToolbar({
|
|
|
620
628
|
<IconStepNext className="h-3.5 w-3.5" />
|
|
621
629
|
</ToolbarTooltipButton>
|
|
622
630
|
|
|
623
|
-
<ToolbarTooltip content="
|
|
631
|
+
<ToolbarTooltip content={t("blueprint.toolbar.logPanelTooltip")}>
|
|
624
632
|
<Button
|
|
625
633
|
type="button"
|
|
626
634
|
variant={debug.logPanelOpen ? "default" : "outline"}
|
|
627
635
|
size="icon"
|
|
628
636
|
className="h-7 w-7 shrink-0"
|
|
629
|
-
aria-label="
|
|
637
|
+
aria-label={t("blueprint.toolbar.logPanelAriaLabel")}
|
|
630
638
|
aria-pressed={debug.logPanelOpen}
|
|
631
639
|
onClick={debug.onToggleLogPanel}
|
|
632
640
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, type ChangeEvent } from "react";
|
|
2
2
|
import { Input } from "@arronqzy/ui";
|
|
3
3
|
import type { ClockNodeConfig } from "@arronqzy/blueprint-dsl";
|
|
4
|
+
import { useI18n } from "@arronqzy/i18n/react";
|
|
4
5
|
|
|
5
6
|
import type { BlueprintGraphNode } from "../graph/document";
|
|
6
7
|
import { resolveNodeClockConfig } from "../graph/document";
|
|
@@ -27,6 +28,7 @@ export function ClockNodeConfigPanel({
|
|
|
27
28
|
node,
|
|
28
29
|
onUpdateNode,
|
|
29
30
|
}: ClockNodeConfigPanelProps) {
|
|
31
|
+
const { t } = useI18n();
|
|
30
32
|
const clockConfig = resolveNodeClockConfig(node);
|
|
31
33
|
|
|
32
34
|
const handleIntervalChange = useCallback(
|
|
@@ -71,15 +73,17 @@ export function ClockNodeConfigPanel({
|
|
|
71
73
|
|
|
72
74
|
return (
|
|
73
75
|
<div className="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5">
|
|
74
|
-
<div className="font-medium text-foreground"
|
|
76
|
+
<div className="font-medium text-foreground">
|
|
77
|
+
{t("blueprint.config.clockTitle")}
|
|
78
|
+
</div>
|
|
75
79
|
<p className="text-[11px] text-muted-foreground">
|
|
76
|
-
|
|
77
|
-
<strong>真信号</strong>,值包含当前时间(formatted / timestamp / isoTime)。
|
|
78
|
-
假信号会原样向下游传递。
|
|
80
|
+
{t("blueprint.config.clockHint")}
|
|
79
81
|
</p>
|
|
80
82
|
|
|
81
83
|
<label className="block space-y-1">
|
|
82
|
-
<span className="text-muted-foreground"
|
|
84
|
+
<span className="text-muted-foreground">
|
|
85
|
+
{t("blueprint.config.clockIntervalSeconds")}
|
|
86
|
+
</span>
|
|
83
87
|
<Input
|
|
84
88
|
type="number"
|
|
85
89
|
min={0}
|
|
@@ -89,12 +93,14 @@ export function ClockNodeConfigPanel({
|
|
|
89
93
|
className="h-8"
|
|
90
94
|
/>
|
|
91
95
|
<p className="text-[11px] text-muted-foreground">
|
|
92
|
-
|
|
96
|
+
{t("blueprint.config.clockIntervalHint")}
|
|
93
97
|
</p>
|
|
94
98
|
</label>
|
|
95
99
|
|
|
96
100
|
<label className="block space-y-1">
|
|
97
|
-
<span className="text-muted-foreground"
|
|
101
|
+
<span className="text-muted-foreground">
|
|
102
|
+
{t("blueprint.config.outputCount")}
|
|
103
|
+
</span>
|
|
98
104
|
<Input
|
|
99
105
|
type="number"
|
|
100
106
|
min={1}
|
|
@@ -104,7 +110,7 @@ export function ClockNodeConfigPanel({
|
|
|
104
110
|
className="h-8"
|
|
105
111
|
/>
|
|
106
112
|
<p className="text-[11px] text-muted-foreground">
|
|
107
|
-
|
|
113
|
+
{t("blueprint.config.outputCountHint")}
|
|
108
114
|
</p>
|
|
109
115
|
</label>
|
|
110
116
|
|
|
@@ -116,13 +122,14 @@ export function ClockNodeConfigPanel({
|
|
|
116
122
|
className="mt-0.5 h-3.5 w-3.5 shrink-0 rounded border border-input"
|
|
117
123
|
/>
|
|
118
124
|
<span className="text-[11px] leading-relaxed text-muted-foreground">
|
|
119
|
-
|
|
120
|
-
秒依次执行;仅输出 1 次时也会立刻执行。关闭则每次(含首次)都先等待 m 秒。
|
|
125
|
+
{t("blueprint.config.emitImmediately")}
|
|
121
126
|
</span>
|
|
122
127
|
</label>
|
|
123
128
|
|
|
124
129
|
<label className="block space-y-1">
|
|
125
|
-
<span className="text-muted-foreground"
|
|
130
|
+
<span className="text-muted-foreground">
|
|
131
|
+
{t("blueprint.config.timeFormat")}
|
|
132
|
+
</span>
|
|
126
133
|
<Input
|
|
127
134
|
value={clockConfig.timeFormat}
|
|
128
135
|
onChange={handleFormatChange}
|
|
@@ -131,7 +138,7 @@ export function ClockNodeConfigPanel({
|
|
|
131
138
|
placeholder="YYYY-MM-DD HH:mm:ss"
|
|
132
139
|
/>
|
|
133
140
|
<p className="text-[11px] text-muted-foreground">
|
|
134
|
-
|
|
141
|
+
{t("blueprint.config.timeFormatHint")}
|
|
135
142
|
</p>
|
|
136
143
|
</label>
|
|
137
144
|
</div>
|