PluginProbe
WebberZone Top 10 — Popular Posts / 4.5.2
WebberZone Top 10 — Popular Posts v4.5.2
4.5.2 4.5.1 4.5.0 4.4.3 4.4.2 4.4.1 4.4.0 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 trunk 1.0 1.0.1 1.1 1.2 1.3 1.4 1.4.1 1.5 1.5.1 1.5.2 1.5.3 1.6 All 118 releases
top-10 / includes / frontend / blocks / src / post-count / controls.js

controls.js in WebberZone Top 10 — Popular Posts 4.5.2, at includes/frontend/blocks/src/post-count/controls.js

395 lines 9.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 BlockControls,
6 AlignmentControl,
7 InspectorControls,
8 } from '@wordpress/block-editor';
9 import {
10 PanelBody,
11 SelectControl,
12 Button,
13 Modal,
14 TextControl,
15 ToggleControl,
16 Popover,
17 DatePicker,
18 TextareaControl,
19 } from '@wordpress/components';
20 import { __ } from '@wordpress/i18n';
21 import { useState } from '@wordpress/element';
22
23 import { svgOptions } from './components/svg';
24 import PaddingControl from './components/padding-control';
25 import UnitControl from './components/unit-control';
26
27 const Controls = ( { attributes, setAttributes } ) => {
28 const {
29 textAlign,
30 counter,
31 fromDate,
32 toDate,
33 textBefore,
34 textAfter,
35 advancedMode,
36 textAdvanced,
37 numberFormat,
38 svgCode,
39 svgIconLocation,
40 svgIconSize,
41 svgIconSizeUnit,
42 } = attributes;
43 const [ isFromDatePickerVisible, setIsFromDatePickerVisible ] =
44 useState( false );
45 const [ isToDatePickerVisible, setIsToDatePickerVisible ] =
46 useState( false );
47 const [ isSvgModalOpen, setIsSvgModalOpen ] = useState( false );
48
49 const formatDate = ( date ) => {
50 if ( ! date ) {
51 return '';
52 }
53 const d = new Date( date );
54 return d.toISOString().split( 'T' )[ 0 ];
55 };
56
57 const handleDateChange = ( date, isFromDate ) => {
58 const formattedDate = formatDate( date );
59 setAttributes( {
60 [ isFromDate ? 'fromDate' : 'toDate' ]: formattedDate,
61 } );
62 setIsFromDatePickerVisible( false );
63 setIsToDatePickerVisible( false );
64 };
65
66 const clearDate = ( isFromDate ) => {
67 setAttributes( { [ isFromDate ? 'fromDate' : 'toDate' ]: '' } );
68 };
69
70 const handleSvgSelection = ( selectedSvg ) => {
71 setAttributes( { svgCode: selectedSvg } );
72 setIsSvgModalOpen( false );
73 };
74 const clearSvg = () => {
75 setAttributes( { svgCode: '' } );
76 };
77
78 return (
79 <>
80 <BlockControls group="block">
81 <AlignmentControl
82 value={ textAlign }
83 onChange={ ( nextAlign ) => {
84 setAttributes( { textAlign: nextAlign } );
85 } }
86 />
87 </BlockControls>
88 <InspectorControls>
89 <PanelBody
90 title={ __( 'Counter Settings', 'top-10' ) }
91 initialOpen={ true }
92 >
93 <SelectControl
94 label={ __( 'Counter Type', 'top-10' ) }
95 value={ counter }
96 options={ [
97 { label: __( 'Total', 'top-10' ), value: 'total' },
98 { label: __( 'Daily', 'top-10' ), value: 'daily' },
99 ] }
100 onChange={ ( value ) =>
101 setAttributes( { counter: value } )
102 }
103 />
104 { counter === 'daily' && (
105 <>
106 <div className="tptn-date-picker-container">
107 <span className="tptn-date-picker-label">
108 { __( 'From', 'top-10' ) }
109 </span>
110 <Button
111 onClick={ () =>
112 setIsFromDatePickerVisible(
113 ( state ) => ! state
114 )
115 }
116 variant="secondary"
117 >
118 { fromDate ||
119 __( 'Select From Date', 'top-10' ) }
120 </Button>
121 { fromDate && (
122 <Button
123 onClick={ () => clearDate( true ) }
124 variant="link"
125 isDestructive
126 >
127 { __( 'Clear', 'top-10' ) }
128 </Button>
129 ) }
130 { isFromDatePickerVisible && (
131 <Popover
132 onClose={ () =>
133 setIsFromDatePickerVisible( false )
134 }
135 >
136 <DatePicker
137 currentDate={ fromDate }
138 onChange={ ( date ) =>
139 handleDateChange( date, true )
140 }
141 />
142 </Popover>
143 ) }
144 </div>
145
146 <div className="tptn-date-picker-container">
147 <span className="tptn-date-picker-label">
148 { __( 'To', 'top-10' ) }
149 </span>
150 <Button
151 onClick={ () =>
152 setIsToDatePickerVisible(
153 ( state ) => ! state
154 )
155 }
156 variant="secondary"
157 >
158 { toDate ||
159 __( 'Select To Date', 'top-10' ) }
160 </Button>
161 { toDate && (
162 <Button
163 onClick={ () => clearDate( false ) }
164 variant="link"
165 isDestructive
166 >
167 { __( 'Clear', 'top-10' ) }
168 </Button>
169 ) }
170 { isToDatePickerVisible && (
171 <Popover
172 onClose={ () =>
173 setIsToDatePickerVisible( false )
174 }
175 >
176 <DatePicker
177 currentDate={ toDate }
178 onChange={ ( date ) =>
179 handleDateChange( date, false )
180 }
181 />
182 </Popover>
183 ) }
184 </div>
185 </>
186 ) }
187 <ToggleControl
188 label={ __( 'Number Formatting', 'top-10' ) }
189 checked={ numberFormat }
190 onChange={ ( value ) =>
191 setAttributes( { numberFormat: value } )
192 }
193 />
194 </PanelBody>
195
196 <PanelBody
197 title={ __( 'Text Customization', 'top-10' ) }
198 initialOpen={ true }
199 >
200 <ToggleControl
201 label={ __( 'Advanced Mode', 'top-10' ) }
202 checked={ advancedMode }
203 onChange={ ( value ) =>
204 setAttributes( { advancedMode: value } )
205 }
206 />
207
208 { ! advancedMode && (
209 <>
210 <TextControl
211 label={ __( 'Text Before Count', 'top-10' ) }
212 value={ textBefore }
213 onChange={ ( value ) =>
214 setAttributes( { textBefore: value } )
215 }
216 />
217 <TextControl
218 label={ __( 'Text After Count', 'top-10' ) }
219 value={ textAfter }
220 onChange={ ( value ) =>
221 setAttributes( { textAfter: value } )
222 }
223 />
224 </>
225 ) }
226
227 { advancedMode && (
228 <TextareaControl
229 label={ __( 'Advanced Text', 'top-10' ) }
230 value={ textAdvanced }
231 onChange={ ( value ) =>
232 setAttributes( { textAdvanced: value } )
233 }
234 // translators: %totalcount% and %dailycount% are literal block placeholders.
235 help={ __(
236 'Use %totalcount% or %dailycount% as placeholders for the count value.',
237 'top-10'
238 ) }
239 />
240 ) }
241 </PanelBody>
242
243 <PanelBody
244 title={ __( 'Icon', 'top-10' ) }
245 initialOpen={ true }
246 >
247 <div
248 style={ {
249 display: 'flex',
250 alignItems: 'center',
251 } }
252 >
253 <TextControl
254 label={ __( 'Icon SVG HTML', 'top-10' ) }
255 value={ svgCode }
256 onChange={ ( value ) =>
257 setAttributes( { svgCode: value } )
258 }
259 />
260 </div>
261 <div
262 style={ {
263 display: 'flex',
264 justifyContent: 'space-between',
265 marginBottom: '10px',
266 } }
267 >
268 <Button
269 onClick={ () => setIsSvgModalOpen( true ) }
270 variant="secondary"
271 >
272 { __( 'Select SVG', 'top-10' ) }
273 </Button>
274 <Button
275 onClick={ clearSvg }
276 variant="secondary"
277 isDestructive
278 >
279 { __( 'Clear', 'top-10' ) }
280 </Button>
281 { svgCode && (
282 <div
283 style={ {
284 marginRight: '10px',
285 width: '30px',
286 height: '30px',
287 } }
288 dangerouslySetInnerHTML={ { __html: svgCode } }
289 />
290 ) }
291 </div>
292 <SvgSelectionModal
293 isOpen={ isSvgModalOpen }
294 onClose={ () => setIsSvgModalOpen( false ) }
295 onSelect={ handleSvgSelection }
296 />
297
298 { svgCode && (
299 <>
300 <SelectControl
301 label={ __( 'Icon Location', 'top-10' ) }
302 value={ svgIconLocation }
303 options={ [
304 {
305 value: 'before',
306 label: __( 'Before Text', 'top-10' ),
307 },
308 {
309 value: 'after',
310 label: __( 'After Text', 'top-10' ),
311 },
312 ] }
313 onChange={ ( newValue ) =>
314 setAttributes( {
315 svgIconLocation: newValue,
316 } )
317 }
318 help={
319 svgIconLocation === 'after'
320 ? __(
321 'Icon will be placed after the text.',
322 'top-10'
323 )
324 : __(
325 'Icon will be placed before the text.',
326 'top-10'
327 )
328 }
329 />
330 <UnitControl
331 label={ __( 'Icon Size', 'top-10' ) }
332 value={ svgIconSize }
333 unit={ svgIconSizeUnit }
334 onValueChange={ ( value ) =>
335 setAttributes( { svgIconSize: value } )
336 }
337 onUnitChange={ ( unit ) =>
338 setAttributes( { svgIconSizeUnit: unit } )
339 }
340 />
341 <PaddingControl
342 attributes={ attributes }
343 setAttributes={ setAttributes }
344 />
345 </>
346 ) }
347 </PanelBody>
348 </InspectorControls>
349 </>
350 );
351 };
352
353 export default Controls;
354
355 const SvgSelectionModal = ( { isOpen, onClose, onSelect } ) => {
356 return isOpen ? (
357 <Modal
358 title={ __( 'Select an SVG', 'top-10' ) }
359 onRequestClose={ onClose }
360 >
361 <div
362 style={ {
363 display: 'grid',
364 gridTemplateColumns: 'repeat(auto-fill, minmax(25px, 1fr))',
365 gap: '2px',
366 padding: '1px',
367 } }
368 >
369 { svgOptions.map( ( svg, index ) => (
370 <Button
371 key={ index }
372 onClick={ () => onSelect( svg.code ) }
373 style={ {
374 padding: '1px',
375 border: '0px solid #ddd',
376 display: 'flex',
377 justifyContent: 'center',
378 alignItems: 'center',
379 height: '25px',
380 } }
381 title={ svg.name }
382 >
383 <svg
384 viewBox="0 0 100 100"
385 xmlns="http://www.w3.org/2000/svg"
386 style={ { width: '100%', height: '100%' } }
387 dangerouslySetInnerHTML={ { __html: svg.code } }
388 />
389 </Button>
390 ) ) }
391 </div>
392 </Modal>
393 ) : null;
394 };
395