mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	Compare commits
	
		
			15 Commits
		
	
	
		
			280-add-mi
			...
			68-feature
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2fc6e18d0f | |||
|  | 80ea4bbdd2 | ||
|  | 801c693ef9 | ||
|  | c1c9562e67 | ||
|  | b9e580af9a | ||
|  | 790c7f6724 | ||
|  | 1be91bb392 | ||
|  | 93f39ebe5b | ||
|  | 176c3c0e27 | ||
|  | 59cd8466be | ||
|  | ef9e872394 | ||
|  | 51a46ab5d7 | ||
|  | 191b416c6c | ||
| 6028efdc7c | |||
|  | 60c9e037a6 | 
| @@ -31,7 +31,9 @@ | ||||
|     "typescript": "^4.7.2", | ||||
|     "vue-loader": "^17.0.0", | ||||
|     "webpack": "^5.75.0", | ||||
|     "webpack-cli": "^5.0.1" | ||||
|     "webpack-cli": "^5.0.1", | ||||
|       "chart.js": "^4.2.1", | ||||
|       "vue-chartjs": "^5.2.0" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@fullcalendar/core": "^6.1.4", | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use Chill\MainBundle\Security\Resolver\ScopeResolverInterface; | ||||
| use Chill\MainBundle\Service\EntityInfo\ViewEntityInfoProviderInterface; | ||||
| use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface; | ||||
| use Chill\MainBundle\Templating\UI\NotificationCounterInterface; | ||||
| use Chill\MainBundle\Widget\WidgetHandlerInterface; | ||||
| use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface; | ||||
| use Symfony\Component\DependencyInjection\ContainerBuilder; | ||||
| use Symfony\Component\HttpKernel\Bundle\Bundle; | ||||
| @@ -62,9 +63,10 @@ class ChillMainBundle extends Bundle | ||||
|             ->addTag('chill_main.workflow_handler'); | ||||
|         $container->registerForAutoconfiguration(CronJobInterface::class) | ||||
|             ->addTag('chill_main.cron_job'); | ||||
|         $container->registerForAutoconfiguration(WidgetHandlerInterface::class) | ||||
|             ->addTag('chill_main.widget_handler'); | ||||
|         $container->registerForAutoconfiguration(ViewEntityInfoProviderInterface::class) | ||||
|             ->addTag('chill_main.entity_info_provider'); | ||||
|  | ||||
|         $container->addCompilerPass(new SearchableServicesCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); | ||||
|         $container->addCompilerPass(new ConfigConsistencyCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); | ||||
|         $container->addCompilerPass(new TimelineCompilerClass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); | ||||
|   | ||||
| @@ -0,0 +1,133 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| 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\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\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Symfony\Component\HttpFoundation\JsonResponse; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| 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") | ||||
|  */ | ||||
| class DashboardHomepageController extends AbstractController{ | ||||
|  | ||||
|     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") | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|  | ||||
|     public function index(): JsonResponse | ||||
|     { | ||||
|         $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); | ||||
|  | ||||
|         if (!$this->security->getUser() instanceof User) { | ||||
|             throw new AccessDeniedHttpException('You must be authenticated and a user to see the dashboard'); | ||||
|         } | ||||
|         // --------------Bar--------------------- | ||||
|         $config = [ | ||||
|             'alias' => 'bar', | ||||
|         ]; | ||||
|  | ||||
|         $context = [ | ||||
|             //'user' => $this->security->getUser(), | ||||
|             //Hardcoder pour resultat | ||||
|             'user' => 19, | ||||
|             'what' => 'accompanying_period_by_month', | ||||
|         ]; | ||||
|         // --------------Number------------------ | ||||
|         /*$config = [ | ||||
|             'alias' => 'number', | ||||
|         ]; | ||||
|  | ||||
|         $context = [ | ||||
|             'user' => $this->security->getUser(), | ||||
|             //'what' => 'notification_unread', | ||||
|             'what' => 'notification_sender', | ||||
|         ];*/ | ||||
|         $data = $this->widgetHandlerManager->getDataForWidget($config, $context); | ||||
|  | ||||
|         return new JsonResponse($data,Response::HTTP_OK,[]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @Route("/widget/{context}", name="chill_main_widget_get_data") | ||||
|      */ | ||||
|     public function getDataForWidget(Request $request, string $context): JsonResponse | ||||
|     { | ||||
|         //Retrieve data from request in vue component | ||||
|         $requestData = json_decode($request->getContent(), true); | ||||
|         dump($requestData); | ||||
|         // Process the widget data using the WidgetHandlerManager | ||||
|         //$handler = $this->widgetHandlerManager->getHandler($requestData); | ||||
|         //dump($handler); | ||||
|  | ||||
|         // Return the widget data in JSON response | ||||
|         //return new JsonResponse($this->getData($requestData)); | ||||
|  | ||||
|         return new JsonResponse($requestData); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Chill\MainBundle\CRUD\Controller\ApiController; | ||||
|  | ||||
| class SavedExportApiController extends ApiController | ||||
| { | ||||
| } | ||||
| @@ -20,6 +20,7 @@ use Chill\MainBundle\Controller\LanguageController; | ||||
| use Chill\MainBundle\Controller\LocationController; | ||||
| use Chill\MainBundle\Controller\LocationTypeController; | ||||
| use Chill\MainBundle\Controller\RegroupmentController; | ||||
| use Chill\MainBundle\Controller\SavedExportApiController; | ||||
| use Chill\MainBundle\Controller\UserController; | ||||
| use Chill\MainBundle\Controller\UserJobApiController; | ||||
| use Chill\MainBundle\Controller\UserJobController; | ||||
| @@ -54,6 +55,7 @@ use Chill\MainBundle\Entity\Language; | ||||
| use Chill\MainBundle\Entity\Location; | ||||
| use Chill\MainBundle\Entity\LocationType; | ||||
| use Chill\MainBundle\Entity\Regroupment; | ||||
| use Chill\MainBundle\Entity\SavedExport; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Entity\UserJob; | ||||
| use Chill\MainBundle\Form\CenterType; | ||||
| @@ -228,7 +230,7 @@ class ChillMainExtension extends Extension implements | ||||
|         $twigConfig = [ | ||||
|             'globals' => [ | ||||
|                 'installation' => [ | ||||
|                     'name' => $config['installation_name'], ], | ||||
|                     'name' => $config['installation_name'],], | ||||
|                 'available_languages' => $config['available_languages'], | ||||
|                 'add_address' => $config['add_address'], | ||||
|             ], | ||||
| @@ -327,9 +329,9 @@ class ChillMainExtension extends Extension implements | ||||
|      * Load parameter for configuration and set parameters for api. | ||||
|      */ | ||||
|     protected function configureCruds( | ||||
|         ContainerBuilder $container, | ||||
|         array $crudConfig, | ||||
|         array $apiConfig, | ||||
|         ContainerBuilder      $container, | ||||
|         array                 $crudConfig, | ||||
|         array                 $apiConfig, | ||||
|         Loader\YamlFileLoader $loader | ||||
|     ): void { | ||||
|         if (0 === \count($crudConfig)) { | ||||
| @@ -767,7 +769,28 @@ class ChillMainExtension extends Extension implements | ||||
|                         ], | ||||
|                     ], | ||||
|                 ], | ||||
|             ], | ||||
|                 [ | ||||
|                     'class' => SavedExport::class, | ||||
|                     'controller' => SavedExportApiController::class, | ||||
|                     'name' => 'saved_export', | ||||
|                     'base_path' => '/api/1.0/main/saved-export', | ||||
|                     'base_role' => 'ROLE_USER', | ||||
|                     'actions' => [ | ||||
|                         '_index' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                             ], | ||||
|                         ], | ||||
|                         '_entity' => [ | ||||
|                             'methods' => [ | ||||
|                                 Request::METHOD_GET => true, | ||||
|                                 Request::METHOD_HEAD => true, | ||||
|                             ], | ||||
|                         ], | ||||
|                     ], | ||||
|                 ] | ||||
|             ] | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,6 +19,7 @@ use Doctrine\ORM\Mapping as ORM; | ||||
| use Ramsey\Uuid\Uuid; | ||||
| use Ramsey\Uuid\UuidInterface; | ||||
| use Symfony\Component\Validator\Constraints as Assert; | ||||
| use Symfony\Component\Serializer\Annotation\Groups; | ||||
|  | ||||
| /** | ||||
|  * @ORM\Entity | ||||
| @@ -35,6 +36,7 @@ class SavedExport implements TrackCreationInterface, TrackUpdateInterface | ||||
|      * @ORM\Column(type="text", nullable=false, options={"default": ""}) | ||||
|      * | ||||
|      * @Assert\NotBlank | ||||
|      * @Groups({"read"}) | ||||
|      */ | ||||
|     private string $description = ''; | ||||
|  | ||||
| @@ -49,11 +51,13 @@ class SavedExport implements TrackCreationInterface, TrackUpdateInterface | ||||
|      * @ORM\Column(name="id", type="uuid", unique="true") | ||||
|      * | ||||
|      * @ORM\GeneratedValue(strategy="NONE") | ||||
|      * @Groups({"read"}) | ||||
|      */ | ||||
|     private UuidInterface $id; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\Column(type="json", nullable=false, options={"default": "[]"}) | ||||
|      * @Groups({"read"}) | ||||
|      */ | ||||
|     private array $options = []; | ||||
|  | ||||
| @@ -61,11 +65,13 @@ class SavedExport implements TrackCreationInterface, TrackUpdateInterface | ||||
|      * @ORM\Column(type="text", nullable=false, options={"default": ""}) | ||||
|      * | ||||
|      * @Assert\NotBlank | ||||
|      * @Groups({"read"}) | ||||
|      */ | ||||
|     private string $title = ''; | ||||
|  | ||||
|     /** | ||||
|      * @ORM\ManyToOne(targetEntity=User::class) | ||||
|      * @Groups({"read"}) | ||||
|      */ | ||||
|     private User $user; | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|    <span v-if="noResults" class="chill-no-data-statement">{{ $t('no_dashboard') }}</span> | ||||
|    <div v-else id="dashboards" class="row g-3" data-masonry='{"percentPosition": true }'> | ||||
|        | ||||
|  | ||||
|       <div class="mbloc col col-sm-6 col-lg-4"> | ||||
|          <div class="custom1"> | ||||
|             <ul class="list-unstyled"> | ||||
| @@ -38,39 +38,33 @@ | ||||
|             </ul> | ||||
|          </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 class="mbloc col col-sm-6 col-lg-4"> | ||||
|            <div class="custom2"> | ||||
|                <MyWidget/> | ||||
|            </div> | ||||
|        </div> | ||||
|  | ||||
|    </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| import MyWidget from './MyWidget.vue' | ||||
| import { mapGetters } from "vuex"; | ||||
| import Masonry from 'masonry-layout/masonry'; | ||||
|  | ||||
|  | ||||
|  | ||||
| export default { | ||||
|    name: "MyCustoms", | ||||
|     components:{ | ||||
|        MyWidget | ||||
|     }, | ||||
|    data() { | ||||
|       return { | ||||
|          counterClass: { | ||||
|             counter: true   //hack to pass class 'counter' in i18n-t | ||||
|          } | ||||
|          }, | ||||
|       } | ||||
|    }, | ||||
|    computed: { | ||||
| @@ -82,8 +76,8 @@ export default { | ||||
|    mounted() { | ||||
|       const elem = document.querySelector('#dashboards'); | ||||
|       const masonry = new Masonry(elem, {}); | ||||
|    } | ||||
| } | ||||
|    }, | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @@ -98,4 +92,4 @@ span.counter { | ||||
|       background-color: unset; | ||||
|    } | ||||
| } | ||||
| </style> | ||||
| </style> | ||||
|   | ||||
| @@ -0,0 +1,91 @@ | ||||
| <template> | ||||
|     <div class="container"> | ||||
|         <Bar v-if="loaded_bar" :data="chartData" :options="chartOptions"/> | ||||
|         <span v-if="loaded_number">{{ number }}</span> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts"> | ||||
| import { | ||||
|     Chart as ChartJS, | ||||
|     Title, | ||||
|     Tooltip, | ||||
|     Legend, | ||||
|     BarElement, | ||||
|     CategoryScale, | ||||
|     LinearScale | ||||
| } from 'chart.js' | ||||
| import {Bar} from 'vue-chartjs' | ||||
| import {defineComponent} from 'vue' | ||||
| import {makeFetch} from "../../lib/api/apiMethods"; | ||||
|  | ||||
| ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) | ||||
|  | ||||
| export default defineComponent({ | ||||
|     name: 'MyWidget', | ||||
|     components: { | ||||
|         Bar, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             loaded_bar: false, | ||||
|             loaded_number: false, | ||||
|             chartData: null, | ||||
|             chartOptions: null, | ||||
|             number: "", | ||||
|         } | ||||
|     }, | ||||
|     async mounted() { | ||||
|         this.loaded_bar = false; | ||||
|         this.loaded_number = false; | ||||
|         const url = '/fr/dashboard/raw_data'; | ||||
|         try { | ||||
|             const response: { data: any, options: any, type: any } = await makeFetch("GET", url); | ||||
|             this.chartData = response.data; | ||||
|             this.chartOptions = response.options; | ||||
|             if (response.type == 'bar') { | ||||
|                 this.loaded_bar = true; | ||||
|             } else { | ||||
|                 this.loaded_number = true | ||||
|                 this.number = response.data.datasets[0].data[0] + " "+ response.data.labels[0]; | ||||
|             } | ||||
|         } catch (error) { | ||||
|             console.log(error); | ||||
|         } | ||||
|     }, | ||||
|     /*methods: { | ||||
|         async makeNumberWidget() { | ||||
|             let body = { | ||||
|                 config: { | ||||
|                     alias: 'number' | ||||
|                 }, | ||||
|                 context: { | ||||
|                     what: 'notification_unread', | ||||
|                     user: 19 //Ne rien mettre ou via les refs | ||||
|                 } | ||||
|             }; | ||||
|             try { | ||||
|                 const response: { | ||||
|                     data: any, | ||||
|                     options: any, | ||||
|                     type: any | ||||
|                 } = await makeFetch('POST', '/{_locale}//{_locale}/dashboard/widget/number', body) | ||||
|                 this.chartData = response.data; | ||||
|                 this.chartOptions = response.options; | ||||
|                 this.loaded_number = true; | ||||
|                 this.number = response.data.datasets[0].data[0] + response.data.labels[0]; | ||||
|             } catch (error) { | ||||
|                 console.log(error) | ||||
|             } | ||||
|  | ||||
|  | ||||
|         }, | ||||
|     }*/ | ||||
| }) | ||||
| </script> | ||||
| <style lang="scss" scoped> | ||||
|     span { | ||||
|         font-size: x-large; | ||||
|         color: #0a53be; | ||||
|     } | ||||
| </style> | ||||
| @@ -0,0 +1,28 @@ | ||||
| export const data = { | ||||
|     labels: [ | ||||
|         'January', | ||||
|         'February', | ||||
|         'March', | ||||
|         'April', | ||||
|         'May', | ||||
|         'June', | ||||
|         'July', | ||||
|         'August', | ||||
|         'September', | ||||
|         'October', | ||||
|         'November', | ||||
|         'December' | ||||
|     ], | ||||
|     datasets: [ | ||||
|         { | ||||
|             label: 'Data One', | ||||
|             backgroundColor: '#f87979', | ||||
|             data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
|  | ||||
| export const options = { | ||||
|     responsive: true, | ||||
|     maintainAspectRatio: false | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/Bundle/ChillMainBundle/Widget/WidgetHandlerInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/Bundle/ChillMainBundle/Widget/WidgetHandlerInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\MainBundle\Widget; | ||||
|  | ||||
| interface WidgetHandlerInterface | ||||
| { | ||||
|     /** | ||||
|      * Return true if the handler supports the handling for this widget. | ||||
|      */ | ||||
|     public function supports(array $config,array $context = []): bool; | ||||
|  | ||||
|     /** | ||||
|      * Return an array which will be passed as data for the chart in the Vue element. | ||||
|      */ | ||||
|     public function getDataForWidget(array $config,array $context = []): array; | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/Bundle/ChillMainBundle/Widget/WidgetHandlerManager.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Bundle/ChillMainBundle/Widget/WidgetHandlerManager.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Chill\MainBundle\Widget; | ||||
|  | ||||
| use Chill\MainBundle\Widget\WidgetHandlerInterface; | ||||
| use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; | ||||
|  | ||||
| final class WidgetHandlerManager | ||||
| { | ||||
|     private iterable $handlers; | ||||
|  | ||||
|     public function __construct( | ||||
|         iterable $handlers | ||||
|     ) { | ||||
|         $this->handlers = $handlers; | ||||
|     } | ||||
|  | ||||
|     public function getHandler(array $config,): WidgetHandlerInterface | ||||
|     { | ||||
|         foreach ($this->handlers as $widget) { | ||||
|             if ($widget->supports($config)) { | ||||
|                 return $widget; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Handle unsupported context | ||||
|         throw new \InvalidArgumentException('Unsupported widget.'); | ||||
|     } | ||||
|  | ||||
|     public function getDataForWidget(array $config, array $context=[]): array | ||||
|     { | ||||
|         return $this->getHandler($config)->getDataForWidget($config,$context); | ||||
|     } | ||||
| } | ||||
| @@ -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, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										105
									
								
								src/Bundle/ChillMainBundle/Widget/Widgets/WidgetBar.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/Bundle/ChillMainBundle/Widget/Widgets/WidgetBar.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\MainBundle\Widget\Widgets; | ||||
|  | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Repository\NotificationRepository; | ||||
| use Chill\MainBundle\Widget\WidgetHandlerInterface; | ||||
| use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Symfony\Component\Security\Core\Exception\AccessDeniedException; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
| use Chill\MainBundle\Widget\Widgets\DataFetcher\WidgetBarDataFetcher; | ||||
|  | ||||
| class WidgetBar implements WidgetHandlerInterface | ||||
| { | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     //private AccompanyingPeriodRepository $acpRepository; | ||||
|  | ||||
|     private WidgetBarDataFetcher $dataFetcher; | ||||
|  | ||||
|     //private NotificationRepository $notificationRepository; | ||||
|  | ||||
|     //private EntityManagerInterface $em; | ||||
|  | ||||
|     public function __construct( | ||||
|     //    AccompanyingPeriodRepository $accompanyingPeriodRepository, | ||||
|         Security                     $security, | ||||
|     //    NotificationRepository       $notificationRepository, | ||||
|     //    EntityManagerInterface       $em, | ||||
|         WidgetBarDataFetcher         $dataFetcher | ||||
|  | ||||
|     ) | ||||
|     { | ||||
|     //    $this->acpRepository = $accompanyingPeriodRepository; | ||||
|         $this->security = $security; | ||||
|     //    $this->notificationRepository = $notificationRepository; | ||||
|     //    $this->em = $em; | ||||
|         $this->dataFetcher = $dataFetcher; | ||||
|     } | ||||
|  | ||||
|     public function supports(array $config, array $context = []): bool | ||||
|     { | ||||
|         // Check if the context is "bar" | ||||
|         return $config['alias'] === 'bar'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @throws \Exception | ||||
|      */ | ||||
|     public function getDataForWidget(array $config, array $context = []): array | ||||
|     { | ||||
|         $user = $this->security->getUser(); | ||||
|         //$userId = $user->getId(); | ||||
|         //Hardcoder pour résultat | ||||
|         $userId = 19; | ||||
|         $dataForWidget = []; | ||||
|         if (!$user instanceof User) { | ||||
|             throw new AccessDeniedException(); | ||||
|         } | ||||
|  | ||||
|         if ($context !== []) { | ||||
|             switch ($context['what']) { | ||||
|                 case 'accompanying_period_by_month': | ||||
|  | ||||
|                     $data = $this->dataFetcher->fetchDataForWidget($userId); | ||||
|                     $dataForWidget = [ | ||||
|                         'labels' => $data['months'], | ||||
|                         'datasets' => [ | ||||
|                             [ | ||||
|                                 'label' => 'Number of accompanying periods opened', | ||||
|                                 'backgroundColor' => ['#41B883'], | ||||
|                                 'data' => $data['counts'] | ||||
|                             ] | ||||
|                         ] | ||||
|                     ]; | ||||
|                     break; | ||||
|                 default: | ||||
|                     throw new \InvalidArgumentException('Invalid Context.'); | ||||
|  | ||||
|             } | ||||
|         } | ||||
|         return [ | ||||
|             'data' => $dataForWidget, | ||||
|             'options' => [ | ||||
|  | ||||
|                 'responsive' => 'true', | ||||
|                 'maintainAspectRatio' => 'false', | ||||
|                 'position' => 'relative' | ||||
|  | ||||
|             ], | ||||
|             'type' => 'bar', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										104
									
								
								src/Bundle/ChillMainBundle/Widget/Widgets/WidgetNumber.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/Bundle/ChillMainBundle/Widget/Widgets/WidgetNumber.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /* | ||||
|  * Chill is a software for social workers | ||||
|  * | ||||
|  * For the full copyright and license information, please view | ||||
|  * the LICENSE file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| namespace Chill\MainBundle\Widget\Widgets; | ||||
|  | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Chill\MainBundle\Repository\NotificationRepository; | ||||
| use Chill\MainBundle\Widget\WidgetHandlerInterface; | ||||
| use Chill\PersonBundle\Repository\AccompanyingPeriodRepository; | ||||
| use Chill\PersonBundle\Repository\Person; | ||||
| use DateInterval; | ||||
| use DateTimeImmutable; | ||||
| use Symfony\Component\Security\Core\Exception\AccessDeniedException; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
|  | ||||
| class WidgetNumber implements WidgetHandlerInterface | ||||
| { | ||||
|  | ||||
|     private Security $security; | ||||
|  | ||||
|     //private AccompanyingPeriodRepository $acpRepository; | ||||
|  | ||||
|     private NotificationRepository $notificationRepository; | ||||
|  | ||||
|  | ||||
|     public function __construct( | ||||
|     //    AccompanyingPeriodRepository $accompanyingPeriodRepository, | ||||
|         Security                     $security, | ||||
|         NotificationRepository       $notificationRepository, | ||||
|  | ||||
|     ) | ||||
|     { | ||||
|     //    $this->acpRepository = $accompanyingPeriodRepository; | ||||
|         $this->security = $security; | ||||
|         $this->notificationRepository = $notificationRepository; | ||||
|     } | ||||
|  | ||||
|     public function supports(array $config, array $context = []): bool | ||||
|     { | ||||
|         return $config['alias'] === 'number'; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function getDataForWidget(array $config, array $context = []): array | ||||
|     { | ||||
|         $user = $this->security->getUser(); | ||||
|         $dataForWidget = []; | ||||
|         if (!$user instanceof User) { | ||||
|             throw new AccessDeniedException(); | ||||
|         } | ||||
|  | ||||
|         if ($context !== []) { | ||||
|             switch ($context['what']) { | ||||
|  | ||||
|                 /*case 'accompanying_period_history' : | ||||
|                     //Send back a data that need to be serialize in order to see | ||||
|                     $since = (new DateTimeImmutable('now'))->sub(new DateInterval('P1Y')); | ||||
|                     $data = $this->acpRepository->countByRecentUserHistory($user, $since); | ||||
|                     $what = $this->acpRepository->findConfirmedByUser($user); | ||||
|                     break;*/ | ||||
|                 case 'notification_sender': | ||||
|                     //Count the number of notification the sender send | ||||
|                     $countSend = $this->notificationRepository->countAllForSender($user); | ||||
|                     $dataForWidget = [ | ||||
|                         'labels' => ['notification(s) envoyée(s)'], | ||||
|                         'datasets' => [ | ||||
|                             [ | ||||
|                                 'data' => [$countSend] | ||||
|                             ] | ||||
|                         ] | ||||
|                     ]; | ||||
|                     break; | ||||
|  | ||||
|                 case 'notification_unread': | ||||
|                     //Count the number of unread notification by the current User | ||||
|                     $countUnread = $this->notificationRepository->countUnreadByUser($user); | ||||
|                     $dataForWidget = [ | ||||
|                         'labels' => ['notification(s) non lue(s)'], | ||||
|                         'datasets' => [ | ||||
|                             [ | ||||
|                                 'data' => [$countUnread] | ||||
|                             ] | ||||
|                         ] | ||||
|                     ]; | ||||
|                     break; | ||||
|                 default : throw new \InvalidArgumentException('Invalid Context.'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'data' => $dataForWidget, | ||||
|             'type' => 'number', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -10,6 +10,22 @@ servers: | ||||
|  | ||||
| components: | ||||
|     schemas: | ||||
|         SavedExport: | ||||
|             type: object | ||||
|             properties: | ||||
|                 id: | ||||
|                     type: integer | ||||
|                 user_id: | ||||
|                     type: integer | ||||
|                 description: | ||||
|                     type: string | ||||
|                 exportalias: | ||||
|                     type: string | ||||
|                 options: | ||||
|                     type: string #TODO -> je pense que c'est object | ||||
|                 title: | ||||
|                     type: string | ||||
|  | ||||
|         User: | ||||
|             type: object | ||||
|             properties: | ||||
| @@ -791,7 +807,7 @@ paths: | ||||
|     /1.0/main/civility.json: | ||||
|         get: | ||||
|             tags: | ||||
|             - civility | ||||
|                 - civility | ||||
|             summary: Return all civility types | ||||
|             responses: | ||||
|                 200: | ||||
| @@ -843,3 +859,27 @@ paths: | ||||
|                 403: | ||||
|                     description: "Unauthorized" | ||||
|  | ||||
|     /1.0/main/saved-export/{id}.json: | ||||
|         get: | ||||
|             tags: | ||||
|                 - export | ||||
|             summary: Return a specific saved export who is saved by an existing user. | ||||
|             parameters: | ||||
|             -   name: id | ||||
|                 in: path | ||||
|                 required: true | ||||
|                 description: The saved export id | ||||
|                 schema: | ||||
|                     type: string | ||||
|                     format: string | ||||
|             responses: | ||||
|                 200: | ||||
|                     description: "ok" | ||||
|                     content: | ||||
|                         application/json: | ||||
|                             schema: | ||||
|                                 type: string | ||||
|                                 items: | ||||
|                                     $ref: '#/components/schemas/SavedExport' | ||||
|                 403: | ||||
|                     description: "Unauthorized" | ||||
|   | ||||
| @@ -115,6 +115,24 @@ services: | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|  | ||||
|     Chill\MainBundle\Widget\: | ||||
|         resource: '../Widget/' | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|  | ||||
|     Chill\MainBundle\Widget\WidgetHandlerManager: | ||||
|         arguments: | ||||
|             $handlers: !tagged_iterator chill_main.widget_handler | ||||
|  | ||||
|     Chill\MainBundle\Widget\Widgets\WidgetNumber: | ||||
|         autoconfigure: true | ||||
|         autowire: true | ||||
|  | ||||
|     Chill\MainBundle\Widget\Widgets\WidgetBar: | ||||
|         autoconfigure: true | ||||
|         autowire: true | ||||
|  | ||||
|  | ||||
|     Chill\MainBundle\Cron\CronManager: | ||||
|         autoconfigure: true | ||||
|         autowire: true | ||||
|   | ||||
| @@ -112,4 +112,17 @@ final class AccompanyingPeriodRepository implements ObjectRepository | ||||
|  | ||||
|         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(); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user