Browse Source

Visit analytics

imwald
Nuša Pukšič 5 months ago
parent
commit
2d107c598b
  1. 1
      assets/app.js
  2. 37
      assets/styles/analytics.css
  3. 35
      migrations/Version20250826151824.php
  4. 23
      src/Controller/Administration/VisitorAnalyticsController.php
  5. 3
      src/Controller/ArticleController.php
  6. 42
      templates/admin/analytics.html.twig
  7. 8
      templates/admin/articles.html.twig

1
assets/app.js

@ -16,6 +16,7 @@ import './styles/form.css'; @@ -16,6 +16,7 @@ import './styles/form.css';
import './styles/notice.css';
import './styles/spinner.css';
import './styles/a2hs.css';
import './styles/analytics.css';
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');

37
assets/styles/analytics.css

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
.analytics-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.analytics-card {
background: lightgray;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.analytics-table {
width: 100%;
border-collapse: collapse;
}
.analytics-table th, .analytics-table td {
padding: 10px;
border-bottom: 1px solid var(--color-border);
}
.analytics-table th {
text-align: left;
font-weight: 600;
}
.text-right {
text-align: right;
}
.analytics-info {
font-size: 0.9rem;
color: var(--color-border);
}

35
migrations/Version20250826151824.php

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250826151824 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
CREATE TABLE visit (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, route VARCHAR(255) NOT NULL, visited_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
DROP TABLE visit
SQL);
}
}

23
src/Controller/Administration/VisitorAnalyticsController.php

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Controller\Administration;
use App\Repository\VisitRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class VisitorAnalyticsController extends AbstractController
{
#[Route('/admin/analytics', name: 'admin_analytics')]
public function index(VisitRepository $visitRepository): Response
{
$visitStats = $visitRepository->getVisitCountByRoute();
return $this->render('admin/analytics.html.twig', [
'visitStats' => $visitStats,
]);
}
}

3
src/Controller/ArticleController.php

@ -77,7 +77,10 @@ class ArticleController extends AbstractController @@ -77,7 +77,10 @@ class ArticleController extends AbstractController
$article = null;
// check if an item with same eventId already exists in the db
$repository = $entityManager->getRepository(Article::class);
// slug might be url encoded, decode it
$slug = urldecode($slug);
$articles = $repository->findBy(['slug' => $slug]);
$revisions = count($articles);
if ($revisions === 0) {

42
templates/admin/analytics.html.twig

@ -37,45 +37,3 @@ @@ -37,45 +37,3 @@
</div>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<style>
.analytics-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.analytics-card {
background: gray;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.analytics-table {
width: 100%;
border-collapse: collapse;
}
.analytics-table th, .analytics-table td {
padding: 10px;
border-bottom: 1px solid var(--color-border);
}
.analytics-table th {
text-align: left;
font-weight: 600;
}
.text-right {
text-align: right;
}
.analytics-info {
font-size: 0.9rem;
color: var(--color-border);
}
</style>
{% endblock %}

8
templates/admin/articles.html.twig

@ -7,13 +7,12 @@ @@ -7,13 +7,12 @@
<tr>
<th>Title</th>
<th>Summary</th>
<th>Coordinate</th>
<th>Add to Index</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for article in articles %}
<tr>
<tr style="padding-bottom: 5px;">
<td><a href="{{ path('article-slug', {slug: article.slug|url_encode}) }}">{{ article.title }}</a></td>
<td>{{ article.summary|slice(0, 100) }}{% if article.summary|length > 100 %}...{% endif %}</td>
<td>
@ -24,8 +23,7 @@ @@ -24,8 +23,7 @@
data-action="click->copy-to-clipboard#copyToClipboard"
style="margin-left: 0.5em;">Copy to Clipboard</button>
</span>
</td>
<td>
<form method="post" action="{{ path('admin_article_add_to_index') }}" style="display:inline;">
<input type="hidden" name="slug" value="{{ article.slug }}">
<label>

Loading…
Cancel
Save