diff --git a/assets/styles/app.css b/assets/styles/app.css index 42a7c59..565a11f 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -69,7 +69,7 @@ body { } .content-wrapper { - background: #F5F7FF; + background: #EEF0FD; width: 100%; -webkit-flex-grow: 1; flex-grow: 1; diff --git a/src/Controller/OrganizationController.php b/src/Controller/OrganizationController.php index 3c27b4a..53a35ac 100644 --- a/src/Controller/OrganizationController.php +++ b/src/Controller/OrganizationController.php @@ -4,6 +4,7 @@ namespace App\Controller; use App\Entity\UsersOrganizations; use App\Service\OrganizationsService; +use App\Service\UserOrganizationService; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Attribute\Route; @@ -18,7 +19,8 @@ class OrganizationController extends AbstractController private const ACCESS_DENIED = 'Access denied'; public function __construct(private readonly EntityManagerInterface $entityManager, - private readonly OrganizationsService $organizationsService) + private readonly OrganizationsService $organizationsService, + private readonly UserOrganizationService $usersOrganizationService) { } @@ -75,7 +77,8 @@ class OrganizationController extends AbstractController $newUsers = $this->entityManager->getRepository(UsersOrganizations::class)->getLastNewActiveUsersByOrganization($organization); $adminUsers = $this->entityManager->getRepository(UsersOrganizations::class)->getAdminUsersByOrganization($organization); // reusing the method to avoid code duplication even though it returns an array of UsersOrganizations - $org = $this->entityManager->getRepository(UsersOrganizations::class)->findActiveUsersByOrganizations([$organization]); + $org = $this->usersOrganizationService->findActiveUsersByOrganizations([$organization]); + diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 450580b..2f8c5b1 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -36,8 +36,8 @@ class UserController extends AbstractController public function index(EntityManagerInterface $entityManager): Response { if ($this->isGranted('ROLE_SUPER_ADMIN')) { - $usersByOrganization = $entityManager->getRepository(UsersOrganizations::class)->getActiveUsersGroupedByOrganization(); - + $usersByOrganization = $this->userOrganizationService->getActiveUsersGroupedByOrganization(); +// dd($usersByOrganization); } else{ $user = $this->getUser(); if (!$user) { @@ -49,8 +49,7 @@ class UserController extends AbstractController // if user is not admin in any organization, throw access denied throw $this->createNotFoundException(self::ACCESS_DENIED); } - $usersByOrganization = $this->entityManager->getRepository(UsersOrganizations::class) - ->findActiveUsersByOrganizations($organizations); + $usersByOrganization = $this->userOrganizationService->findActiveUsersByOrganizations($organizations); } return $this->render('user/index.html.twig', [ 'usersByOrganization' => $usersByOrganization, diff --git a/src/Repository/UsersOrganizationsRepository.php b/src/Repository/UsersOrganizationsRepository.php index 72583b7..a72cf62 100644 --- a/src/Repository/UsersOrganizationsRepository.php +++ b/src/Repository/UsersOrganizationsRepository.php @@ -65,90 +65,8 @@ class UsersOrganizationsRepository extends ServiceEntityRepository return array_map(fn($uo) => $uo->getOrganization(), $results); } - /** - * Get all active users grouped by organization. - * Users with no organization are grouped under 'autre'. - * - * @return array - */ - public function getActiveUsersGroupedByOrganization(): array - { - $users = $this->getEntityManager()->getRepository(User::class)->getAllActiveUsers(); - $userOrgs = $this->getAllActiveUserOrganizationLinks(); - $userToOrgs = $this->mapUserToOrganizations($userOrgs); - $orgs = []; - foreach ($users as $user) { - $userId = $user['id']; - if (isset($userToOrgs[$userId])) { - foreach ($userToOrgs[$userId] as $orgInfo) { - $orgId = $orgInfo['organization_id']; - if (!isset($orgs[$orgId])) { - $orgs[$orgId] = [ - 'organization_id' => $orgId, - 'organization_name' => $orgInfo['organization_name'], - 'users' => [], - ]; - } - $orgs[$orgId]['users'][$userId] = $user; - } - } else { - if (!isset($orgs['autre'])) { - $orgs['autre'] = [ - 'organization_id' => null, - 'organization_name' => 'autre', - 'users' => [], - ]; - } - $orgs['autre']['users'][$userId] = $user; - } - } - - // Convert users arrays to indexed arrays - foreach ($orgs as &$org) { - $org['users'] = array_values($org['users']); - } - - return array_values($orgs); - } - - /** - * Get all active users for each organization in the given array. - * - * @param Organizations[] $organizations - * @return array - */ - public function findActiveUsersByOrganizations(array $organizations): array - { - if (empty($organizations)) { - return []; - } - - $userOrgs = $this->getAllActiveUserOrganizationLinks($organizations); - - $usersByOrg = []; - foreach ($userOrgs as $uo) { - $org = $uo->getOrganization(); - $orgId = $org->getId(); - if (!isset($usersByOrg[$orgId])) { - $usersByOrg[$orgId] = [ - 'organization_id' => $orgId, - 'organization_name' => $org->getName(), - 'users' => [], - ]; - } - $userId = $uo->getUsers()->getId(); - $usersByOrg[$orgId]['users'][$userId] = $uo->getUsers(); - } - - // Convert users arrays to indexed arrays - foreach ($usersByOrg as &$org) { - $org['users'] = array_values($org['users']); - } - - return array_values($usersByOrg); - } /** * Helper: Get all active UsersOrganizations links, optionally filtered by organizations. @@ -156,7 +74,7 @@ class UsersOrganizationsRepository extends ServiceEntityRepository * @param Organizations[]|null $organizations * @return UsersOrganizations[] */ - private function getAllActiveUserOrganizationLinks(array $organizations = null): array + public function getAllActiveUserOrganizationLinks(array $organizations = null): array { $qb = $this->createQueryBuilder('uo') ->innerJoin('uo.organization', 'o') @@ -172,27 +90,6 @@ class UsersOrganizationsRepository extends ServiceEntityRepository return $qb->getQuery()->getResult(); } - /** - * Helper: Map userId to their organizations (id and name), avoiding duplicates. - * - * @param UsersOrganizations[] $userOrgs - * @return array - */ - private function mapUserToOrganizations(array $userOrgs): array - { - $userToOrgs = []; - foreach ($userOrgs as $uo) { - $userId = $uo->getUsers()->getId(); - $org = $uo->getOrganization(); - $orgId = $org->getId(); - $orgName = $org->getName(); - $userToOrgs[$userId][$orgId] = [ - 'organization_id' => $orgId, - 'organization_name' => $orgName, - ]; - } - return $userToOrgs; - } /** * Get the last 10 new active users for a specific organization. diff --git a/src/Service/UserOrganizationService.php b/src/Service/UserOrganizationService.php index 9e2bb5d..dd4f9d7 100644 --- a/src/Service/UserOrganizationService.php +++ b/src/Service/UserOrganizationService.php @@ -6,6 +6,7 @@ use App\Entity\Apps; use App\Entity\Organizations; use App\Entity\Roles; use App\Entity\User; +use App\Service\UserService; use App\Entity\UsersOrganizations; use Doctrine\ORM\EntityManagerInterface; @@ -20,7 +21,8 @@ readonly class UserOrganizationService * * @param EntityManagerInterface $entityManager Le gestionnaire d'entités Doctrine */ - public function __construct(private readonly EntityManagerInterface $entityManager) + public function __construct(private readonly EntityManagerInterface $entityManager, + private readonly UserService $userService) { } @@ -335,4 +337,126 @@ readonly class UserOrganizationService } $this->entityManager->flush(); } + + /** + * Get all active users grouped by organization. + * Users with no organization are grouped under 'autre'. + * + * @return array + */ + public function getActiveUsersGroupedByOrganization(): array + { + $users = $this->entityManager->getRepository(User::class)->getAllActiveUsers(); + $userOrgs = $this->entityManager->getRepository(UsersOrganizations::class)->getAllActiveUserOrganizationLinks(); + + $userToOrgs = $this->mapUserToOrganizations($userOrgs); + + $orgs = []; + foreach ($users as $user) { + $userId = $user['id']; + if (isset($userToOrgs[$userId])) { + foreach ($userToOrgs[$userId] as $orgInfo) { + $orgId = $orgInfo['organization_id']; + if (!isset($orgs[$orgId])) { + $orgs[$orgId] = [ + 'organization_id' => $orgId, + 'organization_name' => $orgInfo['organization_name'], + 'users' => [], + ]; + } +// $orgs[$orgId]['users'][$userId] = $user; + $orgs[$orgId]['users'][$userId] = [ + 'users' => $user, + 'is_connected' => $this->userService->isUserConnected($user['email']) + ]; + } + } else { + if (!isset($orgs['autre'])) { + $orgs['autre'] = [ + 'organization_id' => null, + 'organization_name' => 'autre', + 'users' => [], + ]; + } + $orgs['autre']['users'][$userId] = [ + 'users' => $user, + 'is_connected' => $this->userService->isUserConnected($user['email']) + ]; + } + } + + // Convert users arrays to indexed arrays + foreach ($orgs as &$org) { + $org['users'] = array_values($org['users']); + } + + return array_values($orgs); + } + + /** + * Get all active users for each organization in the given array. + * + * @param Organizations[] $organizations + * @return array + */ + public function findActiveUsersByOrganizations(array $organizations): array + { + if (empty($organizations)) { + return []; + } + + $userOrgs = $this->entityManager->getRepository(UsersOrganizations::class)->getAllActiveUserOrganizationLinks($organizations); + + $usersByOrg = []; + foreach ($userOrgs as $uo) { + $org = $uo->getOrganization(); + $orgId = $org->getId(); + if (!isset($usersByOrg[$orgId])) { + $usersByOrg[$orgId] = [ + 'organization_id' => $orgId, + 'organization_name' => $org->getName(), + 'users' => [], + ]; + } + + $user = $uo->getUsers(); + $userId = $user->getId(); + + // Add connection status to user data + $usersByOrg[$orgId]['users'][$userId] = [ + 'users' => $user, + 'is_connected' => $this->userService->isUserConnected($user->getUserIdentifier()) + ]; + } + + // Convert users arrays to indexed arrays + foreach ($usersByOrg as &$org) { + $org['users'] = array_values($org['users']); + } + + return array_values($usersByOrg); + } + + /** + * Helper: Map userId to their organizations (id and name), avoiding duplicates. + * + * @param UsersOrganizations[] $userOrgs + * @return array + */ + private function mapUserToOrganizations(array $userOrgs): array + { + $userToOrgs = []; + foreach ($userOrgs as $uo) { + $userId = $uo->getUsers()->getId(); + $org = $uo->getOrganization(); + $orgId = $org->getId(); + $orgName = $org->getName(); + $userToOrgs[$userId][$orgId] = [ + 'organization_id' => $orgId, + 'organization_name' => $orgName, + ]; + } + return $userToOrgs; + } + } diff --git a/src/Service/UserService.php b/src/Service/UserService.php index 61eaf5a..41577c5 100644 --- a/src/Service/UserService.php +++ b/src/Service/UserService.php @@ -8,6 +8,7 @@ use App\Entity\Roles; use App\Entity\User; use App\Entity\UsersOrganizations; use Doctrine\ORM\EntityManagerInterface; +use League\Bundle\OAuth2ServerBundle\Model\AccessToken; class UserService { @@ -59,4 +60,29 @@ class UserService 'roleId' => $roleAdmin[0]->getId()])); } + + /** + * Check if the user is currently connected. + * This method check if the user is currently connected to one of the applications. + * + * @param String $userIdentifier + * @return bool + */ + public function isUserConnected(string $userIdentifier): bool + { + $now = new \DateTimeImmutable('now', new \DateTimeZone('Europe/Paris')); + $tokens = $this->entityManager->getRepository(AccessToken::class)->findBy([ + 'userIdentifier' => $userIdentifier, + 'revoked' => false + ]); + + foreach ($tokens as $token) { + // Assuming $token->getExpiry() returns a DateTimeInterface + if ($token->getExpiry() > $now) { + return true; + } + } + + return false; + } } diff --git a/templates/organization/activity.html.twig b/templates/organization/activity.html.twig index 60ad84d..81ea905 100644 --- a/templates/organization/activity.html.twig +++ b/templates/organization/activity.html.twig @@ -1,8 +1,10 @@ {% block body %} -
Aucune activité récente.
#} @@ -10,11 +12,24 @@5 mins ago
5 mins ago
+5 mins ago
+5 mins ago
+5 mins ago
+5 mins ago
+| Picture | -Surname | -Name | -Statut | -Visualiser | -||
|---|---|---|---|---|---|---|
| Aucun utilisateur trouvé. | -||||||
|
- {% if user.pictureUrl %}
- |
- {{ user.surname }} | -{{ user.name }} | -{{ user.email }} | -{##} -{# {% if user.isActive %}#} -{# Actif#} -{# {% else %}#} -{# Inactif#} -{# {% endif %}#} -{# | #} -Actif | -- - - {{ ux_icon('fa6-regular:eye', {height: '30px', width: '30px'}) }} - - | -
| Picture | +Surname | +Name | +Statut | +Visualiser | +|
|---|---|---|---|---|---|
| Aucun utilisateur trouvé. | +|||||
|
+ {% if user.users.pictureUrl %}
+ |
+ {{ user.users.surname }} | +{{ user.users.name }} | +{{ user.users.email }} | ++ {% if user.is_connected %} + Actif + {% else %} + Inactif + {% endif %} + | ++ + + {{ ux_icon('fa6-regular:eye', {height: '30px', width: '30px'}) }} + + | +
| Picture | -Visualiser | -||||
|---|---|---|---|---|---|
| {{ empty_message }} | +Picture | +Visualiser | |||
|---|---|---|---|---|---|
|
- {% if user.pictureUrl %}
- |
- {{ user.email }} | -- - {{ ux_icon('fa6-regular:eye', {height: '30px', width: '30px'}) }} - - | +{{ empty_message }} | ||