put activities in an ajax call
This commit is contained in:
parent
9af81b1d2c
commit
b5d56f1d85
|
|
@ -4,12 +4,26 @@ import {TabulatorFull as Tabulator} from 'tabulator-tables';
|
|||
import {eyeIconLink, TABULATOR_FR_LANG} from "../js/global.js";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {aws: String};
|
||||
static values = {aws: String,
|
||||
id: String,
|
||||
activities: Boolean,
|
||||
table: Boolean,
|
||||
};
|
||||
|
||||
static targets = ["activityList", "emptyMessage"]
|
||||
connect() {
|
||||
if(this.activitiesValue){
|
||||
this.loadActivities();
|
||||
setInterval(() => {
|
||||
this.loadActivities();
|
||||
}, 5000); // Refresh every 60 seconds
|
||||
}
|
||||
if (this.tableValue){
|
||||
this.table();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
table(){
|
||||
const table = new Tabulator("#tabulator-org", {
|
||||
// Register locales here
|
||||
|
|
@ -82,4 +96,59 @@ export default class extends Controller {
|
|||
}],
|
||||
});
|
||||
}
|
||||
|
||||
async loadActivities() {
|
||||
try {
|
||||
// 1. Fetch the data using the ID from values
|
||||
const response = await fetch(`/actions/organization/${this.idValue}/activities-ajax`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
|
||||
const activities = await response.json();
|
||||
|
||||
// 2. Render
|
||||
this.renderActivities(activities);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching activities:', error);
|
||||
this.activityListTarget.innerHTML = `<div class="text-danger">Erreur lors du chargement.</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
renderActivities(activities) {
|
||||
// Clear the loading spinner
|
||||
this.activityListTarget.innerHTML = '';
|
||||
|
||||
if (activities.length === 0) {
|
||||
// Show empty message
|
||||
this.activityListTarget.innerHTML = this.emptyMessageTarget.innerHTML;
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through JSON and build HTML
|
||||
const html = activities.map(activity => {
|
||||
return `
|
||||
<div class="card shadow-sm mb-3 border-0 bg-white rounded-end"
|
||||
style="border-left: 6px solid ${activity.color} !important;">
|
||||
|
||||
<div class="card-header bg-transparent border-0 pb-0 pt-3">
|
||||
<h6 class="text-muted text-uppercase fw-bold mb-0" style="font-size: 0.85rem;">
|
||||
${activity.date}
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-2 pb-4">
|
||||
<div class="card-text fs-5 lh-sm">
|
||||
<span class="fw-bold text-dark">${activity.userName}</span>
|
||||
<div class="text-secondary mt-1">${activity.actionType}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
this.activityListTarget.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Actions;
|
||||
use App\Entity\Organizations;
|
||||
use App\Service\ActionService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route(path: '/actions', name: 'actions_')]
|
||||
class ActionController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager,
|
||||
private ActionService $actionService
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/organization/{id}/activities-ajax', name: 'app_organization_activities_ajax', methods: ['GET'])]
|
||||
public function fetchActivitiesAjax(Organizations $organization): JsonResponse
|
||||
{
|
||||
$actions = $this->entityManager->getRepository(Actions::class)->findBy(
|
||||
['Organization' => $organization],
|
||||
['date' => 'DESC'],
|
||||
15
|
||||
);
|
||||
$formattedActivities = $this->actionService->formatActivities($actions);
|
||||
|
||||
return new JsonResponse($formattedActivities);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,11 +40,11 @@ readonly class ActionService
|
|||
{
|
||||
return array_map(function (Actions $activity) {
|
||||
return [
|
||||
'date' => $activity->getDate(),
|
||||
'date' => $activity->getDate()->format('d/m/Y H:i'),
|
||||
'actionType' => $activity->getActionType(),
|
||||
'users' => $activity->getUsers(),
|
||||
'organization' => $activity->getOrganization(),
|
||||
'description' => $activity->getDescription(),
|
||||
'userName' => $activity->getUsers()->getName(),
|
||||
// 'organization' => $activity->getOrganization(),
|
||||
// 'description' => $activity->getDescription(),
|
||||
'color' => $this->getActivityColor($activity->getDate())
|
||||
];
|
||||
}, $activities);
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
{% block body %}
|
||||
|
||||
|
||||
<div class="card border-0">
|
||||
<div class="card-header d-flex justify-content-between align-items-center border-0">
|
||||
<h3>{{ title }}</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if activities|length == 0 %}
|
||||
<p>Aucune activité récente.</p>
|
||||
{% else %}
|
||||
{% set sortedActivities = activities|sort((a, b) => a.date <=> b.date)|reverse %}
|
||||
<ul class="list-group gap-2">
|
||||
{% for activity in sortedActivities%}
|
||||
{% include 'user/organization/userActivity.html.twig' with {
|
||||
activityTime: activity.date,
|
||||
action: activity.actionType,
|
||||
userName: activity.users.name,
|
||||
color: activity.color
|
||||
} %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
{% else %}
|
||||
|
||||
<div id="tabulator-org" data-controller="organization"
|
||||
data-organization-table-value="true"
|
||||
data-organization-data-value="{{ organizationsData|json_encode(constant("JSON_UNESCAPED_UNICODE"))|e("html_attr") }}"
|
||||
data-organization-aws-value="{{ aws_url }}"></div>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
{# single row so that activity and users tabs are next to each other#}
|
||||
{# single row so that activity and users tabs are next to each other #}
|
||||
<div class="row">
|
||||
{# User tables #}
|
||||
{# User tables #}
|
||||
<div class="col-9">
|
||||
<div class="row mb-3 d-flex gap-2 ">
|
||||
<div class="col mb-3 card no-header-bg">
|
||||
|
|
@ -49,7 +49,8 @@
|
|||
<h2>
|
||||
Nouveaux utilisateurs
|
||||
</h2>
|
||||
<a href="{{ path('user_new', {'organizationId': organization.id}) }}" class="btn btn-primary">Ajouter un utilisateur</a>
|
||||
<a href="{{ path('user_new', {'organizationId': organization.id}) }}"
|
||||
class="btn btn-primary">Ajouter un utilisateur</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="tabulator-userListSmall" data-controller="user"
|
||||
|
|
@ -93,7 +94,7 @@
|
|||
</div>
|
||||
|
||||
{# APPLICATION ROW #}
|
||||
{# TODO: Weird gap not going away#}
|
||||
{# TODO: Weird gap not going away #}
|
||||
<div class="row mb-3 ">
|
||||
{% for application in applications %}
|
||||
<div class="col-6 mb-3">
|
||||
|
|
@ -104,16 +105,36 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{# Activities col#}
|
||||
{# Activities col #}
|
||||
<div class="col-3 m-auto">
|
||||
{% include 'organization/activity.html.twig' with {
|
||||
title: 'Activités récentes',
|
||||
empty_message: 'Aucune activité récente.'
|
||||
} %}
|
||||
<div class="card border-0"
|
||||
data-controller="organization"
|
||||
data-organization-activities-value = "true"
|
||||
data-organization-id-value="{{ organization.id }}">
|
||||
|
||||
<div class="card-header d-flex justify-content-between align-items-center border-0">
|
||||
<h3>Activité récente</h3>
|
||||
|
||||
<button class="btn btn-sm btn-outline-secondary" data-action="organization#loadActivities">
|
||||
<i class="fas fa-sync"></i> Rafraîchir
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body bg-light">
|
||||
<div class="d-flex flex-column" data-organization-target="activityList">
|
||||
<div class="text-center text-muted p-5">
|
||||
<span class="spinner-border" aria-hidden="true"></span>
|
||||
</div>
|
||||
{# Ne pas enlever le 2ème /div#}
|
||||
</div>
|
||||
|
||||
{# Empty state #}
|
||||
<div class="d-none" data-organization-target="emptyMessage">
|
||||
<div class="alert alert-light text-center shadow-sm">Aucune activité récente.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
{% block body %}
|
||||
|
||||
<div class="card border">
|
||||
<div class="card-header d-flex align-items-center border-0">
|
||||
<div class="row align-items-center">
|
||||
|
||||
<h4 class="mb-0">
|
||||
<span style="display:inline-block; width:16px; height:16px; border-radius:50%; background:{{ color }}; margin-right:10px;"></span>
|
||||
{{ activityTime|ago }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>{{ userName }} - {{ action }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Loading…
Reference in New Issue