PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / trunk
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance vtrunk
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / vendor / team-updraft / lib-onboarding-wizard / Wizard / Onboarding / src / components / Fields / Fields.tsx

Fields.tsx in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance trunk, at vendor/team-updraft/lib-onboarding-wizard/Wizard/Onboarding/src/components/Fields/Fields.tsx

194 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import License from './License';
2 import Checkbox from './Checkbox';
3 import CheckboxCard from './CheckboxCard';
4 import TrackingTest from './TrackingTest';
5 import Email from './Email';
6 import Password from './Password';
7 import Plugins from './Plugins';
8 import QrCode from './QrCode';
9 import TwoFaValidation from './TwoFaValidation';
10 import BackupCodes from './BackupCodes';
11 import Dropdown from './Dropdown';
12 import NumberInputWithControls from './NumberInputWithControls';
13 import MultiSelectDropdown from './MultiSelectDropdown';
14 import Text from './Text';
15 import Textarea from './Textarea';
16 import Pricing from './Pricing';
17 import Status from './Status';
18 import { ErrorBoundary } from '../ErrorBoundary';
19 // @ts-ignore
20 import useOnboardingStore from "@/store/useOnboardingStore";
21 // @ts-ignore
22 import useAlertStore from "@/store/useAlertStore";
23 import ButtonInput from '../Inputs/ButtonInput';
24 import Alert from '../Alert';
25 import { normalizeValue } from '../../utils/normalizeValue';
26 import { useEffect } from '@wordpress/element';
27
28 type FieldsProps = {
29 fields: any[];
30 onChange: (id: string, value: any) => void;
31 fieldStatus?: (id: string, success: boolean) => void;
32 };
33 /**
34 * Fields component that renders different field types based on the field configuration
35 * @param {Object} props Component props
36 * @param {Array} props.fields Array of field configurations
37 * @param {Function} props.onChange Callback function when field values change
38 * @param {Function} props.fieldStatus Callback function when success status of field changes
39 * @returns {JSX.Element|null} The rendered fields or null if no fields
40 */
41 const Fields = ({ fields, onChange, fieldStatus = () => {} }:FieldsProps ) => {
42 const {
43 getValue,
44 setValue,
45 isEdited,
46 settings,
47 } = useOnboardingStore();
48
49 const { getAlertState, setAlertState } = useAlertStore();
50
51 // Effect to set default values for fields that haven't been edited.
52 // This runs after the component renders, avoiding the "cannot update during render" warning.
53 useEffect(() => {
54 fields.forEach((field) => {
55 const isEditedField = isEdited(field.id);
56 const value = getValue(field.id);
57
58 if (!isEditedField && (value === undefined || value === null) && field.default !== undefined) {
59 const disabled = field.is_lock === true;
60 if (disabled) {
61 setValue(field.id, false);
62 } else {
63 setValue(field.id, field.default);
64 }
65 }
66 });
67 }, [fields, settings, isEdited, setValue, getValue]); // Re-run only when necessary
68
69 if (!fields) return null;
70
71 const fieldComponents: Record<string, any> = {
72 two_fa_validation: TwoFaValidation,
73 qr_code: QrCode,
74 backup_codes: BackupCodes,
75 license: License,
76 checkbox: Checkbox,
77 tracking_test: TrackingTest,
78 email: Email,
79 plugins: Plugins,
80 password: Password,
81 dropdown: Dropdown,
82 number: NumberInputWithControls,
83 multi_select: MultiSelectDropdown,
84 button: ButtonInput,
85 text: Text,
86 textarea: Textarea,
87 pricing: Pricing,
88 status: Status,
89 };
90
91 //the settings contain the values.
92 return (
93 <ErrorBoundary>
94 {fields.map((field) => {
95 // 1) Evaluate visible_if (if present)
96 if (field.visible_if && field.visible_if.field) {
97 const cond = field.visible_if;
98
99 // Try to get the current value from the store
100 let currentValue = getValue(cond.field);
101
102 const normalizedCurrent = normalizeValue(currentValue);
103 const normalizedEquals = normalizeValue(cond.equals);
104
105 if (normalizedCurrent !== normalizedEquals) {
106 // Condition not met: skip rendering this field
107 return null;
108 }
109 }
110
111 // 2) Get the value from the store. Default values are now handled in the useEffect hook.
112 const value = getValue(field.id);
113 // Opt-in card layout for checkbox/switch fields. Any field that does not
114 // set `layout: 'card'` keeps its existing component, so legacy consumers
115 // are unaffected.
116 const isCheckboxCard = field.type === 'checkbox' && field.layout === 'card';
117 const Component = isCheckboxCard ? CheckboxCard : (fieldComponents[field.type] || null);
118
119 // 3) Special handling for "button" field type (externalAction)
120 if (field.type === 'button') {
121 const groupId = field.group_id;
122 const alertState = getAlertState(groupId);
123
124 const handleButtonClick = () => {
125 const externalActionName = field.externalAction;
126 const externalAction = (window as any).pluginOnboardingActions?.[externalActionName];
127
128 if (typeof externalAction === 'function') {
129 externalAction(
130 field,
131 settings,
132 (id: string, newState: any) => setAlertState(id, newState),
133 setValue
134 );
135 } else {
136 console.warn(`External action '${externalActionName}' not found.`);
137 setAlertState(groupId, {
138 responseMessage: `Action '${externalActionName}' is not implemented.`,
139 responseSuccess: false,
140 responseCode: 'danger',
141 isUpdating: false,
142 });
143 fieldStatus(field.id, false);
144 }
145 };
146
147 // Determine variant and message for Alert
148 const alertVariant = alertState.responseCode === 'loading'
149 ? 'loading'
150 : (alertState.responseCode === 'success' ? 'success' : 'danger');
151 const alertMessage = alertState.responseMessage;
152
153 return (
154 <div key={`${field.id}-wrapper`} className="!mt-6">
155 {field.actionType === 'connection_test' && alertState.responseMessage && (
156 <Alert
157 variant={alertVariant}
158 message={alertMessage}
159 className="mb-4"
160 />
161 )}
162 <ButtonInput
163 onClick={handleButtonClick}
164 btnVariant="secondary"
165 size="md"
166 className="w-full"
167 disabled={alertState.isUpdating}
168 >
169 {field.label}
170 </ButtonInput>
171 </div>
172 );
173 }
174
175 // 4) Common props for non-button fields
176 const commonProps = {
177 key: field.id,
178 field: field,
179 onChange: (val: any) => onChange(field.id, val),
180 fieldStatus: (success: boolean) => fieldStatus(field.id, success),
181 value: value,
182 };
183
184 return Component
185 ? <Component
186 {...commonProps}
187 />
188 : null;
189 })}
190 </ErrorBoundary>
191 );
192 };
193
194 export default Fields;