Extension_ImageService_Widget.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /**
  2. * W3TC image service widgets Google Charts driver.
  3. *
  4. * @file Google Charts driver for W3TC dashboard image service widget.
  5. * @author W3TC.
  6. * @version 1.0
  7. * @since 2.7.0
  8. */
  9. jQuery( document ).ready(
  10. function() {
  11. google.charts.load( 'current', { packages: ['corechart', 'gauge'] } );
  12. google.charts.setOnLoadCallback( load );
  13. setInterval(load, 60000); // Refresh charts every 60 seconds
  14. jQuery(window).resize(load); // Redraw charts after resize
  15. // Load method for image service charts. Fires on document ready, window resize, and on 60 second interval.
  16. function load() {
  17. processed_data = preprocess_data( w3tc_webp_data );
  18. draw_charts( processed_data );
  19. }
  20. // Preprocesses statistics data for chart use.
  21. /**
  22. * @param {array} data Image Service data.
  23. * @returns {array} Image Service data in format required for Google charts.
  24. */
  25. function preprocess_data( data ) {
  26. var processed_data = {
  27. 'counts': {
  28. 'data': [
  29. [ 'Converted', Number(data.counts.data['converted']),data.counts.data['convertedbytes'] ],
  30. [ 'Not Converted', Number(data.counts.data['notconverted']),data.counts.data['notconvertedbytes'] ],
  31. [ 'Processing', Number(data.counts.data['processing']),data.counts.data['processingbytes'] ],
  32. [ 'Sending', Number(data.counts.data['sending']),data.counts.data['sendingbytes'] ],
  33. [ 'Unconverted', Number(data.counts.data['unconverted']),data.counts.data['unconvertedbytes'] ]
  34. ],
  35. 'type': data.counts.type
  36. },
  37. 'apihourly': {
  38. 'data': [
  39. [ 'Hourly', Number( data.api.data['usage_hourly'] ) ]
  40. ],
  41. 'limit': Number( data.api.data['limit_hourly'] ),
  42. 'type': data.api.type
  43. }
  44. };
  45. // Monthly data is only present for free users as pro is unlimited monthly usage.
  46. if( 'limit_monthly' in data.api.data ) {
  47. processed_data['apimonthly'] = {
  48. 'data': [
  49. [ 'Monthly', Number( data.api.data['usage_monthly'] ) ]
  50. ],
  51. 'limit': Number( data.api.data['limit_monthly'] ),
  52. 'type': data.api.type
  53. };
  54. }
  55. return processed_data;
  56. }
  57. // Draws the stats charts.
  58. /**
  59. * @param {array} data - Preprocessed Image Service data.
  60. */
  61. function draw_charts( data ) {
  62. for ( var key in data ) {
  63. if ( data[key]['type'] === 'pie' && document.getElementById( key + '_chart' ) ) {
  64. var chart_data = new google.visualization.DataTable();
  65. // Add columns for the chart data
  66. chart_data.addColumn( 'string', 'Status' );
  67. chart_data.addColumn( 'number', 'Count' );
  68. chart_data.addColumn( { type: 'string', role: 'tooltip', 'p': { 'html': true } } );
  69. chart_data.addColumn( 'number', 'Bytes' );
  70. // Add rows for the chart data
  71. data[key]['data'].forEach( function ( row ) {
  72. chart_data.addRow( [ row[0], row[1], generateTooltip( row[0], row[1], row[2]), row[2] ] );
  73. });
  74. var chart_options = {
  75. chartArea: { width: '100%', height: '100%', top: 8, bottom: 40 },
  76. legend: { position: 'bottom' },
  77. tooltip: { isHtml: true }
  78. };
  79. var chart = new google.visualization.PieChart( document.getElementById( key + '_chart' ) );
  80. } else if( data[key]['type'] === 'gauge' ) {
  81. if( document.getElementById( key + '_chart' ) === null ) {
  82. jQuery( '#api_charts' ).append( '<div id="' + key + '_chart"></div>' );
  83. }
  84. var chart_data = google.visualization.arrayToDataTable( data[key]['data'], true );
  85. var yellow_from, yellow_to, red_from;
  86. if ( data[key]['limit'] > 100 && data[key]['limit'] <= 1000 ) {
  87. yellow_from = data[key]['limit'] - 200;
  88. yellow_to = data[key]['limit'] - 100;
  89. red_from = data[key]['limit'] - 100;
  90. } else if ( data[key]['limit'] > 1000 ) {
  91. yellow_from = data[key]['limit'] - 2000;
  92. yellow_to = data[key]['limit'] - 1000;
  93. red_from = data[key]['limit'] - 1000;
  94. } else {
  95. yellow_from = data[key]['limit'] - 20;
  96. yellow_to = data[key]['limit'] - 10;
  97. red_from = data[key]['limit'] - 10;
  98. }
  99. var chart_options = {
  100. legend: { position: 'bottom' },
  101. max: data[key]['limit'],
  102. yellowFrom: yellow_from,
  103. yellowTo: yellow_to,
  104. redFrom: red_from,
  105. redTo: data[key]['limit'],
  106. minorTicks: 5
  107. };
  108. var chart = new google.visualization.Gauge( document.getElementById( key + '_chart' ) );
  109. }
  110. chart.draw( chart_data, chart_options );
  111. };
  112. }
  113. // Function to generate custom tooltip with count and bytes
  114. function generateTooltip( dataType, count, bytes ) {
  115. return `<div style="padding:10px;"><span><strong>Type:</strong> ${dataType}</span><br/><span><strong>Count:</strong> ${count}</span><br/><span><strong>Bytes:</strong> ${formatBytes(bytes)}</span></div>`;
  116. }
  117. // Formats a timestamp into a human readable string.
  118. /**
  119. * @param {Object} d Timestamp.
  120. * @returns {string} Human readable date/time string.
  121. */
  122. function dateFormat( d ){
  123. return ( "0" + d.getUTCHours() ).slice( -2 ) + ":" + ( "0" + d.getUTCMinutes() ).slice( -2 );
  124. }
  125. // Formats bytes into a human readable string.
  126. /**
  127. * @param {Number} x Bytes.
  128. * @returns {string} Human readable string.
  129. */
  130. function formatBytes( x ){
  131. const units = [ 'bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ];
  132. let l = 0, n = parseInt(x, 10) || 0;
  133. while( n >= 1000 && ++l ){
  134. n = n/1000;
  135. }
  136. return( n.toFixed( n < 10 && l > 0 ? 1 : 0 ) + ' ' + units[l] );
  137. }
  138. // Time since last refresh.
  139. var seconds_timer_id;
  140. // Interval for the image service data refresh.
  141. /**
  142. * @param {Number} new_seconds_till_refresh Interval to trigger refresh.
  143. */
  144. function setRefresh( new_seconds_till_refresh ) {
  145. clearTimeout( seconds_timer_id );
  146. var seconds_till_refresh = new_seconds_till_refresh;
  147. seconds_timer_id = setInterval(
  148. function () {
  149. seconds_till_refresh--;
  150. if ( seconds_till_refresh <= 0 ) {
  151. clearInterval( seconds_timer_id ); // Change clearTimeout to clearInterval here
  152. seconds_timer_id = null;
  153. load();
  154. setRefresh( new_seconds_till_refresh ); // Restart the timer after calling load()
  155. return;
  156. }
  157. },
  158. 1000
  159. );
  160. }
  161. }
  162. );