First Widget Bar + Number of notification unread. All is hardcoded

This commit is contained in:
Lucas Silva 2023-05-16 02:17:36 +02:00
parent 790c7f6724
commit b9e580af9a
7 changed files with 169 additions and 107 deletions

View File

@ -32,6 +32,7 @@ use Chill\MainBundle\Security\Resolver\CenterResolverInterface;
use Chill\MainBundle\Security\Resolver\ScopeResolverInterface; use Chill\MainBundle\Security\Resolver\ScopeResolverInterface;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface; use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
use Chill\MainBundle\Templating\UI\NotificationCounterInterface; use Chill\MainBundle\Templating\UI\NotificationCounterInterface;
use Chill\MainBundle\Widget\WidgetHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface; use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Bundle\Bundle;
@ -62,6 +63,8 @@ class ChillMainBundle extends Bundle
->addTag('chill_main.workflow_handler'); ->addTag('chill_main.workflow_handler');
$container->registerForAutoconfiguration(CronJobInterface::class) $container->registerForAutoconfiguration(CronJobInterface::class)
->addTag('chill_main.cron_job'); ->addTag('chill_main.cron_job');
$container->registerForAutoconfiguration(WidgetHandlerInterface::class)
->addTag('chill_main.widget_handler');
$container->addCompilerPass(new SearchableServicesCompilerPass()); $container->addCompilerPass(new SearchableServicesCompilerPass());
$container->addCompilerPass(new ConfigConsistencyCompilerPass()); $container->addCompilerPass(new ConfigConsistencyCompilerPass());

View File

@ -11,110 +11,113 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller; namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\UserRepository;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\MainBundle\Widget\WidgetHandlerManager; use Chill\MainBundle\Widget\WidgetHandlerManager;
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Security;
use PHPUnit\Util\Json;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
/** /**
* @Route("/{_locale}/dashboard") * @Route("/{_locale}/dashboard")
*/ */
class DashboardHomepageController extends AbstractController{ class DashboardHomepageController extends AbstractController{
// private WidgetHandlerManager $widgetHandlerManager;
//
// public function __construct(
// //AccompanyingPeriodRepository $accompanyingPeriodRepository,
// WidgetHandlerManager $widgetHandlerManager
// )
// {
// //$this->accompanyingPeriodRepository = $accompanyingPeriodRepository;
// $this->widgetHandlerManager = $widgetHandlerManager;
// }
private WidgetHandlerManager $widgetHandlerManager; private WidgetHandlerManager $widgetHandlerManager;
private Security $security;
private UserRepository $userRepository;
private EntityManagerInterface $em;
private LoggerInterface $logger;
private SerializerInterface $serializer;
private PaginatorFactory $paginatorFactory;
public function __construct(
//AccompanyingPeriodRepository $accompanyingPeriodRepository,
WidgetHandlerManager $widgetHandlerManager,
Security $security,
UserRepository $userRepository,
EntityManagerInterface $em,
LoggerInterface $logger,
SerializerInterface $serializer,
PaginatorFactory $paginatorFactory,
)
{
//$this->accompanyingPeriodRepository = $accompanyingPeriodRepository;
$this->widgetHandlerManager = $widgetHandlerManager;
$this->security = $security;
$this->userRepository = $userRepository;
$this->em = $em;
$this->logger = $logger;
$this->serializer = $serializer;
$this->paginatorFactory = $paginatorFactory;
}
/** /**
* @Route("/raw_data", name="chill_main_widget_raw_data") * @Route("/raw_data", name="chill_main_widget_raw_data")
* @return JsonResponse
*/ */
public function index(): JsonResponse public function index(): JsonResponse
{ {
// Retrieve data and prepare it for the chart $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');
$chartData = [
'data'=> [
'labels' => [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
],
'datasets' =>[
[ if (!$this->security->getUser() instanceof User) {
'label' => 'Dataset 1', throw new AccessDeniedHttpException('You must be authenticated and a user to see the dashboard');
'data' => [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11], }
'backgroundColor' => ['rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)'],
'borderColor' => ['rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)'],
'borderWidth' => 1,
],
]
],
$config = [
'alias' => 'bar',
]; ];
$chartOptions = [
'options' => [
'responsive'=> 'true', $context = [
'maintainAspectRatio'=> 'false' //'user' => $this->security->getUser(),
//Hardcoder pour resultat
] 'user' => 19,
'what' => 'accompanying_period_by_month',
]; ];
$chartConfig =$chartData + $chartOptions; $data = $this->widgetHandlerManager->getDataForWidget($config, $context);
//Return the chart data as JSON response return new JsonResponse($data,Response::HTTP_OK,[]);
return $this->json($chartConfig, $status = 200,$headers = [], $context= []);
} }
/** /**
* @Route("/widget/{context}", name="chill_main_widget_get_data") * @Route("/widget/{context}", name="chill_main_widget_get_data")
*/ */
public function getDataForWidget(Request $request, $context): JsonResponse public function getDataForWidget(Request $request, string $context): JsonResponse
{ {
//Retrieve data from request in vue component //Retrieve data from request in vue component
$requestData = json_decode($request->getContent(),true); $requestData = json_decode($request->getContent(), true);
dump($requestData);
// Process the widget data using the WidgetHandlerManager // Process the widget data using the WidgetHandlerManager
$handler = $this->widgetHandlerManager->getHandler($requestData, $context); //$handler = $this->widgetHandlerManager->getHandler($requestData);
//dump($handler);
// Return the widget data in JSON response // Return the widget data in JSON response
return new JsonResponse($this->getData($requestData, $context)); //return new JsonResponse($this->getData($requestData));
return new JsonResponse($requestData);
} }
private function getData( array $config,array $context)
{
$widgetData = [];
foreach ($config as $widget) {
$widgetData[] = [
'data' => $this->widgetHandlerManager->getDataForWidget($config,$context),
'options'=> 'responsive: true'
];
}
return $widgetData;
}
} }

View File

@ -43,21 +43,6 @@
<MyWidget/> <MyWidget/>
</div> </div>
</div> </div>
<div class="mbloc col col-sm-6 col-lg-4">
<div class="custom2">
Mon dashboard personnalisé
</div>
</div>
<div class="mbloc col col-sm-6 col-lg-4">
<div class="custom3">
Mon dashboard personnalisé
</div>
</div>
<div class="mbloc col col-sm-6 col-lg-4">
<div class="custom4">
Mon dashboard personnalisé
</div>
</div>
</div> </div>
</template> </template>

View File

@ -1,6 +1,7 @@
<template> <template>
<div class="container"> <div class="container">
<Bar v-if="loaded" :data="chartData" :options="chartOptions"/> <Bar v-if="loaded_bar" :data="chartData" :options="chartOptions"/>
<span v-if="loaded_number">{{number}} Notification(s) non lue(s)</span>
</div> </div>
</template> </template>
@ -16,7 +17,6 @@ import {
} from 'chart.js' } from 'chart.js'
import { Bar } from 'vue-chartjs' import { Bar } from 'vue-chartjs'
import {defineComponent} from 'vue' import {defineComponent} from 'vue'
import * as chartConfig from './js/chartConfig'
import {makeFetch} from "../../lib/api/apiMethods"; import {makeFetch} from "../../lib/api/apiMethods";
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
@ -24,29 +24,32 @@ ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
export default defineComponent({ export default defineComponent({
name: 'MyWidget', name: 'MyWidget',
components: { components: {
Bar Bar,
}, },
data() { data() {
return { return {
loaded: false, loaded_bar: false,
chartData: { loaded_number: false,
labels: [ 'January', 'February', 'March' ], chartData: null,
datasets: [ { data: [40, 20, 12] } ] chartOptions: null,
}, number: "",
chartOptions: {
responsive: true
}
} }
}, },
async mounted() { async mounted() {
this.loaded=false; this.loaded_bar=false;
this.loaded_number=false;
const url = '/fr/dashboard/raw_data'; const url = '/fr/dashboard/raw_data';
try { try {
const response: { data: any } = await makeFetch("GET", url); const response: { data: any, options: any, type: any} = await makeFetch("GET", url);
this.chartData = response.data; this.chartData = response.data;
console.log(this.chartData); this.chartOptions = response.options;
console.log(chartConfig); if(response.type == 'bar'){
this.loaded = true; this.loaded_bar = true;
}
else {
this.loaded_number = true
this.number = response.data.datasets[0].data[0];
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@ -0,0 +1,55 @@
<?php
namespace Chill\MainBundle\Widget\Widgets\DataFetcher;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\ResultSetMapping;
class WidgetBarDataFetcher
{
private EntityManagerInterface $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* @throws \Exception
*/
public function fetchDataForWidget(int $userId): array
{
$sql = "
SELECT DATE_TRUNC('month', ap.openingdate) AS month,
COUNT(ap.id) AS count
FROM chill_person_accompanying_period ap
WHERE ap.user_id = :userId
GROUP BY DATE_TRUNC('month', ap.openingdate)
ORDER BY DATE_TRUNC('month', ap.openingdate) ASC
";
$rsm = new ResultSetMapping();
$rsm->addScalarResult('month', 'month');
$rsm->addScalarResult('count', 'count');
$query = $this->entityManager->createNativeQuery($sql, $rsm);
$query->setParameter('userId', $userId);
$results = $query->getResult();
$counts = [];
$months =[] ;
foreach ($results as $result) {
$date = new \DateTime($result['month']);
$formattedMonth = $date->format('Y-m');
$months[] = $formattedMonth;
$counts[] = $result['count'];
}
return [
'months'=>$months,
'counts'=>$counts,
];
}
}

View File

@ -25,27 +25,27 @@ class WidgetBar implements WidgetHandlerInterface
private Security $security; private Security $security;
private AccompanyingPeriodRepository $acpRepository; //private AccompanyingPeriodRepository $acpRepository;
private WidgetBarDataFetcher $dataFetcher; private WidgetBarDataFetcher $dataFetcher;
private NotificationRepository $notificationRepository; //private NotificationRepository $notificationRepository;
private EntityManagerInterface $em; //private EntityManagerInterface $em;
public function __construct( public function __construct(
AccompanyingPeriodRepository $accompanyingPeriodRepository, // AccompanyingPeriodRepository $accompanyingPeriodRepository,
Security $security, Security $security,
NotificationRepository $notificationRepository, // NotificationRepository $notificationRepository,
EntityManagerInterface $em, // EntityManagerInterface $em,
WidgetBarDataFetcher $dataFetcher WidgetBarDataFetcher $dataFetcher
) )
{ {
$this->acpRepository = $accompanyingPeriodRepository; // $this->acpRepository = $accompanyingPeriodRepository;
$this->security = $security; $this->security = $security;
$this->notificationRepository = $notificationRepository; // $this->notificationRepository = $notificationRepository;
$this->em = $em; // $this->em = $em;
$this->dataFetcher = $dataFetcher; $this->dataFetcher = $dataFetcher;
} }

View File

@ -113,4 +113,17 @@ final class AccompanyingPeriodRepository implements ObjectRepository
return $qb; return $qb;
} }
public function countByUserGroupedByMonth(User $user): array
{
$qb = $this->createQueryBuilder('a');
$qb->select()
->addSelect('COUNT(a.id) AS count')
->andWhere('a.user = :user')
->setParameter('user', $user)
->groupBy('month')
->orderBy('month', 'ASC');
return $qb->getQuery()->getResult();
}
} }