Skip to content

Commit 2797b63

Browse files
authored
Add widget for downloads chart with json encoded data (#8415)
1 parent 25664aa commit 2797b63

File tree

11 files changed

+196
-164
lines changed

11 files changed

+196
-164
lines changed

app/lib/frontend/templates/views/pkg/score_tab.dart

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:_pub_shared/format/encoding.dart';
5+
import 'dart:convert';
6+
7+
import 'package:_pub_shared/data/download_counts_data.dart';
68
import 'package:_pub_shared/format/number_format.dart';
79
import 'package:pana/models.dart';
8-
import 'package:pub_dev/service/download_counts/download_counts.dart';
910
import 'package:pub_dev/shared/popularity_storage.dart';
11+
import 'package:pub_dev/shared/utils.dart';
1012

1113
import '../../../../scorecard/models.dart' hide ReportStatus;
1214
import '../../../../shared/urls.dart' as urls;
@@ -184,31 +186,12 @@ d.Node _downloadsChart(WeeklyVersionDownloadCounts weeklyVersionDownloads) {
184186
id: '-downloads-chart',
185187
attributes: {
186188
'data-widget': 'downloads-chart',
187-
'data-downloads-chart': _encodeForDownloadsChart(weeklyVersionDownloads)
189+
'data-downloads-chart-points':
190+
base64Encode(jsonUtf8Encoder.convert(weeklyVersionDownloads))
188191
},
189192
);
190193
}
191194

192-
String _encodeForDownloadsChart(WeeklyVersionDownloadCounts wvcd) {
193-
final date = wvcd.newestDate.toUtc().millisecondsSinceEpoch ~/ 1000;
194-
195-
final allCounts = <int>[];
196-
final allRanges = <String>[];
197-
wvcd.majorRangeWeeklyDownloads.forEach((e) => allCounts.addAll(e.counts));
198-
wvcd.minorRangeWeeklyDownloads.forEach((e) => allCounts.addAll(e.counts));
199-
wvcd.patchRangeWeeklyDownloads.forEach((e) => allCounts.addAll(e.counts));
200-
allCounts.addAll(wvcd.totalWeeklyDownloads);
201-
202-
wvcd.majorRangeWeeklyDownloads.forEach((e) => allRanges.add(e.versionRange));
203-
wvcd.minorRangeWeeklyDownloads.forEach((e) => allRanges.add(e.versionRange));
204-
wvcd.patchRangeWeeklyDownloads.forEach((e) => allRanges.add(e.versionRange));
205-
206-
return [
207-
encodeIntsAsLittleEndianBase64String([date, ...allCounts]),
208-
allRanges
209-
].join(',');
210-
}
211-
212195
final _statusIconUrls = {
213196
ReportStatus.passed:
214197
staticUrls.getAssetUrl('/static/img/report-ok-icon-green.svg'),

app/lib/scorecard/models.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
import 'dart:io';
66

7+
import 'package:_pub_shared/data/download_counts_data.dart';
78
import 'package:_pub_shared/search/tags.dart';
89
import 'package:json_annotation/json_annotation.dart';
910
import 'package:pana/models.dart';
1011
import 'package:pub_dev/service/download_counts/backend.dart';
11-
import 'package:pub_dev/service/download_counts/download_counts.dart';
1212
import 'package:pub_dev/task/models.dart';
1313

1414
import '../scorecard/backend.dart';

app/lib/service/download_counts/computations.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import 'dart:async';
55
import 'dart:math';
66

7+
import 'package:_pub_shared/data/download_counts_data.dart';
78
import 'package:gcloud/storage.dart';
89
import 'package:pub_dev/service/download_counts/backend.dart';
910
import 'package:pub_dev/service/download_counts/download_counts.dart';

app/lib/service/download_counts/download_counts.dart

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,13 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:_pub_shared/data/download_counts_data.dart';
56
import 'package:basics/basics.dart';
67
import 'package:collection/collection.dart' show IterableExtension;
78
import 'package:json_annotation/json_annotation.dart';
89
import 'package:pub_semver/pub_semver.dart';
910
part 'download_counts.g.dart';
1011

11-
/// A [VersionRangeCount] is a tuple containing a version range and a list of
12-
/// download counts for periods of same length.
13-
///
14-
/// The first entry in the tuple is a string describing the `versionRange`, for
15-
/// instance '>=1.0.0-0 <2.0.0'.
16-
///
17-
/// The second entry in the tuple is an integer list of `counts` with download
18-
/// counts for each period. A period could for instance be a day, or a week etc.
19-
/// The `counts` list contains at most [maxAge] entries.
20-
///
21-
/// Consider the example of period being one day. The first count represents the
22-
/// number of downloads on `newestDate` followed by the downloads on
23-
/// `newestDate` - 1 and so on. E.g.
24-
///
25-
/// counts = [ 42, 21, 55 ]
26-
/// ▲ ▲ ▲
27-
/// │ │ └──────────── Download count on newestDate - 2 days
28-
/// │ │
29-
/// │ └──────────────── Download count on newestDate - 1 day
30-
///
31-
/// └──────────────────── Download count on newestDate
32-
///
33-
///
34-
/// Each entry in the `counts` list is non-negativ. A `0` entry can for a given
35-
/// day mean that the version range has no downloads or that there is no data.
36-
typedef VersionRangeCount = ({String versionRange, List<int> counts});
37-
3812
/// The maximum number of days for which we store downloads counts for a package.
3913
const maxAge = 731;
4014

@@ -242,46 +216,3 @@ class WeeklyDownloadCounts {
242216
_$WeeklyDownloadCountsFromJson(json);
243217
Map<String, dynamic> toJson() => _$WeeklyDownloadCountsToJson(this);
244218
}
245-
246-
@JsonSerializable(includeIfNull: false)
247-
class WeeklyVersionDownloadCounts {
248-
/// An integer list where each number is the total number of downloads for a
249-
/// given 7 day period starting from [newestDate].
250-
final List<int> totalWeeklyDownloads;
251-
252-
/// A list of [VersionRangeCount] with major version ranges and weekly
253-
/// downloads for these ranges.
254-
///
255-
/// E.g. each number in the `counts` list is the total number of downloads for
256-
/// the range in a 7 day period starting from [newestDate].
257-
final List<VersionRangeCount> majorRangeWeeklyDownloads;
258-
259-
/// A list of [VersionRangeCount] with minor version ranges and weekly
260-
/// downloads for these ranges.
261-
///
262-
/// E.g. each number in the `counts` list is the total number of downloads for
263-
/// the range in a 7 day period starting from [newestDate].
264-
final List<VersionRangeCount> minorRangeWeeklyDownloads;
265-
266-
/// A list of [VersionRangeCount] with patch version ranges and weekly
267-
/// downloads for these ranges.
268-
///
269-
/// E.g. each number in the `counts` list is the total number of downloads for
270-
/// the range in a 7 day period starting from [newestDate].
271-
final List<VersionRangeCount> patchRangeWeeklyDownloads;
272-
273-
/// The newest date with download counts data available.
274-
final DateTime newestDate;
275-
276-
WeeklyVersionDownloadCounts({
277-
required this.newestDate,
278-
required this.majorRangeWeeklyDownloads,
279-
required this.minorRangeWeeklyDownloads,
280-
required this.patchRangeWeeklyDownloads,
281-
required this.totalWeeklyDownloads,
282-
});
283-
284-
factory WeeklyVersionDownloadCounts.fromJson(Map<String, dynamic> json) =>
285-
_$WeeklyVersionDownloadCountsFromJson(json);
286-
Map<String, dynamic> toJson() => _$WeeklyVersionDownloadCountsToJson(this);
287-
}

app/lib/service/download_counts/download_counts.g.dart

Lines changed: 0 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/lib/shared/redis_cache.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:async';
66
import 'dart:convert';
77
import 'dart:math';
88

9+
import 'package:_pub_shared/data/download_counts_data.dart';
910
import 'package:_pub_shared/data/package_api.dart' show VersionScore;
1011
import 'package:gcloud/service_scope.dart' as ss;
1112
import 'package:googleapis/youtube/v3.dart';

pkg/_pub_shared/build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ targets:
1010
- 'lib/data/admin_api.dart'
1111
- 'lib/data/advisories_api.dart'
1212
- 'lib/data/completion.dart'
13+
- 'lib/data/download_counts_data.dart'
1314
- 'lib/data/package_api.dart'
1415
- 'lib/data/page_data.dart'
1516
- 'lib/data/publisher_api.dart'
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:json_annotation/json_annotation.dart';
6+
7+
part 'download_counts_data.g.dart';
8+
9+
/// A [VersionRangeCount] is a tuple containing a version range and a list of
10+
/// download counts for periods of same length.
11+
///
12+
/// The first entry in the tuple is a string describing the `versionRange`, for
13+
/// instance '>=1.0.0-0 <2.0.0'.
14+
///
15+
/// The second entry in the tuple is an integer list of `counts` with download
16+
/// counts for each period. A period could for instance be a day, or a week etc.
17+
///
18+
/// Consider the example of period being one day. The first count represents the
19+
/// number of downloads on `newestDate` followed by the downloads on
20+
/// `newestDate` - 1 and so on. E.g.
21+
///
22+
/// counts = [ 42, 21, 55 ]
23+
/// ▲ ▲ ▲
24+
/// │ │ └──────────── Download count on newestDate - 2 days
25+
/// │ │
26+
/// │ └──────────────── Download count on newestDate - 1 day
27+
///
28+
/// └──────────────────── Download count on newestDate
29+
///
30+
///
31+
/// Each entry in the `counts` list is non-negativ. A `0` entry can for a given
32+
/// day mean that the version range has no downloads or that there is no data.
33+
typedef VersionRangeCount = ({String versionRange, List<int> counts});
34+
35+
@JsonSerializable(includeIfNull: false)
36+
class WeeklyVersionDownloadCounts {
37+
/// An integer list where each number is the total number of downloads for a
38+
/// given 7 day period starting from [newestDate].
39+
final List<int> totalWeeklyDownloads;
40+
41+
/// A list of [VersionRangeCount] with major version ranges and weekly
42+
/// downloads for these ranges.
43+
///
44+
/// E.g. each number in the `counts` list is the total number of downloads for
45+
/// the range in a 7 day period starting from [newestDate].
46+
final List<VersionRangeCount> majorRangeWeeklyDownloads;
47+
48+
/// A list of [VersionRangeCount] with minor version ranges and weekly
49+
/// downloads for these ranges.
50+
///
51+
/// E.g. each number in the `counts` list is the total number of downloads for
52+
/// the range in a 7 day period starting from [newestDate].
53+
final List<VersionRangeCount> minorRangeWeeklyDownloads;
54+
55+
/// A list of [VersionRangeCount] with patch version ranges and weekly
56+
/// downloads for these ranges.
57+
///
58+
/// E.g. each number in the `counts` list is the total number of downloads for
59+
/// the range in a 7 day period starting from [newestDate].
60+
final List<VersionRangeCount> patchRangeWeeklyDownloads;
61+
62+
/// The newest date with download counts data available.
63+
final DateTime newestDate;
64+
65+
WeeklyVersionDownloadCounts({
66+
required this.newestDate,
67+
required this.majorRangeWeeklyDownloads,
68+
required this.minorRangeWeeklyDownloads,
69+
required this.patchRangeWeeklyDownloads,
70+
required this.totalWeeklyDownloads,
71+
});
72+
73+
factory WeeklyVersionDownloadCounts.fromJson(Map<String, dynamic> json) =>
74+
_$WeeklyVersionDownloadCountsFromJson(json);
75+
Map<String, dynamic> toJson() => _$WeeklyVersionDownloadCountsToJson(this);
76+
}

0 commit comments

Comments
 (0)