Bläddra i källkod

Switch chart library

Jordi Boggiano 9 år sedan
förälder
incheckning
62c4f696de

+ 48 - 2
src/Packagist/WebBundle/Resources/public/css/main.css

@@ -401,7 +401,6 @@ strong {
 
 .wrapper-search {
     background: #f28d1a;
-    border-bottom: 1px solid #ccc;
 }
 
 .wrapper-search .container {
@@ -456,7 +455,6 @@ footer p {
 
 #search-form input[type="search"] {
     background: #FFF;
-    box-shadow: 0 0 0 3px rgba(0,0,0,0.08);
     font: 18px 'Open Sans', sans-serif;
     border: 0;
     padding: 0px 10px;
@@ -1424,6 +1422,54 @@ ul.packages .metadata-block:last-child {
 }
 
 
+.chart {
+    min-height: 300px;
+}
+.version-stats-chart .chart {
+    min-height: 400px;
+}
+svg {
+    display: auto !important;
+    width: auto !important;
+    height: auto !important;
+}
+svg.chart {
+    display: block !important;
+    width:100% !important;
+    height:100% !important;
+    padding-left: 0;
+}
+@media (max-width: 767px) {
+  svg.chart {
+    margin-left: -10px;
+  }
+}
+.nvd3 text {
+  font: normal 12px 'Open Sans';
+}
+.nv-x text {
+  baseline-shift: -10px;
+}
+.nv-context .nv-x text {
+  baseline-shift: -5px;
+}
+.nvd3 .nv-axis .domain {
+  display: none;
+}
+.nvd3 .nv-axis .nv-axisMaxMin text {
+  font-weight: normal !important;
+}
+.nvd3 .nv-y .nv-axis .nv-axisMaxMin:last-child {
+  display: none;
+}
+.nvd3 .nv-x .nv-axis .nv-axisMaxMin:last-child text {
+  text-anchor: end !important;
+}
+.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
+  fill-opacity: 0 !important;
+  stroke-opacity: 0 !important;
+}
+
 @media (max-width: 1199px) {
     .publishing-packages {
         margin-top: 40px;

+ 84 - 54
src/Packagist/WebBundle/Resources/public/js/charts.js

@@ -2,68 +2,87 @@
     "use strict";
 
     var colors = [
-        'rgba(242, 141, 26, 1)',
-        'rgba(45, 45, 50, 1)'
+        '#f28d1a',
+        '#2d2d32'
     ];
 
-    Chart.defaults.global.responsive = true;
-    Chart.defaults.global.animationSteps = 10;
-    Chart.defaults.global.tooltipYPadding = 10;
-
-    function initPackagistChart(canvas, labels, values, scale, tooltips) {
-        var ctx = canvas.getContext("2d");
-        var data = {
-            labels: labels.map(function (val, index, arr) {
-                return index % Math.round(arr.length / 50) == 0 ? val : '';
-            }),
-            datasets: []
-        };
-        var scale = parseInt(scale, 10);
-        var scaleUnit = '';
-        switch (scale) {
-            case 1000:
-                scaleUnit = 'K';
-                break;
-            case 1000000:
-                scaleUnit = 'mio';
-                break;
+    function initPackagistChart(svg, labels, series, withDatePicker) {
+        var format = d3.time.format("%Y-%m-%d");
+        if (labels[0].match(/^\d+-\d+$/)) {
+            format = d3.time.format("%Y-%m");
         }
 
-        var opts = {
-            bezierCurve: false,
-            scaleLabel: " <%=value%>" + scaleUnit,
-            tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>" + scaleUnit,
-            pointDot: false
-        };
+        var chartData = [];
+        series.map(function (serie, index) {
+            var points = [];
+            labels.map(function (label, index) {
+                points.push({x: format.parse(label), y: parseInt(serie.values[index]) || 0});
+            })
+            chartData.push({
+                values: points,
+                key: serie.name,
+                color: colors[index]
+            });
+        })
 
-        if (!tooltips || labels.length > 50 || labels.length <= 2) {
-            opts.showTooltips = false;
+        if (withDatePicker && $(window).width() < 767) {
+            withDatePicker = false;
         }
 
-        for (var i = 0; i < values.length; i++) {
-            data.datasets.push(
-                {
-                    fillColor: "rgba(0,0,0,0)",
-                    strokeColor: colors[i],
-                    pointColor: colors[i],
-                    pointStrokeColor: "#fff",
-                    data: values[i].map(function (value) {
-                        return Math.round(parseInt(value, 10) / scale, 2);
-                    })
+        nv.addGraph(function() {
+            var chart;
+            if (withDatePicker) {
+                chart = nv.models.lineWithFocusChart();
+            } else {
+                chart = nv.models.lineChart();
+            }
+
+            function formatDate(a,b) {
+                if (!(a instanceof Date)) {
+                    a = new Date(a);
                 }
-            );
-        }
+                return format(a,b);
+            }
+            function formatDigit(a,b) {
+                if (a > 1000000) {
+                    return Math.round(a/1000000) + 'mio';
+                }
+                if (a > 1000) {
+                    return Math.round(a/1000) + 'K';
+                }
+                return a;
+            }
+
+            chart.xAxis.tickFormat(formatDate);
+            chart.yAxis.tickFormat(formatDigit);
+
+            if (withDatePicker) {
+                chart.x2Axis.tickFormat(formatDate);
+                chart.y2Axis.tickFormat(formatDigit);
+            }
+
+            d3.select(svg)
+                .datum(chartData)
+                .transition().duration(100)
+                .call(chart);
 
-        new Chart(ctx).Line(data, opts);
+            nv.utils.windowResize(chart.update);
+
+            return chart;
+        });
     };
 
-    $('canvas[data-labels]').each(function () {
+    $('svg[data-labels]').each(function () {
         initPackagistChart(
             this,
             $(this).attr('data-labels').split(','),
-            $(this).attr('data-values').split('|').map(function (values) { return values.split(','); }),
-            $(this).attr('data-scale'),
-            true
+            $(this).attr('data-values').split('|').map(function (values) {
+                values = values.split(':');
+                return {
+                    name: values[0],
+                    values: values[1].split(',')
+                };
+            })
         );
     });
 
@@ -73,10 +92,19 @@
             versionCache = {},
             ongoingRequest = false;
 
+        function initChart(type, res) {
+            initPackagistChart(
+                $('.js-'+type+'-dls')[0],
+                res.labels,
+                [{name: 'Daily Downloads', values: res.values}],
+                true
+            );
+        }
+
         $.ajax({
             url: statsUrl,
             success: function (res) {
-                initPackagistChart($('.js-all-dls')[0], res.labels, [res.values], Math.max.apply(res.values) > 10000 ? 1000 : 1, false);
+                initChart('all', res);
             }
         })
         function loadVersionChart(versionId) {
@@ -84,7 +112,7 @@
             $.ajax({
                 url: versionStatsUrl.replace('_VERSION_', versionId) + '?average=' + average + '&from=' + date,
                 success: function (res) {
-                    initPackagistChart($('.js-version-dls')[0], res.labels, [res.values], Math.max.apply(res.values) > 10000 ? 1000 : 1, false);
+                    initChart('version', res);
                     versionCache[versionId] = res;
                     ongoingRequest = false;
                 }
@@ -110,7 +138,7 @@
 
             if (versionCache[versionId]) {
                 res = versionCache[versionId];
-                initPackagistChart($('.js-version-dls')[0], res.labels, [res.values], Math.max.apply(res.values) > 10000 ? 1000 : 1, false);
+                initChart('version', res);
             } else {
                 if (ongoingRequest) {
                     return;
@@ -123,7 +151,10 @@
         });
 
         $(window).on('scroll', function () {
-            $('.version-stats-chart').css('top', Math.max(0, window.scrollY - $('.version-stats').offset().top + 80) + 'px');
+            var basePos = $('.version-stats').offset().top;
+            var footerPadding = $(document).height() - basePos - $('footer').height() - $('.version-stats-chart').height() - 50;
+            var headerPadding = 80;
+            $('.version-stats-chart').css('top', Math.max(0, Math.min(footerPadding, window.scrollY - basePos + headerPadding)) + 'px');
         });
 
         // initialize version list expander
@@ -131,8 +162,7 @@
         if (versionsList.offsetHeight < versionsList.scrollHeight) {
             $('.package .versions-expander').removeClass('hidden').on('click', function () {
                 $(this).addClass('hidden');
-                $(versionsList).css('overflow-y', 'visible')
-                    .css('max-height', 'inherit');
+                $(versionsList).css('max-height', 'inherit');
             });
         }
     };

+ 1 - 2
src/Packagist/WebBundle/Resources/public/js/view.js

@@ -171,8 +171,7 @@
     if (versionsList.offsetHeight < versionsList.scrollHeight) {
         $('.package .versions-expander').removeClass('hidden').on('click', function () {
             $(this).addClass('hidden');
-            $(versionsList).css('overflow-y', 'visible')
-                .css('max-height', 'inherit');
+            $(versionsList).css('max-height', 'inherit');
         });
     }
 

+ 15 - 7
src/Packagist/WebBundle/Resources/views/Package/stats.html.twig

@@ -45,18 +45,21 @@
             <h3>Daily installs{% if average != 'daily' %}, averaged {{ average }}{% endif %}</h3>
             <div class="row">
                 <div class="col-xs-12">
-                    <canvas class="js-all-dls" width="500" height="200">
-                        Sorry, the graph can't be displayed because your browser doesn't support &lt;canvas&gt; html element.
-                    </canvas>
+                    <svg class="chart js-all-dls" width="500" height="200">
+                        Sorry, the graph can't be displayed because your browser doesn't support &lt;svg&gt; html element.
+                    </svg>
                 </div>
             </div>
 
+            <br>
             <h3>Daily installs per version{% if average != 'daily' %}, averaged {{ average }}{% endif %}</h3>
             <div class="row package version-stats">
                 <div class="col-xs-12 col-md-9 version-stats-chart">
-                    <canvas class="js-version-dls" width="500" height="200">
-                        Sorry, the graph can't be displayed because your browser doesn't support &lt;canvas&gt; html element.
-                    </canvas>
+                    <div style="position: relative">
+                        <svg class="chart js-version-dls" width="500" height="200">
+                            Sorry, the graph can't be displayed because your browser doesn't support &lt;svg&gt; html element.
+                        </svg>
+                    </div>
                 </div>
                 {% include 'PackagistWebBundle:Web:versionList.html.twig' with {versions: versions, expandedId: expandedId} %}
             </div>
@@ -64,8 +67,13 @@
     </section>
 {% endblock %}
 
+{% block stylesheets %}
+    <link href="https://cdn.rawgit.com/novus/nvd3/v1.7.1/build/nv.d3.css" rel="stylesheet">
+{% endblock %}
+
 {% block scripts %}
-    <script src="{{ asset('js/libs/Chart.js/Chart.min.js') }}"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
+    <script src="https://cdn.rawgit.com/novus/nvd3/v1.7.1/build/nv.d3.min.js"></script>
     <script src="{{ asset('bundles/packagistweb/js/charts.js') }}"></script>
     <script>
         (function () {

+ 15 - 20
src/Packagist/WebBundle/Resources/views/Web/stats.html.twig

@@ -12,37 +12,27 @@
             <h3>Packages/versions over time</h3>
 
             <p class="row">
-                <canvas class="col-xs-12" width="500" height="200" data-labels="{{ chart.months|join(',') }}" data-scale="1000" data-values="{{ chart.versions|join(',') }}|{{ chart.packages|join(',') }}">
-                    Sorry, the graph can't be displayed because your browser doesn't support &lt;canvas&gt; html element.
-                </canvas>
+                <svg class="chart col-xs-12" width="500" height="200" data-labels="{{ chart.months|join(',') }}" data-scale="1000" data-values="Versions:{{ chart.versions|join(',') }}|Packages:{{ chart.packages|join(',') }}">
+                    Sorry, the graph can't be displayed because your browser doesn't support &lt;svg&gt; html element.
+                </svg>
             </p>
-            <ul class="legend">
-                <li class="legend-first"><span>&#9632;</span> Versions</li>
-                <li class="legend-second"><span>&#9632;</span> Packages</li>
-            </ul>
             <p>The last data point is for the current month and shows partial data.</p>
 
             {% if downloadsChart %}
                 <h3>Packages installed in the last 30 days</h3>
                 <p class="row">
-                    <canvas class="col-xs-12" width="500" height="200" data-labels="{{ downloadsChart.labels|join(',') }}" data-scale="1000" data-values="{{ downloadsChart.values|join(',') }}">
-                        Sorry, the graph can't be displayed because your browser doesn't support &lt;canvas&gt; html element.
-                    </canvas>
+                    <svg class="chart col-xs-12" width="500" height="200" data-labels="{{ downloadsChart.labels|join(',') }}" data-scale="1000" data-values="Installs:{{ downloadsChart.values|join(',') }}">
+                        Sorry, the graph can't be displayed because your browser doesn't support &lt;svg&gt; html element.
+                    </svg>
                 </p>
-                <ul class="legend">
-                    <li class="legend-first"><span>&#9632;</span> Installs</li>
-                </ul>
             {% endif %}
             {% if downloadsChartMonthly %}
                 <h3>Packages installed per month</h3>
                 <p class="row">
-                    <canvas class="col-xs-12" width="500" height="200" data-labels="{{ downloadsChartMonthly.labels|join(',') }}" data-scale="1000000" data-values="{{ downloadsChartMonthly.values|join(',') }}">
-                        Sorry, the graph can't be displayed because your browser doesn't support &lt;canvas&gt; html element.
-                    </canvas>
+                    <svg class="chart col-xs-12" width="500" height="200" data-labels="{{ downloadsChartMonthly.labels|join(',') }}" data-scale="1000000" data-values="Installs:{{ downloadsChartMonthly.values|join(',') }}">
+                        Sorry, the graph can't be displayed because your browser doesn't support &lt;svg&gt; html element.
+                    </svg>
                 </p>
-                <ul class="legend">
-                    <li class="legend-first"><span>&#9632;</span> Installs</li>
-                </ul>
                 <p>The last data point is for the current month and shows partial data.</p>
             {% endif %}
 
@@ -61,7 +51,12 @@
     </section>
 {% endblock %}
 
+{% block stylesheets %}
+    <link href="https://cdn.rawgit.com/novus/nvd3/v1.7.1/build/nv.d3.css" rel="stylesheet">
+{% endblock %}
+
 {% block scripts %}
-    <script src="{{ asset('js/libs/Chart.js/Chart.min.js') }}"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
+    <script src="https://cdn.rawgit.com/novus/nvd3/v1.7.1/build/nv.d3.min.js"></script>
     <script src="{{ asset('bundles/packagistweb/js/charts.js') }}"></script>
 {% endblock %}

+ 1 - 0
src/Packagist/WebBundle/Resources/views/layout.html.twig

@@ -15,6 +15,7 @@
         <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
         <link rel="stylesheet" href="{{ asset('bundles/packagistweb/css/main.css') }}" />
         <link rel="stylesheet" href="{{ asset('css/humane/jackedup.css') }}" />
+        {% block stylesheets %}{% endblock %}
 
         {% block head_feeds %}
         <link rel="alternate" type="application/rss+xml" title="Newly Submitted Packages - Packagist" href="{{ url('feed_packages', {_format: 'rss'}) }}" />

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 9
web/js/libs/Chart.js/Chart.min.js


Vissa filer visades inte eftersom för många filer har ändrats