PluginProbe
UpStream: a Project Management Plugin for WordPress / trunk
UpStream: a Project Management Plugin for WordPress vtrunk
trunk 1.39.0 1.39.1 1.39.2 1.39.3 2.0.7 2.1.0
upstream / vendor / alledia / wordpress-plugin-framework / src / assets / jsx / admin-addons.jsx

admin-addons.jsx in UpStream: a Project Management Plugin for WordPress trunk, at vendor/alledia/wordpress-plugin-framework/src/assets/jsx/admin-addons.jsx

436 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Addons tabs class.
3 *
4 */
5 class AllexAddonsTabs extends React.Component {
6 /**
7 * Constructor.
8 *
9 * @param props
10 */
11 constructor (props) {
12 super(props);
13
14 // State
15 this.state = {
16 currentTab: this.props.currentTab
17 };
18
19 // Events
20 this.handleClick = this.handleClick.bind(this);
21 }
22
23 /**
24 * Handles the click event on tabs.
25 *
26 * @param e
27 */
28 handleClick (e) {
29 e.preventDefault();
30
31 this.setState({currentTab: e.target.dataset.tab});
32 this.props.parentTabClickHandler(e.target.dataset.tab);
33 }
34
35 /**
36 * Renders the element.
37 *
38 * @returns {*}
39 */
40 render () {
41
42 return (
43 <div className="nav-tab-wrapper">
44 {this.props.addonsCount > 0 ? (
45 <div>
46 <a href="#"
47 className={this.state.currentTab == 'installed' ? 'nav-tab nav-tab-active' : 'nav-tab'}
48 data-tab="installed"
49 onClick={this.handleClick}>
50
51 {allexContext.labels.installed}
52 </a>
53
54 <a href="#"
55 className={this.state.currentTab == 'missed' ? 'nav-tab nav-tab-active' : 'nav-tab'}
56 data-tab="missed"
57 onClick={this.handleClick}>
58
59 {allexContext.labels.browse_more}
60 </a>
61 </div>
62 ) : (null)}
63 </div>
64 );
65 }
66 }
67
68 /**
69 * Table of addons.
70 *
71 * @param {Array} addons
72 * @param {String} currentTab
73 * @param {String} nonce
74 * @param {String} pluginName
75 * @param {Int} addonsCount
76 * @param {Int} addonsCountTotal
77 */
78 class AllexAddonsTable extends React.Component {
79 /**
80 * The constructor.
81 *
82 * @param props
83 */
84 constructor (props) {
85 super(props);
86 }
87
88 /**
89 * Renders the element.
90 *
91 * @returns {*}
92 */
93 render () {
94 const rows = this.props.addons.map((addon, index) => {
95 // Check if the current addon belongs to the current tab, based on the state.
96 if (
97 (addon.isInstalled && this.props.currentTab === 'installed')
98 || (!addon.isInstalled && this.props.currentTab === 'missed')
99 ) {
100 return (<AllexAddonsRow key={'allex_addon_' + addon.slug} addon={addon}
101 currentTab={this.props.currentTab} nonce={this.props.nonce}
102 pluginName={this.props.pluginName}/>);
103 } else {
104 return null;
105 }
106 });
107
108 return (
109 <section id={'allex-addons-' + this.props.currentTab} className="allex-addons-container">
110 {this.props.addonsCount == this.props.addonsCountTotal ? (
111 <p className="notice allex-addons-all-installed">{allexContext.labels.all_plugins_installed}</p>
112 ) : (null)}
113
114 {rows}
115 </section>
116 );
117 }
118 }
119
120 /**
121 * Addons row class.
122 *
123 * @param {Int} index
124 * @param {Object} addon
125 * @param {String} currentTab
126 * @param {String} nonce
127 * @param {String} pluginName
128 */
129 class AllexAddonsRow extends React.Component {
130 /**
131 * The constructor.
132 *
133 * @param props
134 */
135 constructor (props) {
136 super(props);
137
138 // State
139 this.state = {
140 licenseKey: this.props.addon.licenseKey,
141 licenseStatus: this.props.addon.licenseStatus,
142 messages: [],
143 showForm: this.props.addon.licenseKey === '',
144 processing: false
145 };
146
147 // Events
148 this.onChangeLicenseKey = this.onChangeLicenseKey.bind(this);
149 this.localizeLicenseStatus = this.localizeLicenseStatus.bind(this);
150 this.showForm = this.showForm.bind(this);
151 this.hideForm = this.hideForm.bind(this);
152 this.activateLicenseKey = this.activateLicenseKey.bind(this);
153 this.addMessage = this.addMessage.bind(this);
154 this.focusInput = this.focusInput.bind(this);
155 }
156
157 /**
158 *
159 * @param status
160 *
161 * @returns {String}
162 */
163 localizeLicenseStatus (status) {
164 if (status !== null && status !== '' && typeof status === 'string') {
165 if (allexContext.labels['license_status_' + status]) {
166 return allexContext.labels['license_status_' + status];
167 }
168
169 return status;
170 }
171
172 return '';
173 }
174
175 /**
176 * Show the license key form
177 */
178 showForm () {
179 this.setState({
180 showForm: true,
181 messages: []
182 });
183 }
184
185 /**
186 * Hide the license key form
187 */
188 hideForm () {
189 this.setState({
190 showForm: false,
191 messages: []
192 });
193 }
194
195 /**
196 * Add a message to the state.
197 *
198 * @param messageText
199 */
200 addMessage (messageText) {
201 let messages = this.state.messages;
202
203 messages.push(messageText);
204
205 this.setState({messages: messages});
206 }
207
208 /**
209 * Set focus on the input.
210 */
211 focusInput () {
212 jQuery('article[data-slug="' + this.props.addon.slug + '"] input').focus().select();
213 }
214
215 /**
216 * Make a request to the system to activate the license key.
217 */
218 activateLicenseKey () {
219 let component = this;
220
221 jQuery.ajax({
222 type: 'POST',
223 url: ajaxurl,
224 data: {
225 action: 'allex_addon_license_validate',
226 key: this.state.licenseKey,
227 plugin_name: this.props.pluginName,
228 addon_name: this.props.addon.slug,
229 addon_edd_id: this.props.addon.eddId,
230 nonce: this.props.nonce
231 },
232 beforeSend: function (jqXHR, settings) {
233 component.setState({processing: true, messages: []});
234 },
235 success: function (response, textStatus, jqXHR) {
236 component.setState({
237 processing: false,
238 licenseStatus: response.license_status
239 });
240
241 // Error.
242 if (!response.success) {
243 component.focusInput();
244 component.addMessage(response.message);
245
246 return;
247 }
248
249 // Invalid licenses.
250 if (response.license_status !== 'valid') {
251 component.focusInput();
252 component.addMessage(component.localizeLicenseStatus(response.license_status));
253
254 return;
255 }
256
257 // Valid licenses.
258 if (response.license_status === 'valid') {
259 component.setState({showForm: false});
260
261 return;
262 }
263 },
264 error: function (jqXHR, textStatus, errorThrown) {
265 component.setState({processing: false});
266
267 // Error.
268 component.addMessage(textStatus + '. ' + allexContext.labels.contact_support);
269 }
270 });
271 }
272
273 /**
274 * Event triggered when a license key is added in the input field.
275 *
276 * @param e
277 */
278 onChangeLicenseKey (e) {
279 this.setState({
280 licenseKey: e.target.value,
281 licenseStatus: 'inactive'
282 });
283 }
284
285 /**
286 * Renders the element.
287 *
288 * @returns {*}
289 */
290 render () {
291 let messages = this.state.messages.map((message, index) => {
292 let key = this.props.addon.slug + '_' + index;
293
294 return (<li key={key}>{message}</li>);
295 });
296
297 let showForm = this.state.showForm && this.props.currentTab === 'installed';
298 let showKey = this.props.currentTab === 'installed';
299
300 let form = <div className="allex-addon-license-form">
301 <div>
302 <label>{allexContext.labels.license_key}</label>
303
304 <input
305 type="text"
306 size="40"
307 maxLength="32"
308 autoComplete="false"
309 placeholder={allexContext.labels.enter_license_key}
310 value={this.state.licenseKey}
311 onChange={this.onChangeLicenseKey}
312 disabled={this.state.processing ? 'disabled' : ''}/>
313
314 <button
315 type="button"
316 className="button activate"
317 onClick={this.activateLicenseKey}
318 disabled={this.state.processing ? 'disabled' : ''}>
319
320 {this.state.processing ? allexContext.labels.please_wait : allexContext.labels.activate}
321 </button>
322
323 {this.state.processing ? (
324 <div className="lds-dual-ring"></div>
325 ) : (
326 <i className="dashicons dashicons-no-alt"
327 onClick={this.hideForm}></i>
328 )}
329 </div>
330
331 {this.state.processing === false ? (
332 <ul className="allex-addon-messages">
333 {messages}
334 </ul>
335 ) : (null)}
336 </div>;
337
338 return (
339 <article data-slug={this.props.addon.slug}>
340 <i className={this.props.addon.iconClass}></i>
341
342 <header>
343 <h3>{this.props.addon.title}</h3>
344 <p>{this.props.addon.description}</p>
345 </header>
346
347 {showForm ? (form) : (null)}
348
349 {this.props.currentTab === 'installed' && !showForm ? (
350 <div className="allex-addon-license">
351 <label>{allexContext.labels.license_key}</label>
352 <code>{this.state.licenseKey}</code>
353 &nbsp;
354 <a href="#"
355 onClick={this.showForm}>{allexContext.labels.change}</a>
356
357
358 <div className="allex-addon-license-status">
359 {this.localizeLicenseStatus(this.state.licenseStatus)}
360 </div>
361 </div>
362 ) : (null)}
363 </article>
364 );
365 }
366 }
367
368 /**
369 * Addons container class.
370 *
371 * @param {String} pluginName
372 * @param {Int} addonsCount
373 * @param {Int} addonsCountTotal
374 * @param {String} browseMoreUrl
375 * @param {Array} addons
376 * @param {String} nonce
377 *
378 */
379 class AllexAddonsContainer extends React.Component {
380 /**
381 * Constructor.
382 *
383 * @param props
384 */
385 constructor (props) {
386 super(props);
387
388 // State
389 this.state = {
390 currentTab: this.props.addonsCount > 0 ? 'installed' : 'missed'
391 };
392
393 // Events
394 this.handleTabClick = this.handleTabClick.bind(this);
395 }
396
397 /**
398 * Event called by the child tabs' click event.
399 *
400 * @param currentTab
401 */
402 handleTabClick (currentTab) {
403 this.setState({currentTab: currentTab});
404 }
405
406 /**
407 * Renders the element.
408 *
409 * @returns {*}
410 */
411 render () {
412 return (
413 <div id="allex-addons-table" className={this.props.pluginName}>
414 <AllexAddonsTabs
415 addonsCount={this.props.addonsCount}
416 addonsCountTotal={this.props.addonsCountTotal}
417 currentTab={this.state.currentTab}
418 parentTabClickHandler={this.handleTabClick}>
419 </AllexAddonsTabs>
420
421 {this.state.currentTab == 'missed' ? (
422 <div className="allex-addons-table-header">
423 <a href={this.props.browseMoreUrl} className="button button-primary" target="_blank">
424 {allexContext.labels.get_plugins}
425 </a>
426 </div>
427 ) : (null)}
428
429 <AllexAddonsTable addons={this.props.addons} currentTab={this.state.currentTab} nonce={this.props.nonce}
430 pluginName={this.props.pluginName} addonsCount={this.props.addonsCount}
431 addonsCountTotal={this.props.addonsCountTotal}/>
432 </div>
433 );
434 }
435 }
436