@adcops/autocore-react 3.3.54 → 3.3.59

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.
@@ -0,0 +1,147 @@
1
+ /*
2
+ * Copyright (C) 2026 Automated Design Corp. All Rights Reserved.
3
+ *
4
+ * <TestMethodDialog> — picker UI for swapping the active test method.
5
+ *
6
+ * The main form displays a single "Test Method: <label>" row with an
7
+ * edit button. Clicking edit opens this dialog. The dialog shows a
8
+ * dropdown of every method declared in the current project's
9
+ * `test_methods` block, plus the long-form description for whichever
10
+ * method the operator has the dropdown highlighted on. OK commits the
11
+ * choice via the supplied callback; Cancel discards.
12
+ *
13
+ * This pattern scales past three or four methods where a SelectButton
14
+ * starts wrapping or eating horizontal space, and gives every method
15
+ * room to ship a description that disambiguates similar names.
16
+ */
17
+
18
+ import React, { useEffect, useMemo, useState } from 'react';
19
+ import { Button } from 'primereact/button';
20
+ import { Dialog } from 'primereact/dialog';
21
+ import { Dropdown } from 'primereact/dropdown';
22
+ import type { TestMethod } from './TestSetupForm';
23
+ import { useTisSchemas } from './TisProvider';
24
+
25
+ export interface TestMethodDialogProps {
26
+ visible: boolean;
27
+ onHide: () => void;
28
+ /** Method ID currently selected on the form. The dropdown opens
29
+ * pointing at this value so the dialog reflects current state. */
30
+ currentMethodId: string;
31
+ /**
32
+ * Called with the chosen method_id when the operator clicks OK.
33
+ * Cancel does not fire this callback. The parent is responsible
34
+ * for actually applying the new selection (e.g., updating the
35
+ * provider's selection or local state).
36
+ */
37
+ onSelected: (methodId: string) => void;
38
+ }
39
+
40
+ /** Display name for one method: prefer the schema's `label`, fall
41
+ * back to the canonical `method_id` key. */
42
+ const methodLabelOf = (methodId: string, schema: TestMethod | undefined): string =>
43
+ (schema?.label && schema.label.length > 0) ? schema.label : methodId;
44
+
45
+ export const TestMethodDialog: React.FC<TestMethodDialogProps> = ({
46
+ visible, onHide, currentMethodId, onSelected,
47
+ }) => {
48
+ const schemas = useTisSchemas();
49
+
50
+ // Local "draft" selection — the dropdown writes to this; OK
51
+ // applies it. We deliberately don't update the provider's
52
+ // selection on every dropdown change, so a Cancel really cancels.
53
+ const [draftMethodId, setDraftMethodId] = useState<string>(currentMethodId);
54
+
55
+ // Re-sync the draft whenever the dialog opens so a stale value
56
+ // from a previous open doesn't ghost the current selection.
57
+ useEffect(() => {
58
+ if (visible) setDraftMethodId(currentMethodId);
59
+ }, [visible, currentMethodId]);
60
+
61
+ const options = useMemo(() => {
62
+ return Object.keys(schemas).map(methodId => ({
63
+ label: methodLabelOf(methodId, schemas[methodId]),
64
+ value: methodId,
65
+ }));
66
+ }, [schemas]);
67
+
68
+ const draftSchema = schemas[draftMethodId];
69
+ const draftDescription =
70
+ (draftSchema?.description && draftSchema.description.length > 0)
71
+ ? draftSchema.description
72
+ : null;
73
+
74
+ const handleOk = () => {
75
+ if (draftMethodId && draftMethodId !== currentMethodId) {
76
+ onSelected(draftMethodId);
77
+ }
78
+ onHide();
79
+ };
80
+
81
+ const footer = (
82
+ <div style={{ display: 'flex', justifyContent: 'flex-end', gap: '0.5rem' }}>
83
+ <Button label="Cancel" icon="pi pi-times" onClick={onHide} text />
84
+ <Button
85
+ label="OK"
86
+ icon="pi pi-check"
87
+ onClick={handleOk}
88
+ disabled={!draftMethodId}
89
+ />
90
+ </div>
91
+ );
92
+
93
+ return (
94
+ <Dialog
95
+ header="Select Test Method"
96
+ visible={visible}
97
+ onHide={onHide}
98
+ footer={footer}
99
+ modal
100
+ style={{ width: 'min(560px, 90vw)' }}
101
+ >
102
+ {options.length === 0 ? (
103
+ <p style={{ color: 'var(--text-secondary-color)' }}>
104
+ No test methods are declared in this project's <code>test_methods</code> block.
105
+ </p>
106
+ ) : (
107
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
108
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
109
+ <label htmlFor="acTestMethodDropdown" style={{ flexShrink: 0 }}>
110
+ Test Method:
111
+ </label>
112
+ <Dropdown
113
+ inputId="acTestMethodDropdown"
114
+ value={draftMethodId}
115
+ options={options}
116
+ onChange={(e) => setDraftMethodId(e.value)}
117
+ placeholder="Select a method"
118
+ style={{ flex: 1 }}
119
+ />
120
+ </div>
121
+ {/*
122
+ * Show the description region whenever we have a
123
+ * draft selection — keeps layout stable even when
124
+ * the operator picks a method without one (we just
125
+ * render a muted placeholder rather than collapsing
126
+ * the dialog by ~3rem).
127
+ */}
128
+ <div
129
+ style={{
130
+ padding: '0.75rem 1rem',
131
+ background: 'var(--surface-100)',
132
+ borderRadius: '6px',
133
+ minHeight: '4.5rem',
134
+ color: draftDescription
135
+ ? 'var(--text-color)'
136
+ : 'var(--text-secondary-color)',
137
+ fontStyle: draftDescription ? 'normal' : 'italic',
138
+ whiteSpace: 'pre-wrap',
139
+ }}
140
+ >
141
+ {draftDescription ?? 'No description provided for this test method.'}
142
+ </div>
143
+ </div>
144
+ )}
145
+ </Dialog>
146
+ );
147
+ };