<?php
namespace App\Controller\Backend;
use App\Controller\Base\BaseController;
use App\Entity\DashboardList;
use App\Entity\DashboardTab;
use App\Entity\TGrafik;
use App\Filter\DashboardListFilterType;
use App\Form\DashboardListType;
use App\Repository\DashboardComponentRepository;
use App\Repository\DashboardListRepository;
use App\Repository\TGrafikRepository;
use Symfony\Component\Routing\Annotation\Route;
use Kematjaya\Breadcrumb\Lib\Builder as BreacrumbBuilder;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use App\Utils\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
class DashboardListController extends BaseController
{
private $pageName = 'dashboard_list';
private $class = DashboardList::class;
/**
* @Route("/dashboard_list",name="dashboard_list")
*/
public function index(BreacrumbBuilder $builder, Request $request, PaginatorInterface $paginatorInterface)
{
$builder->add('Setting Dashboard ', "dashboard_list", array(), " <i class='fa fa-home'></i>");
$form = $this->createFormFilter(DashboardListFilterType::class);
$queryBuilder = $this->getQueryBuilder($this->class);
$queryBuilder = $this->buildFilter($request, $form, $queryBuilder)->addOrderBy("this.id", "DESC");
$this->setSessionLimit($request);
$maxPerPage = $request->getSession()->get("limit") ? $request->getSession()->get("limit") : $this->getLimit();
$pagination = $paginatorInterface->paginate($queryBuilder, $request->query->getInt('page', 1), $maxPerPage);
return $this->render('backend/dashboard_list/index.html.twig', [
'page_name' => $this->pageName,
'button_credential' => $this->buttonCredentials($this->pageName),
'filter' => $form->createView(),
'pagination' => $pagination
]);
}
/**
* @Route("/dashboard_list/form/{id}", defaults={"id"= null}, name="dashboard_list_form", methods={"POST", "GET"})
*/
public function form(?string $id = null, Request $request, DashboardListRepository $dashboardListRepository)
{
if ($id) {
$dashboardList = $dashboardListRepository->find($id);
} else {
$dashboardList = new DashboardList();
}
if (!$dashboardList) {
throw new NotFoundHttpException();
}
$form = $this->createForm(DashboardListType::class, $dashboardList, ['action' => $this->generateUrl('dashboard_list_form', ['id' => $dashboardList->getId()])]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$dashboard = $form->getData();
$dashboard->setCreatedAt(new \DateTime('now', new \DateTimeZone('Asia/Jakarta')));
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($dashboard);
$entityManager->flush();
$this->addFlash('notice', 'List dashboard berhasil disimpan');
return $this->redirectToRoute('dashboard_list');
}
return $this->render('/backend/dashboard_list/form.html.twig', ['form' => $form->createView()]);
}
/**
* @Route("/dashboard_list/{id}/delete_dashboard_list", name="dashboard_list_delete", methods={"GET"})
*/
public function delete(?string $id = null, DashboardListRepository $dashboardListRepository)
{
$dashboard_list = $dashboardListRepository->find($id);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($dashboard_list);
$entityManager->flush();
return $this->redirectToRoute('dashboard_list');
}
/**
* @Route("/add_selected", name="dashboard_list_add_selected", methods={"POST"})
*/
public function add_selected(Request $request, ObjectManager $objectManager)
{
$sessionName = $request->get("name");
$this->get('session')->set($sessionName, $request->get('selected'));
$selected = (!empty($this->get('session')->get($sessionName))) ? $this->get('session')->get($sessionName) : [];
return $this->json($selected);
}
/**
* @Route("/action_selected", name="dashboard_list_action_selected", methods={"POST"})
*/
public function action_selected(Request $request, ObjectManager $objectManager)
{
$sessionName = $request->get("name");
if ($this->isCsrfTokenValid($sessionName . '_action_selected', $request->request->get('_token'))) {
$selected = (!empty($this->get('session')->get($sessionName))) ? $this->get('session')->get($sessionName) : [];
$deleted = $objectManager->deleteByIds($this->class, $selected);
if ($deleted) {
$this->get('session')->set($sessionName, []);
$this->addFlash('success', $this->getTranslator()->trans('messages.deleted.success'));
} else {
$this->addFlash('error', $this->getTranslator()->trans('messages.deleted.error'));
}
}
return $this->redirectToRoute('dashboard_list');
}
// /**
// * @Route("/dashboard_list/{id}/preview", name="dashboard_list_preview", methods={"GET", "POST"})
// */
// public function preview(BreacrumbBuilder $builder, DashboardListRepository $dashboardListRepository, DashboardList $dashboardList, DashboardComponentRepository $dashboardComponentRepository)
// {
// $builder->add('Setting Dashboard ', "dashboard_list", array(), " <i class='fa fa-home'></i>");
// $builder->add('Preview');
// $dashboardList = $dashboardListRepository->find($dashboardList);
// $tabs = $dashboardList->getDashboardTabs()->toArray();
// usort($tabs, fn($a, $b) => $a->getUrutan() <=> $b->getUrutan());
// $componentsByTab = [];
// foreach ($tabs as $tab) {
// $componentsByTab[$tab->getId()] = $dashboardComponentRepository->findBy(['dashboard_tab' => $tab]);
// }
// return $this->render('backend/dashboard_list/preview.html.twig', [
// 'page_name' => $this->pageName,
// 'button_credential' => $this->buttonCredentials($this->pageName),
// 'dashboardList' => $dashboardList,
// 'tabs' => $tabs,
// 'componentsByTab' => $componentsByTab
// ]);
// }
/**
* @Route("/dashboard_list/{id}/preview", name="dashboard_list_preview", methods={"GET", "POST"})
*/
public function preview(
BreacrumbBuilder $builder,
DashboardListRepository $dashboardListRepository,
DashboardList $dashboardList,
DashboardComponentRepository $dashboardComponentRepository,
TGrafikRepository $tGrafikRepo,
EntityManagerInterface $em
) {
$builder->add('Setting Dashboard ', "dashboard_list", [], " <i class='fa fa-home'></i>");
$builder->add('Preview');
$dashboardList = $dashboardListRepository->find($dashboardList);
$tabs = $dashboardList->getDashboardTabs()->toArray();
usort($tabs, fn($a, $b) => $a->getUrutan() <=> $b->getUrutan());
$componentsByTab = [];
$components = [];
foreach ($tabs as $tab) {
$components = $dashboardComponentRepository->findBy(['dashboard_tab' => $tab]);
foreach ($components as $component) {
// if ($component->getType() === 'table') {
// $grafikId = $component->getExternalChartId();
// $tGrafik = $tGrafikRepo->find($grafikId);
// if ($tGrafik) {
// $columns = $this->getGrafikColumns($tGrafik);
// $component->setColumns($columns);
// $em->persist($component);
// }
// }
if ($component->getType() === 'table') {
$config = $component->getConfig();
$dataSourceType = $config['data_source_type'] ?? 't_grafik';
if ($dataSourceType === 't_grafik') {
$grafikId = $component->getExternalChartId();
$tGrafik = $tGrafikRepo->find($grafikId);
if ($tGrafik) {
$columns = $this->getGrafikColumns($tGrafik);
$columns = array_filter($columns, fn($c) => $c !== 'all');
$component->setColumns($columns);
$em->persist($component);
}
} elseif ($dataSourceType === 't_explore_data_detail') {
// Sesuaikan kolom default eksplorasi
$columns = ['no', 'periode', 'nilai'];
$component->setColumns($columns);
$em->persist($component);
}
}
if ($component->getType() === 'html') {
$grafikId = $component->getDataSource();
$tGrafik = $tGrafikRepo->find($grafikId);
if ($tGrafik) {
$conn = $em->getConnection();
$table = $tGrafik->getTabel();
// map khusus 'kategori_plant' → 'plant'
$axisX = $tGrafik->getAxisx() === 'kategori_plant' ? 'plant' : $tGrafik->getAxisx();
$axisY = $tGrafik->getAxisYIds(); // array nama kolom Y
$operation = $tGrafik->getOperation() ?: 'COUNT';
// build SELECT
$selectParts = [];
foreach ($axisY as $col) {
$selectParts[] = sprintf('%s("%s") AS "%s"', $operation, $col, strtolower($col)); // alias ke lowercase
}
$selectClause = sprintf('"%s", %s', $axisX, implode(', ', $selectParts));
$sql = sprintf('SELECT %s FROM "%s" GROUP BY "%s" ORDER BY "%s" LIMIT 1', $selectClause, $table, $axisX, $axisX);
try {
$stmt = $conn->prepare($sql);
$data = $stmt->executeQuery()->fetchAllAssociative();
} catch (\Throwable $e) {
$data = [];
}
// normalisasi key ke lowercase, termasuk axisX
$firstRow = [];
if (!empty($data[0])) {
foreach ($data[0] as $key => $val) {
$firstRow[strtolower($key)] = $val;
}
// pastikan axisX juga tersedia sebagai 'plant' bila relevan
if ($axisX !== strtolower($axisX) && isset($data[0][$axisX])) {
$firstRow[strtolower($axisX)] = $data[0][$axisX];
}
}
$template = $component->getConfig()['html_template'] ?? '';
// ↓ turunkan placeholder ke lowercase sebelum lookup
$replacedHtml = preg_replace_callback('/\{\{\s*([A-Za-z0-9_]+)\s*\}\}/', function ($m) use ($firstRow) {
$key = strtolower($m[1]);
if (array_key_exists($key, $firstRow)) {
// aman-kan value agar tidak injeksi; HTML murni dari template tetap dipertahankan
return htmlspecialchars((string) $firstRow[$key], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
return "<span style='color:red'>[undefined: {$m[1]}]</span>";
}, $template);
$component->setResolvedData([$replacedHtml]);
$em->persist($component); // pastikan entity flagged as dirty
}
}
}
$componentsByTab[$tab->getId()] = $components;
}
$em->flush();
return $this->render('backend/dashboard_list/preview.html.twig', [
'page_name' => $this->pageName,
'button_credential' => $this->buttonCredentials($this->pageName),
'dashboardList' => $dashboardList,
'tabs' => $tabs,
'componentsByTab' => $componentsByTab,
'components' => $components
]);
}
private function getGrafikColumns(TGrafik $grafik): array
{
$sumbu_x = ($grafik->getAxisx() === 'kategori_plant') ? 'plant' : $grafik->getAxisx();
$sumbu_y = $grafik->getAxisYIds();
return array_merge([$sumbu_x], $sumbu_y);
}
/**
* @Route("/dashboard_list/tab/add", name="tab_add", methods={"POST"})
*/
public function addTab(Request $request, EntityManagerInterface $em, DashboardListRepository $repo): JsonResponse
{
$id = $request->request->get('dashboard_id');
$dashboard = $repo->find($id);
if (!$dashboard) {
return new JsonResponse(['success' => false, 'message' => 'Dashboard tidak ditemukan'], 404);
}
$lastTab = $dashboard->getDashboardTabs()->last();
$lastUrutan = $lastTab ? $lastTab->getUrutan() : 0;
$tab = new DashboardTab();
$tab->setName($request->request->get('nama_tab'));
$tab->setDashboardList($dashboard);
$tab->setUrutan($lastUrutan + 1);
$tab->setCreatedAt(new \DateTime('now', new \DateTimeZone('Asia/Jakarta')));
$em->persist($tab);
$em->flush();
return new JsonResponse(['success' => true, 'tab_id' => $tab->getId()]);
}
/**
* @Route("/dashboard_list/tab/rename/{id}", methods={"POST"})
*/
public function rename($id, Request $request, EntityManagerInterface $em, DashboardTab $dashboardTab)
{
$newName = $request->request->get('nama_tab');
$dashboardTab->setName($newName);
$em->flush();
return new JsonResponse(['success' => true]);
}
/**
* @Route("/dashboard_list/tab/delete/{id}", name="tab_delete", methods={"DELETE"})
*/
public function deleteTab(DashboardTab $dashboardTab, EntityManagerInterface $em): JsonResponse
{
$em->remove($dashboardTab);
$em->flush();
return new JsonResponse(['success' => true]);
}
}