PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.26
Advanced Ads – Ad Manager & AdSense v2.0.26
2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / src / admin / components / FileUploaderField.jsx
advanced-ads / src / admin / components Last commit date
Accordion.jsx 1 month ago Card.jsx 1 month ago CardSkeleton.jsx 1 month ago FileUploaderField.jsx 1 month ago SearchComboBox.jsx 1 month ago
FileUploaderField.jsx
161 lines
1 /**
2 * External Dependencies
3 */
4 import { Upload } from 'lucide-react';
5
6 /**
7 * Internal Dependencies
8 */
9 import { useFileUploader } from '../hooks/useFileUploader';
10
11 export function FileUploaderField( {
12 maxFiles = 5,
13 maxSizeMB = 5,
14 allowedExt = [ 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt', 'docx', 'log' ],
15 label = 'Drag & drop files or <strong>click to browse</strong>',
16 uploaderRef = null, // pass a ref if parent needs { selectedFiles, reset }
17 } ) {
18 const {
19 selectedFiles,
20 errors,
21 atLimit,
22 processFiles,
23 deleteFile,
24 reset,
25 meta,
26 } = useFileUploader( { maxFiles, maxSizeMB, allowedExt } );
27
28 // Only expose selectedFiles + reset to the parent form via ref
29 // Do NOT destructure and store the whole hook return — it goes stale
30 if ( uploaderRef ) {
31 uploaderRef.current = { selectedFiles, reset };
32 }
33
34 function handleDragOver( e ) {
35 e.preventDefault();
36 if ( ! atLimit ) {
37 e.currentTarget.classList.add( 'dragover' );
38 }
39 }
40 function handleDragLeave( e ) {
41 e.currentTarget.classList.remove( 'dragover' );
42 }
43 function handleDrop( e ) {
44 e.preventDefault();
45 e.currentTarget.classList.remove( 'dragover' );
46 processFiles( e.dataTransfer.files );
47 }
48 function handleChange( e ) {
49 processFiles( e.target.files );
50 e.target.value = ''; // allow re-selecting the same file
51 }
52
53 const count = selectedFiles.length;
54 const acceptAttr = meta.allowedExt.map( ( e ) => '.' + e ).join( ',' );
55
56 return (
57 <div
58 id="attachments-container"
59 className="advads-field-input advads-file-uploader"
60 >
61 { /* Drop zone */ }
62 <div
63 id="attachments-drop-zone"
64 className={ `dropzone${ atLimit ? ' limit-reached' : '' }` }
65 onDragOver={ handleDragOver }
66 onDragLeave={ handleDragLeave }
67 onDrop={ handleDrop }
68 >
69 <Upload className="size-8 mb-4" />
70
71 <p
72 className="text-sm mt-0 mb-2"
73 dangerouslySetInnerHTML={ { __html: label } }
74 />
75
76 <input
77 id="attachments"
78 type="file"
79 multiple
80 accept={ acceptAttr }
81 onChange={ handleChange }
82 />
83
84 { /* Hints */ }
85 <div className="upload-hints">
86 <div>
87 <strong>Allowed:</strong>{ ' ' }
88 { meta.allowedExt.map( ( e ) => '.' + e ).join( ', ' ) }
89 </div>
90 <span>
91 <strong>Max size:</strong> { meta.maxSizeMB } MB per
92 file
93 </span>
94 <span>
95 <strong>Max files:</strong> { meta.maxFiles }
96 </span>
97 </div>
98 </div>
99
100 { /* Count badge */ }
101 { count > 0 && (
102 <div
103 className={ `file-count-badge${
104 atLimit ? ' at-limit' : ''
105 }` }
106 >
107 { count } / { meta.maxFiles } file{ count !== 1 ? 's' : '' }{ ' ' }
108 selected
109 </div>
110 ) }
111
112 { /* Errors */ }
113 { errors.length > 0 && (
114 <div className="error-box">
115 <p className="error-box-title">Some files were rejected:</p>
116 <ul className="error-list">
117 { errors.map( ( r, i ) => (
118 <li key={ i }>
119 <strong>{ r.name }</strong>:{ ' ' }
120 { r.reasons.join( '; ' ) }
121 </li>
122 ) ) }
123 </ul>
124 </div>
125 ) }
126
127 { /* Selected files */ }
128 <div className="selected-files-container">
129 { selectedFiles.map( ( f ) => (
130 <div key={ f.id } className="file-item">
131 <div className="file-image">
132 { f.isImage ? (
133 <img src={ f.fileimage } alt="" />
134 ) : (
135 <i className="far fa-file-alt" />
136 ) }
137 </div>
138 <div className="file-detail">
139 <h6>{ f.filename }</h6>
140 <p>
141 <span>Size: { f.filesize }</span>
142 <span style={ { marginLeft: 10 } }>
143 Modified: { f.datetime }
144 </span>
145 </p>
146 <div className="file-actions">
147 <button
148 className="file-action-btn"
149 onClick={ () => deleteFile( f.id ) }
150 >
151 Delete
152 </button>
153 </div>
154 </div>
155 </div>
156 ) ) }
157 </div>
158 </div>
159 );
160 }
161