Skip to content

Commit

Permalink
Create package statistics page
Browse files Browse the repository at this point in the history
  • Loading branch information
codedmonkey committed Dec 30, 2024
1 parent 2469612 commit 27e3492
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 3 deletions.
57 changes: 57 additions & 0 deletions assets/controllers/chart_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Controller } from '@hotwired/stimulus';
import Chart from 'chart.js/auto'; // todo limit size https://www.chartjs.org/docs/latest/getting-started/integration.html#bundle-optimization

/* stimulusFetch: 'lazy' */
export default class extends Controller {
static targets = [
'canvas',
]

static values = {
data: Object,
type: String,
}

connect() {
const data = this.dataValue;
const type = this.typeValue;

new Chart(
this.canvasTarget,
{
type: 'line',
data: this.parseData(data, type),
},
);
}

parseData(data, type) {
switch (type) {
case 'daily':
return {
labels: Object.keys(data).map(key => `${key.substring(0, 4)}-${key.substring(4, 6)}-${key.substring(6, 8)}`),
datasets: [
{
label: 'Installations per day',
data: Object.values(data),
},
],
};

case 'daily-versions':
const datasets = [];

for (const key in data) {
datasets.push({
label: key,
data: Object.values(data[key]),
});
}

return {
labels: Object.keys(data[0]).map(key => `${key.substring(0, 4)}-${key.substring(4, 6)}-${key.substring(6, 8)}`),
datasets,
};
}
}
}
1 change: 0 additions & 1 deletion assets/dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
* Welcome to your app's main JavaScript file!
*
Expand Down
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@hotwired/stimulus": "^3.0.0",
"@symfony/stimulus-bridge": "^3.2.0",
"@symfony/webpack-encore": "^5.0.0",
"chart.js": "^4.4.7",
"core-js": "^3.38.0",
"regenerator-runtime": "^0.13.9",
"ts-loader": "^9.5.1",
Expand All @@ -21,5 +22,9 @@
"build": "encore dev",
"watch": "encore dev --watch",
"production": "encore production --progress"
}
},
"browserslist": [
"defaults",
"not IE 11"
]
}
42 changes: 42 additions & 0 deletions src/Controller/Dashboard/DashboardPackagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,48 @@ public function versions(string $packageName): Response
]);
}

#[Route('/dashboard/packages/statistics/{packageName}', name: 'dashboard_packages_statistics', requirements: ['packageName' => '[a-z0-9_.-]+/[a-z0-9_.-]+'])]
#[IsGrantedAccess]
public function statistics(string $packageName): Response
{
$package = $this->packageRepository->findOneBy(['name' => $packageName]);

$versionInstallationsData = [];

foreach ($package->getVersions() as $version) {
$majorVersion = $version->getMajorVersion();

$versionInstallationsData[$majorVersion] ??= [];

foreach ($version->getInstallations()->getData() as $key => $installations) {
$versionInstallationsData[$majorVersion][$key] ??= 0;
$versionInstallationsData[$majorVersion][$key] += $installations;
}
}

$today = new \DateTimeImmutable();
$todayKey = $today->format('Ymd');
$installationsToday = $package->getInstallations()->getData()[$todayKey] ?? 0;

$installationsLast30Days = 0;
$date = new \DateTimeImmutable('-30 days');

while ($date <= $today) {
$dateKey = $date->format('Ymd');
$installationsLast30Days += $package->getInstallations()->getData()[$dateKey] ?? 0;

$date = $date->modify('+1 day');
}

return $this->render('dashboard/packages/package_statistics.html.twig', [
'package' => $package,
'versionInstallationsData' => $versionInstallationsData,
'installationsTotal' => $package->getInstallations()->getTotal(),
'installationsLast30Days' => $installationsLast30Days,
'installationsToday' => $installationsToday,
]);
}

#[Route('/dashboard/packages/add-mirroring', name: 'dashboard_packages_add_mirroring')]
#[IsGranted('ROLE_ADMIN')]
public function addMirror(Request $request): Response
Expand Down
21 changes: 21 additions & 0 deletions src/Doctrine/Entity/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,27 @@ public function getPrettyPublicUrl(): ?string
return $url;
}

public function getMajorVersion(): int
{
$split = explode('.', $this->version);

return (int) $split[0];
}

public function getMinorVersion(): int
{
$split = explode('.', $this->version);

return (int) $split[1];
}

public function getPatchVersion(): int
{
$split = explode('.', $this->version);

return (int) $split[2];
}

public function toComposerArray(): array
{
$tags = [];
Expand Down
4 changes: 3 additions & 1 deletion templates/dashboard/packages/package_header.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<span class="nav-link disabled">Dependants</span>
</li>
<li class="nav-item">
<span class="nav-link disabled">Statistics</span>
{% set packageVersionsUrl = ea_url()
.setRoute('dashboard_packages_statistics', {packageName: package.name}) %}
<a {% if currentPage == 'statistics' %}class="nav-link active" aria-current="page"{% else %}class="nav-link text-primary"{% endif%} href="{{ packageVersionsUrl }}">Statistics</a>
</li>
</ul>
63 changes: 63 additions & 0 deletions templates/dashboard/packages/package_statistics.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% extends '@EasyAdmin/page/content.html.twig' %}

{% block page_title %}{{ package.name }}{% endblock %}

{% block search_wrapper %}
{% include 'dashboard/packages/search_box.html.twig' with {searchAutofocus: false} %}
{% endblock %}

{% block page_content %}
{% include 'dashboard/packages/package_header.html.twig' with {currentPage: 'statistics'} %}

<div class="mb-3">
<h2>{{ 'Installations'|trans }}</h2>
<div class="row">
<div class="col-md-4">
<div class="card mb-2">
<div class="card-body">
<div>{{ 'Total'|trans }}:</div>
<div class="display-6">{{ installationsTotal|number_format(thousandSep: ' ') }}</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-2">
<div class="card-body">
<div>{{ 'Last 30 days'|trans }}:</div>
<div class="display-6">{{ installationsLast30Days|number_format(thousandSep: ' ') }}</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-2">
<div class="card-body">
<div>{{ 'Today'|trans }}:</div>
<div class="display-6">{{ installationsToday|number_format(thousandSep: ' ') }}</div>
</div>
</div>
</div>
</div>
</div>

<div class="mb-3">
<h2>{{ 'Daily installations'|trans }}</h2>
<div
data-controller="chart"
data-chart-data-value="{{ package.installations.data ? package.installations.data|json_encode|escape : '{}' }}"
data-chart-type-value="daily"
>
<canvas data-chart-target="canvas"></canvas>
</div>
</div>

<div>
<h2>{{ 'Daily installations per version'|trans }}</h2>
<div
data-controller="chart"
data-chart-data-value="{{ versionInstallationsData|json_encode|escape }}"
data-chart-type-value="daily-versions"
>
<canvas data-chart-target="canvas"></canvas>
</div>
</div>
{% endblock %}
7 changes: 7 additions & 0 deletions translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ Move Up: Move Up
No credentials: No credentials
Search packages: Search packages

Daily installations: Daily installations
Daily installations per version: Daily installations per version
Installations: Installations
Last 30 days: Last 30 days
Today: Today
Total: Total

Admin: Admin
Owner: Owner

Expand Down

0 comments on commit 27e3492

Please sign in to comment.