cubecart / v6

CubeCart Version 6
https://cubecart.com
71 stars 58 forks source link

Google Charts Tweak #3582

Closed bhsmither closed 5 days ago

bhsmither commented 2 months ago

In admin, Statistics, if any chart has no column that exceeds a very small value, that chart's range of values include negative numbers. This seems to be a default chart rendering behavior. While it is possible, however impractical, there could be a sum-total for a given column to equal a negative number.

In the demo store, in Statistics, Best Customers tab, this chart starts at 744.0. This also seems to be a default chart rendering behavior.

Suggest there be found a way to code the chart instructions to render the range of the chart to start at zero, always.

bhsmither commented 2 months ago

This is my tweak in dashboard.index.php:

            var data = google.visualization.arrayToDataTable([{/literal}{$CHART.data}{literal}]); var yMax; var columnRange = data.getColumnRange(1);if (columnRange.max < 20) { yMax = 20; }
            var options = {title: '{/literal}{$CHART.title}{literal}',width:'100%',height:300,vAxis:{title:'{/literal}{$CONFIG.default_currency}{literal}',viewWindowMode:'explicit',viewWindow:{min:0,max:yMax}}};
abrookbanks commented 2 months ago

Hmm from my testing:

data.getColumnRange(1)

Always returns:

{min: 0, max: 0}

abrookbanks commented 2 months ago
data.getColumnRange(2);

does the job though.

bhsmither commented 2 months ago

I do not yet know what getColumnRange() actually looks at. Obviously, the argument represents something to discriminate one aspect from another.

I have changed my charts from the stock 'line' graphs to 'column' graphs. Maybe that's the difference?

abrookbanks commented 2 months ago

Expect so.

bhsmither commented 2 months ago

Further research on the API shows that the argument to getColumnRange() is the column number, zero-based, but the zeroeth column is used for the chart legends.

In your experiment, does column 2 (third array element, 'Feb') have a non-zero value, where column 1 (second array element, 'Jan') have zero values?

My initial experiments were not comprehensive enough. My next experiment is to iterate over the columns and return the highest value rounded up to something reasonable. (Reminder: The viewWindow option requires both min and max.)

bhsmither commented 2 months ago

Observe:

[
  ['Month', '2024', '2023'],
  ['Jan',  0, 0],
  ['Feb',  0, 120.40],
  ['Mar',  0, 0],
  ['Apr',  0, 0],
  ['May',  0, 0],
  ['Jun',  0, 523.48],
  ['Jul',  0, 246.09],
  ['Aug',  0, 0],
  ['Sep',  0, 0],
  ['Oct',  0, 0],
  ['Nov',  0, 0],
  ['Dec',  0, 0],
]

The getColumnRange(2) is looking at the right-most column - which for the above table, would be 120.40 to 523.48.

So, the next experiment will iterate over the cells (cols 1-getNumberOfColumns(), rows 0-getNumberOfRows()), looking for the highest value. (The top-most row is not counted in getNumberOfRows() because a default parameter says the first row in the table is a 'header' row, not a 'data' row.)

bhsmither commented 1 month ago

This is my solution:

In /admin/skins/default/templates/dashboard.index.php, near line 21, find:

            var options = {title: '{/literal}{$CHART.title}{literal}',width:'100%',height:300};

Change to:

            var yMax = 0, gNOR = data.getNumberOfRows(), gNOC = data.getNumberOfColumns();
            for(var x = 1; x < gNOC; x++) {
              for(var y = 0; y < gNOR; y++) {
                yMax = Math.max(data.getValue(y,x), yMax);
              }
            }

            var log10yMax = Math.log10(yMax);
            var floorexp = Math.floor(log10yMax);
            var normyMax = yMax/Math.pow(10,floorexp);
            var ceilnormyMax = Math.ceil(normyMax);
            yMax = ceilnormyMax * Math.pow(10,floorexp);

            if (yMax < 20 || isNaN(yMax)) { yMax = 20; }
            var options = {
              title: '{/literal}{$CHART.title}{literal}',
              width:'100%',
              height:300,
              vAxis:{
                title:'{/literal}{$CONFIG.default_currency}{literal}',
                viewWindowMode:'explicit',
                viewWindow:{min:0,max:yMax}
              }
            };

In /admin/skins/default/templates/statistics.index.php, near lines 261-265, find:

     var options = {
       title: chart_title.innerHTML,
       hAxis: {title: chart_hAxis.innerHTML},
       vAxis: {title: chart_vAxis.innerHTML}
     };

Change to:

     var yMax = 0, gNOR = data.getNumberOfRows(), gNOC = data.getNumberOfColumns();
     for(var x = 1; x < gNOC; x++) {
       for(var y = 0; y < gNOR; y++) {
         yMax = Math.max(data.getValue(y,x), yMax);
       }
     }

     var log10yMax = Math.log10(yMax);
     var floorexp = Math.floor(log10yMax);
     var normyMax = yMax/Math.pow(10,floorexp);
     var ceilnormyMax = Math.ceil(normyMax);
     yMax = ceilnormyMax * Math.pow(10,floorexp);

     if (yMax < 20 || isNaN(yMax)) { yMax = 20; }

     var options = {
       title: chart_title.innerHTML,
       hAxis: {title: chart_hAxis.innerHTML},
       vAxis: {title: chart_vAxis.innerHTML,viewWindowMode:'explicit',viewWindow:{min:0,max:yMax}}
     };
abrookbanks commented 5 days ago

Thanks this works well.