PluginProbe
ElasticPress / 5.0.2
ElasticPress v5.0.2
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / assets / js / features / components / control.js

control.js in ElasticPress 5.0.2, at assets/js/features/components/control.js

254 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WordPress dependencies.
3 */
4 import {
5 CheckboxControl,
6 FormTokenField,
7 Notice,
8 RadioControl,
9 SelectControl,
10 TextControl,
11 TextareaControl,
12 ToggleControl,
13 } from '@wordpress/components';
14 import { safeHTML } from '@wordpress/dom';
15 import { RawHTML, WPElement } from '@wordpress/element';
16 import { __, sprintf } from '@wordpress/i18n';
17
18 /**
19 * Internal dependencies.
20 */
21 import { useFeatureSettings } from '../provider';
22
23 /**
24 * Control component.
25 *
26 * @param {object} props Component props.
27 * @param {boolean} props.disabled Whether the control is disabled.
28 * @param {string} props.help Control help text.
29 * @param {string} props.label Control label.
30 * @param {string} props.name Setting name.
31 * @param {Function} props.onChange Change event handler.
32 * @param {Array|null} props.options (optional) Control options.
33 * @param {false|string} props.requiresFeature Any feature required by this setting.
34 * @param {boolean} props.requiresSync Whether setting changes require a sync.
35 * @param {boolean|string} props.syncedValue Setting value at last sync.
36 * @param {string} props.type Control type.
37 * @param {boolean|string} props.value Setting value.
38 * @returns {WPElement} Reports component.
39 */
40 export default ({
41 disabled,
42 help,
43 label,
44 name,
45 onChange,
46 options,
47 requiresFeature,
48 requiresSync,
49 syncedValue,
50 type,
51 value,
52 }) => {
53 const { getFeature, isBusy, settings, willSettingRequireSync } = useFeatureSettings();
54
55 /**
56 * Help text formatted to allow safe HTML.
57 */
58 const helpHtml = help ? (
59 <span dangerouslySetInnerHTML={{ __html: safeHTML(help) }} /> // eslint-disable-line react/no-danger
60 ) : null;
61
62 /**
63 * Options formatted for radio controls to allow safe HTML in labels.
64 */
65 const radioOptions = options
66 ? options.map((o) => {
67 return {
68 value: o.value,
69 label: <span dangerouslySetInnerHTML={{ __html: safeHTML(o.label) }} />, // eslint-disable-line react/no-danger
70 };
71 })
72 : [];
73
74 /**
75 * The feature required by this setting, if any.
76 */
77 const requiredFeature =
78 requiresFeature && settings[requiresFeature]?.active !== true
79 ? getFeature(requiresFeature)
80 : false;
81
82 /**
83 * The notice to display if a feature is required.
84 */
85 const requiredFeatureNotice =
86 name === 'active'
87 ? /* translators: Feature name */
88 __('The %s feature must be enabled to use this feature.', 'elasticpress')
89 : /* translators: Feature name */
90 __('The %s feature must be enabled to use the following setting.', 'elasticpress');
91
92 /**
93 * The notice to display if a sync is required.
94 */
95 const syncNotice =
96 name === 'active'
97 ? __('Enabling this feature requires re-syncing your content.', 'elasticpress')
98 : __('A change to following setting requires re-syncing your content.', 'elasticpress');
99
100 /**
101 * Whether the control is disabled.
102 */
103 const isDisabled = isBusy || disabled || requiredFeature;
104
105 /**
106 * Whether the selected value for this setting will require a sync.
107 */
108 const willRequireSync = willSettingRequireSync(value, syncedValue, requiresSync);
109
110 /**
111 * Handle change to checkbox values.
112 *
113 * @param {boolean} checked Whether checkbox is checked.
114 */
115 const onChangeCheckbox = (checked) => {
116 const value = checked ? '1' : '0';
117
118 onChange(value);
119 };
120
121 /**
122 * Handle change to token field values.
123 *
124 * The FormTokenField control does not support separate values and labels,
125 * so whenever a change is made we need to set the field value based on the
126 * selected label.
127 *
128 * @param {string[]} values Selected values.
129 */
130 const onChangeFormTokenField = (values) => {
131 const value = values
132 .map((v) => options.find((o) => o.label === v)?.value)
133 .filter(Boolean)
134 .join(',');
135
136 onChange(value);
137 };
138
139 return (
140 <>
141 {requiredFeature ? (
142 <Notice isDismissible={false} status={name === 'active' ? 'error' : 'warning'}>
143 {sprintf(requiredFeatureNotice, requiredFeature.shortTitle)}
144 </Notice>
145 ) : null}
146 {willRequireSync ? (
147 <Notice isDismissible={false} status="warning">
148 {syncNotice}
149 </Notice>
150 ) : null}
151 <div className="ep-dashboard-control">
152 {(() => {
153 switch (type) {
154 case 'checkbox': {
155 return (
156 <CheckboxControl
157 checked={value === '1'}
158 help={helpHtml}
159 label={label}
160 onChange={onChangeCheckbox}
161 disabled={isDisabled}
162 />
163 );
164 }
165 case 'hidden': {
166 return null;
167 }
168 case 'markup': {
169 return <RawHTML>{safeHTML(label)}</RawHTML>;
170 }
171 case 'multiple': {
172 const suggestions = options.map((o) => o.label);
173 const values = value
174 .split(',')
175 .map((v) => options.find((o) => o.value === v)?.label)
176 .filter(Boolean);
177
178 return (
179 <FormTokenField
180 __experimentalExpandOnFocus
181 __experimentalShowHowTo={false}
182 label={label}
183 onChange={onChangeFormTokenField}
184 disabled={isDisabled}
185 suggestions={suggestions}
186 value={values}
187 />
188 );
189 }
190 case 'radio': {
191 return (
192 <RadioControl
193 help={helpHtml}
194 label={label}
195 onChange={onChange}
196 options={radioOptions}
197 disabled={isDisabled}
198 selected={value}
199 />
200 );
201 }
202 case 'select': {
203 return (
204 <SelectControl
205 help={helpHtml}
206 label={label}
207 onChange={onChange}
208 options={options}
209 disabled={isDisabled}
210 value={value}
211 />
212 );
213 }
214 case 'toggle': {
215 return (
216 <ToggleControl
217 checked={value}
218 help={helpHtml}
219 label={label}
220 onChange={onChange}
221 disabled={isDisabled}
222 />
223 );
224 }
225 case 'textarea': {
226 return (
227 <TextareaControl
228 help={helpHtml}
229 label={label}
230 onChange={onChange}
231 disabled={isDisabled}
232 value={value}
233 />
234 );
235 }
236 default: {
237 return (
238 <TextControl
239 help={helpHtml}
240 label={label}
241 onChange={onChange}
242 disabled={isDisabled}
243 value={value}
244 type={type}
245 />
246 );
247 }
248 }
249 })()}
250 </div>
251 </>
252 );
253 };
254