fix change template mode; fix schedule view; minor fixes
This commit is contained in:
@@ -14,4 +14,7 @@ import './styles/main.less';
|
|||||||
global.jQuery = global.$ = require('jquery');
|
global.jQuery = global.$ = require('jquery');
|
||||||
require('@fortawesome/fontawesome-free/css/all.min.css');
|
require('@fortawesome/fontawesome-free/css/all.min.css');
|
||||||
require('bootstrap');
|
require('bootstrap');
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
|
$(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
|
})
|
||||||
Vendored
+3
-1
@@ -1,9 +1,11 @@
|
|||||||
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
||||||
import './services/theme_controller'
|
import {tmp} from "./services/theme_controller";
|
||||||
|
|
||||||
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||||
export const app = startStimulusApp(require.context(
|
export const app = startStimulusApp(require.context(
|
||||||
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
||||||
true,
|
true,
|
||||||
/\.[jt]sx?$/
|
/\.[jt]sx?$/
|
||||||
));
|
));
|
||||||
|
new tmp()
|
||||||
// register any custom, 3rd party controllers here
|
// register any custom, 3rd party controllers here
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Controller } from '@hotwired/stimulus';
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
import { tmp } from '../services/theme_controller'
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
modes;
|
modes;
|
||||||
currentState;
|
currentState;
|
||||||
@@ -6,6 +8,8 @@ export default class extends Controller {
|
|||||||
this.modes = $(this.element).find('p');
|
this.modes = $(this.element).find('p');
|
||||||
this.currentState = localStorage.getItem('themeMode');
|
this.currentState = localStorage.getItem('themeMode');
|
||||||
this.changeState()
|
this.changeState()
|
||||||
|
var tmp1 = new tmp();
|
||||||
|
tmp1.update();
|
||||||
}
|
}
|
||||||
switch(event) {
|
switch(event) {
|
||||||
var mode = event.params.mode;
|
var mode = event.params.mode;
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
(() => {
|
export class tmp {
|
||||||
'use strict'
|
constructor() {
|
||||||
|
|
||||||
const getStoredTheme = () => localStorage.getItem('theme')
|
const getStoredTheme = () => localStorage.getItem('theme')
|
||||||
const setStoredTheme = theme => localStorage.setItem('theme', theme)
|
|
||||||
|
|
||||||
const getPreferredTheme = () => {
|
const getPreferredTheme = () => {
|
||||||
const storedTheme = getStoredTheme()
|
const storedTheme = getStoredTheme()
|
||||||
if (storedTheme) {
|
if (storedTheme) {
|
||||||
@@ -13,17 +10,29 @@
|
|||||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||||
}
|
}
|
||||||
|
|
||||||
const setTheme = theme => {
|
this.setTheme(getPreferredTheme())
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||||
|
const storedTheme = getStoredTheme()
|
||||||
|
if (storedTheme !== 'light' && storedTheme !== 'dark') {
|
||||||
|
this.setTheme(getPreferredTheme())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
this.showActiveTheme(getPreferredTheme())
|
||||||
|
this.update();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setTheme = theme => {
|
||||||
if (theme === 'auto') {
|
if (theme === 'auto') {
|
||||||
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
|
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.setAttribute('data-bs-theme', theme)
|
document.documentElement.setAttribute('data-bs-theme', theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setStoredTheme = theme => localStorage.setItem('theme', theme)
|
||||||
setTheme(getPreferredTheme())
|
showActiveTheme = (theme, focus = false) => {
|
||||||
|
|
||||||
const showActiveTheme = (theme, focus = false) => {
|
|
||||||
const themeSwitcher = document.querySelector('#bd-theme')
|
const themeSwitcher = document.querySelector('#bd-theme')
|
||||||
|
|
||||||
if (!themeSwitcher) {
|
if (!themeSwitcher) {
|
||||||
@@ -50,26 +59,15 @@
|
|||||||
themeSwitcher.focus()
|
themeSwitcher.focus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
update() {
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
|
||||||
const storedTheme = getStoredTheme()
|
|
||||||
if (storedTheme !== 'light' && storedTheme !== 'dark') {
|
|
||||||
setTheme(getPreferredTheme())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
|
||||||
showActiveTheme(getPreferredTheme())
|
|
||||||
|
|
||||||
document.querySelectorAll('[data-bs-theme-value]')
|
document.querySelectorAll('[data-bs-theme-value]')
|
||||||
.forEach(toggle => {
|
.forEach(toggle => {
|
||||||
toggle.addEventListener('click', () => {
|
toggle.addEventListener('click', () => {
|
||||||
const theme = toggle.getAttribute('data-bs-theme-value')
|
const theme = toggle.getAttribute('data-bs-theme-value')
|
||||||
console.log(theme)
|
this.setStoredTheme(theme)
|
||||||
setStoredTheme(theme)
|
this.setTheme(theme)
|
||||||
setTheme(theme)
|
this.showActiveTheme(theme, true)
|
||||||
showActiveTheme(theme, true)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
})()
|
}
|
||||||
@@ -59,5 +59,10 @@ body {
|
|||||||
/* background-color: lightgray;*/
|
/* background-color: lightgray;*/
|
||||||
/*}*/
|
/*}*/
|
||||||
a {
|
a {
|
||||||
text-decoration: none !important;
|
//text-decoration: none !important;
|
||||||
|
}
|
||||||
|
.spinner-grow.overdue {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use App\Enum\Months;
|
|||||||
use App\Enum\ReportStatus;
|
use App\Enum\ReportStatus;
|
||||||
use App\Enum\ReportTodoEnum;
|
use App\Enum\ReportTodoEnum;
|
||||||
use App\Helper\MonthHelper;
|
use App\Helper\MonthHelper;
|
||||||
|
use App\Services\OverdueReports;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
@@ -26,12 +27,6 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
|||||||
|
|
||||||
class BaseController extends AbstractController
|
class BaseController extends AbstractController
|
||||||
{
|
{
|
||||||
private MonthHelper $monthHelper;
|
|
||||||
|
|
||||||
public function __construct(){
|
|
||||||
$this->monthHelper = new MonthHelper();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/', name: 'index')]
|
#[Route('/', name: 'index')]
|
||||||
public function index(): Response
|
public function index(): Response
|
||||||
{
|
{
|
||||||
@@ -42,12 +37,13 @@ class BaseController extends AbstractController
|
|||||||
}
|
}
|
||||||
#[Route('/reports/{monthId}', name: 'app_base')]
|
#[Route('/reports/{monthId}', name: 'app_base')]
|
||||||
#[IsGranted('reportView')]
|
#[IsGranted('reportView')]
|
||||||
public function reportsIndex(EntityManagerInterface $entityManager, int $monthId = 0) : Response
|
public function reportsIndex(EntityManagerInterface $entityManager, OverdueReports $overdueReports, int $monthId = 0) : Response
|
||||||
{
|
{
|
||||||
|
$monthHelper = new MonthHelper($overdueReports);
|
||||||
$isOverdue = false;
|
$isOverdue = false;
|
||||||
if ($monthId > -1) {
|
if ($monthId > -1) {
|
||||||
$monthCurrent = $this->monthHelper->getCurrentMonth($monthId);
|
$monthCurrentDate = $monthHelper->getCurrentMonthDate($monthId);
|
||||||
$reportsAll = $entityManager->getRepository(Reports::class)->findAllInMonth($monthCurrent);
|
$reportsAll = $entityManager->getRepository(Reports::class)->findAllInMonth($monthCurrentDate);
|
||||||
} else {
|
} else {
|
||||||
$reportsAll = $entityManager->getRepository(Reports::class)->findAllOverdue();
|
$reportsAll = $entityManager->getRepository(Reports::class)->findAllOverdue();
|
||||||
$isOverdue = true;
|
$isOverdue = true;
|
||||||
@@ -67,10 +63,11 @@ class BaseController extends AbstractController
|
|||||||
ksort($reports);
|
ksort($reports);
|
||||||
return $this->render('reports/list.html.twig', [
|
return $this->render('reports/list.html.twig', [
|
||||||
'reportsGroup' => $reports,
|
'reportsGroup' => $reports,
|
||||||
'months' => $this->monthHelper->takeMonths(),
|
'months' => $monthHelper->takeMonths(),
|
||||||
'currentMonth' => $monthCurrent ?? null,
|
'currentMonth' => $monthCurrentDate ?? null,
|
||||||
'reportToDoList' => ReportTodoEnum::cases(),
|
'reportToDoList' => ReportTodoEnum::cases(),
|
||||||
'isOverdue' => $isOverdue,
|
'isOverdue' => $isOverdue,
|
||||||
|
'countOverdueLeft' => $overdueReports->getLeftCount()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ class ReportsController extends AbstractController
|
|||||||
$token = $request->get("token");
|
$token = $request->get("token");
|
||||||
if ($this->isCsrfTokenValid('report-status', $token)) {
|
if ($this->isCsrfTokenValid('report-status', $token)) {
|
||||||
$reportsService->setClient($report->getClient());
|
$reportsService->setClient($report->getClient());
|
||||||
$isDone = false;
|
|
||||||
if ($request->get("unDone")){
|
if ($request->get("unDone")){
|
||||||
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
||||||
"report" => $report->getId(),
|
"report" => $report->getId(),
|
||||||
@@ -30,8 +29,12 @@ class ReportsController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
$todo->setDeleted(true);
|
$todo->setDeleted(true);
|
||||||
$entityManager->persist($todo);
|
$entityManager->persist($todo);
|
||||||
|
$report->setDone(false);
|
||||||
} else {
|
} else {
|
||||||
foreach (ReportTodoEnum::cases() as $case) {
|
foreach (ReportTodoEnum::cases() as $case) {
|
||||||
|
if (!$request->get($case->value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
|
||||||
"report" => $report->getId(),
|
"report" => $report->getId(),
|
||||||
"name" => $case->value
|
"name" => $case->value
|
||||||
@@ -40,19 +43,19 @@ class ReportsController extends AbstractController
|
|||||||
$todo = new ReportsTodo();
|
$todo = new ReportsTodo();
|
||||||
$todo->setReport($report);
|
$todo->setReport($report);
|
||||||
$todo->setName($case);
|
$todo->setName($case);
|
||||||
}
|
|
||||||
if ($request->get($case->value) !== null) {
|
|
||||||
$todo->setDeleted(false);
|
|
||||||
} else {
|
} else {
|
||||||
$todo->setDeleted(true);
|
$todo->setDeleted(!$todo->isDeleted());
|
||||||
|
}
|
||||||
|
if ($todo->getName() === ReportTodoEnum::COMPLETE) {
|
||||||
|
if ($todo->isDeleted()) {
|
||||||
|
$report->setDone(false);
|
||||||
|
} else {
|
||||||
|
$report->setDone(true);
|
||||||
}
|
}
|
||||||
if ($todo->getName() === ReportTodoEnum::COMPLETE && !$todo->isDeleted()) {
|
|
||||||
$isDone = true;
|
|
||||||
}
|
}
|
||||||
$entityManager->persist($todo);
|
$entityManager->persist($todo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$report->setDone($isDone);
|
|
||||||
$entityManager->persist($report);
|
$entityManager->persist($report);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
$reportsService->tryAddNextReport();
|
$reportsService->tryAddNextReport();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class ScheduleController extends AbstractController
|
|||||||
{
|
{
|
||||||
if ($typeId == 1) {
|
if ($typeId == 1) {
|
||||||
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllCurrent();
|
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllCurrent();
|
||||||
|
$isOverdue = $entityManager->getRepository(Schedule::class)->findAllOverdue(true);
|
||||||
} else {
|
} else {
|
||||||
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllOverdue();
|
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllOverdue();
|
||||||
}
|
}
|
||||||
@@ -25,16 +26,15 @@ class ScheduleController extends AbstractController
|
|||||||
return $this->render('schedule/index.html.twig', [
|
return $this->render('schedule/index.html.twig', [
|
||||||
'typeId' => $typeId,
|
'typeId' => $typeId,
|
||||||
'schedules' => $schedulesTmp,
|
'schedules' => $schedulesTmp,
|
||||||
|
'isOverdue' => $isOverdue ?? false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/schedule_status', name: 'app_schedule_status')]
|
#[Route('/schedule_status/{id}', name: 'app_schedule_status', methods: ['POST'])]
|
||||||
public function setDone(EntityManagerInterface $entityManager, Request $request): Response
|
public function setDone(EntityManagerInterface $entityManager, Request $request, Schedule $schedule): Response
|
||||||
{
|
{
|
||||||
$scheduleId = $request->getPayload()->get('scheduleId');
|
$token = $request->get("token");
|
||||||
$token = $request->getPayload()->get("token");
|
if ($this->isCsrfTokenValid('schedule-status', $token)) {
|
||||||
if ($scheduleId && $this->isCsrfTokenValid('schedule-status', $token)) {
|
|
||||||
$schedule = $entityManager->getRepository(Schedule::class)->find($scheduleId);
|
|
||||||
$isDone = true;
|
$isDone = true;
|
||||||
if ($schedule->isDone()) {
|
if ($schedule->isDone()) {
|
||||||
$isDone = false;
|
$isDone = false;
|
||||||
|
|||||||
@@ -18,4 +18,15 @@ enum ScheduleStatus: int
|
|||||||
ScheduleStatus::COMPLETED => 'success',
|
ScheduleStatus::COMPLETED => 'success',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function borderColor(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
ScheduleStatus::TODO => '',
|
||||||
|
ScheduleStatus::INCOMING => 'warning',
|
||||||
|
ScheduleStatus::OVERDUE => 'danger',
|
||||||
|
ScheduleStatus::COMPLETED => 'success',
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,53 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace App\Helper;
|
namespace App\Helper;
|
||||||
|
|
||||||
|
use App\Services\OverdueReports;
|
||||||
|
|
||||||
class MonthHelper
|
class MonthHelper
|
||||||
{
|
{
|
||||||
|
public function __construct(private readonly OverdueReports $overdueReports){}
|
||||||
public function takeMonths() : array
|
public function takeMonths() : array
|
||||||
{
|
{
|
||||||
$startDate = new \DateTime("-6 months");
|
$startDate = new \DateTime("-6 months");
|
||||||
$startDate->modify("first day of this month");
|
$startDate->modify("first day of this month");
|
||||||
$return = [];
|
$return = [];
|
||||||
|
$overdueCounts = $this->overdueReports->getList();
|
||||||
for ($i=1; $i<=11; $i++) {
|
for ($i=1; $i<=11; $i++) {
|
||||||
$tmp = clone $startDate;
|
$tmp = clone $startDate;
|
||||||
$tmp->modify("+$i month");
|
$tmp->modify("+$i month");
|
||||||
$return[$i] = $tmp;
|
$return[$i] = [
|
||||||
|
'date' => $tmp,
|
||||||
|
'overdueCount' => 0
|
||||||
|
];
|
||||||
|
$key = $tmp->format('Y-m');
|
||||||
|
if (isset($overdueCounts[$key])) {
|
||||||
|
$return[$i]['overdueCount'] = $overdueCounts[$key];
|
||||||
|
unset($overdueCounts[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($overdueCounts) > 0) {
|
||||||
|
$this->overdueReports->setLeftCount(array_sum($overdueCounts));
|
||||||
}
|
}
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getCurrentMonth(int $monthId) : \DateTime
|
public function getCurrentMonthDate(int $monthId) : \DateTime
|
||||||
{
|
{
|
||||||
$months = $this->takeMonths();
|
$months = $this->takeMonths();
|
||||||
if ($monthId==0) {
|
if ($monthId==0) {
|
||||||
$currentMonth = intval(date("n"));
|
$currentMonth = intval(date("n"));
|
||||||
|
|
||||||
foreach ($months as $mId => $monthObj) {
|
foreach ($months as $mId => $monthObj) {
|
||||||
if ($monthObj->format("m") == $currentMonth) {
|
$date = $monthObj['date']->format('m');
|
||||||
|
if ($date == $currentMonth) {
|
||||||
$monthCurrent = $monthObj;
|
$monthCurrent = $monthObj;
|
||||||
$monthId = $mId;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$monthCurrent = $months[$monthId];
|
$monthCurrent = $months[$monthId];
|
||||||
}
|
}
|
||||||
return $monthCurrent;
|
return $monthCurrent['date'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,25 +11,49 @@ use Doctrine\Persistence\ManagerRegistry;
|
|||||||
*/
|
*/
|
||||||
class ScheduleRepository extends ServiceEntityRepository
|
class ScheduleRepository extends ServiceEntityRepository
|
||||||
{
|
{
|
||||||
|
private const _OVERDUE_DAYS_START = 15;
|
||||||
|
private const _OVERDUE_DAYS_END = 30;
|
||||||
public function __construct(ManagerRegistry $registry)
|
public function __construct(ManagerRegistry $registry)
|
||||||
{
|
{
|
||||||
parent::__construct($registry, Schedule::class);
|
parent::__construct($registry, Schedule::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findAllOverdue()
|
public function findAllOverdue(bool $onlyCount = false) : array|int
|
||||||
{
|
{
|
||||||
$dateEnd = new \DateTime("now");
|
$dateEnd = new \DateTime("now");
|
||||||
|
$dateEnd->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
$reports = $this->createQueryBuilder('s')
|
$reports = $this->createQueryBuilder('s')
|
||||||
->where('s.isDone = :isDone')
|
->where('s.isDone = :isDone')
|
||||||
->andWhere('s.dateEnd < :dateEnd')
|
->andWhere('s.dateEnd < :dateEnd')
|
||||||
// ->andWhere('s.isDelete = :isDelete')
|
// ->andWhere('s.isDelete = :isDelete')
|
||||||
->setParameter('isDone', 0)
|
->setParameter('isDone', 0)
|
||||||
|
// ->setParameter('isDelete', 0)
|
||||||
|
->setParameter('dateEnd', $dateEnd);
|
||||||
|
|
||||||
|
if ($onlyCount) {
|
||||||
|
$reports->select('COUNT(s.id)');
|
||||||
|
return $reports->getQuery()->getSingleScalarResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $reports->getQuery()->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isOverdue(): bool
|
||||||
|
{
|
||||||
|
$dateEnd = new \DateTime("now");
|
||||||
|
$dateEnd->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
|
$query = $this->createQueryBuilder('s')
|
||||||
|
->select('count(s.id)')
|
||||||
|
->where('s.isDone = :isDone')
|
||||||
|
->andWhere('s.dateEnd < :dateEnd')
|
||||||
|
// ->andWhere('s.isDelete = :isDelete')
|
||||||
|
->setParameter('isDone', 0)
|
||||||
// ->setParameter('isDelete', 0)
|
// ->setParameter('isDelete', 0)
|
||||||
->setParameter('dateEnd', $dateEnd)
|
->setParameter('dateEnd', $dateEnd)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult();
|
->getSingleScalarResult();
|
||||||
|
|
||||||
return $reports;
|
trigger_error(var_export($query,true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,9 +63,9 @@ class ScheduleRepository extends ServiceEntityRepository
|
|||||||
{
|
{
|
||||||
$date = new \DateTime();
|
$date = new \DateTime();
|
||||||
$dateStart = clone $date;
|
$dateStart = clone $date;
|
||||||
$dateStart->modify("-15 days");
|
$dateStart->modify("-".self::_OVERDUE_DAYS_START." days");
|
||||||
$dateEnd = clone $date;
|
$dateEnd = clone $date;
|
||||||
$dateEnd->modify("+30 days");
|
$dateEnd->modify("+".self::_OVERDUE_DAYS_END." days");
|
||||||
return $this->createQueryBuilder('r')
|
return $this->createQueryBuilder('r')
|
||||||
->where('r.dateEnd >= :dateStart')
|
->where('r.dateEnd >= :dateStart')
|
||||||
->andWhere('r.dateEnd <= :dateEnd')
|
->andWhere('r.dateEnd <= :dateEnd')
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace App\Services;
|
||||||
|
use App\Entity\Reports;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
class OverdueReports
|
||||||
|
{
|
||||||
|
private array $list;
|
||||||
|
private int $leftCount = 0;
|
||||||
|
public function __construct(private readonly EntityManager $entity){
|
||||||
|
$this->list = $this->takeOverdueList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getList(): array
|
||||||
|
{
|
||||||
|
return $this->list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLeftCount(int $leftCount): void
|
||||||
|
{
|
||||||
|
$this->leftCount = $leftCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLeftCount(): int
|
||||||
|
{
|
||||||
|
return $this->leftCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function takeOverdueList() : array
|
||||||
|
{
|
||||||
|
$reports = $this->entity->getRepository(Reports::class)->findAllOverdue();
|
||||||
|
if (!$reports) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$toReturn = [];
|
||||||
|
/** @var Reports $report */
|
||||||
|
foreach ($reports as $report) {
|
||||||
|
$date = $report->getDateStart()->format('Y-m');
|
||||||
|
if (!array_key_exists($date, $toReturn)) {
|
||||||
|
$toReturn[$date] = 1;
|
||||||
|
} else {
|
||||||
|
$toReturn[$date]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $toReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +1,20 @@
|
|||||||
{% macro month_menu(routeName, months, currentMonth) %}
|
{% macro month_menu(routeName, months, currentMonth, countOverdueLeft) %}
|
||||||
<div class="row reports-months-all">
|
<div class="row reports-months-all">
|
||||||
{# <div class="col">#}
|
|
||||||
{# <div class="card">#}
|
|
||||||
{# <a href="{{ path(routeName, {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>#}
|
|
||||||
{# </div>#}
|
|
||||||
{# </div>#}
|
|
||||||
{# {% for id,month in months %}#}
|
|
||||||
{# {% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}#}
|
|
||||||
{# <div class="col col-xxl-1 col-xl-2 col-lg-2 col-md-3 col-sm-3 col-4">#}
|
|
||||||
{# <div class="card">#}
|
|
||||||
{# <a href="{{ path(routeName,{monthId: id}) }}" class="btn {% if isCurrent %}btn-success{% else %}btn-secondary{% endif %}">#}
|
|
||||||
{# {% if routeName=='app_schedule' %}#}
|
|
||||||
{# {{ id }}#}
|
|
||||||
{# {% else %}#}
|
|
||||||
{# {{ month | date("Y-m") }}#}
|
|
||||||
{# {% endif %}#}
|
|
||||||
{# </a>#}
|
|
||||||
{# </div>#}
|
|
||||||
{# </div>#}
|
|
||||||
{# {% endfor %}#}
|
|
||||||
<ul class="nav nav-underline nav-fill">
|
<ul class="nav nav-underline nav-fill">
|
||||||
<li class="nav-item">
|
<li class="nav-item position-relative">
|
||||||
<a href="{{ path(routeName, {monthId:-1}) }}" class="nav-link {% if currentMonth is null %}active{% endif %}">Zaległe</a>
|
<a href="{{ path(routeName, {monthId:-1}) }}" class="nav-link {% if currentMonth is null %}active{% endif %}">Zaległe</a>
|
||||||
|
{% if countOverdueLeft > 0 %}
|
||||||
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% for id,month in months %}
|
{% for id,obj in months %}
|
||||||
|
{% set month = obj.date %}
|
||||||
{% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}
|
{% set isCurrent = currentMonth is not null and month | date("Y-m") == currentMonth | date("Y-m") %}
|
||||||
<li class="nav-item">
|
<li class="nav-item position-relative"
|
||||||
|
{% if obj.overdueCount > 0 %}
|
||||||
|
data-toggle="tooltip" data-bs-placement="bottom" title="Zaległe sprawozdania do zrobienia"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
<a class="nav-link {% if isCurrent %} active{% endif %}" href="{{ path(routeName,{monthId: id}) }}">
|
<a class="nav-link {% if isCurrent %} active{% endif %}" href="{{ path(routeName,{monthId: id}) }}">
|
||||||
{% if routeName=='app_schedule' %}
|
{% if routeName=='app_schedule' %}
|
||||||
{{ id }}
|
{{ id }}
|
||||||
@@ -33,6 +22,9 @@
|
|||||||
{{ month | date("Y-m") }}
|
{{ month | date("Y-m") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
|
{% if obj.overdueCount > 0 %}
|
||||||
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% import 'navigation/switch_months.html.twig' as navigation %}
|
{% import 'navigation/switch_months.html.twig' as navigation %}
|
||||||
{% import 'reports/listInclude.html.twig' as sets %}
|
{% import 'reports/listInclude.html.twig' as sets %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{{ navigation.month_menu('app_base',months,currentMonth) }}
|
{{ navigation.month_menu('app_base',months,currentMonth,countOverdueLeft) }}
|
||||||
<div class="
|
<div class="
|
||||||
row
|
row
|
||||||
d-flex
|
d-flex
|
||||||
|
|||||||
@@ -3,20 +3,27 @@
|
|||||||
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('report-status') }}">
|
||||||
<div class="btn-group" role="group" aria-label="Todos">
|
<div class="btn-group" role="group" aria-label="Todos">
|
||||||
{% for todo in reportToDoList %}
|
{% for todo in reportToDoList %}
|
||||||
<input onchange="this.form.submit()"
|
<button type="submit" class="btn-check" name="{{ todo.value }}" value='1' id="checkboxToDo{{ todo.value }}Id{{ report.id }}"></button>
|
||||||
name="{{ todo.value }}"
|
{# <input onchange="this.form.submit()"#}
|
||||||
type="checkbox"
|
{# name="{{ todo.value }}"#}
|
||||||
class="btn-check"
|
{# type="checkbox"#}
|
||||||
id="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
{# class="btn-check"#}
|
||||||
|
{# id="checkboxToDo{{ todo.value }}Id{{ report.id }}"#}
|
||||||
|
{# {% if report.isReportsTodo(todo) %}#}
|
||||||
|
{# checked="checked"#}
|
||||||
|
{# {% endif %}#}
|
||||||
|
{# {% if not is_granted('reportEdit') %}#}
|
||||||
|
{# disabled#}
|
||||||
|
{# {% endif %}#}
|
||||||
|
{# autocomplete="off"#}
|
||||||
|
{# >#}
|
||||||
|
<label class="btn
|
||||||
{% if report.isReportsTodo(todo) %}
|
{% if report.isReportsTodo(todo) %}
|
||||||
checked="checked"
|
btn-{{ reportEnum.checkboxColor }}
|
||||||
|
{% else %}
|
||||||
|
btn-outline-{{ reportEnum.checkboxColor }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not is_granted('reportEdit') %}
|
d-flex align-items-center"
|
||||||
disabled
|
|
||||||
{% endif %}
|
|
||||||
autocomplete="off"
|
|
||||||
>
|
|
||||||
<label class="btn btn-outline-{{ reportEnum.checkboxColor }} d-flex align-items-center"
|
|
||||||
for="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
for="checkboxToDo{{ todo.value }}Id{{ report.id }}"
|
||||||
data-toggle="tooltip" data-placement="bottom" title="{{ todo.takeLang }}">
|
data-toggle="tooltip" data-placement="bottom" title="{{ todo.takeLang }}">
|
||||||
<i class="fa fa-solid fa-{{ todo.takeIcon }}"> </i>
|
<i class="fa fa-solid fa-{{ todo.takeIcon }}"> </i>
|
||||||
|
|||||||
@@ -2,44 +2,42 @@
|
|||||||
{% import 'navigation/switch_months.html.twig' as navigation %}
|
{% import 'navigation/switch_months.html.twig' as navigation %}
|
||||||
{% block title %}Harmonogramy{% endblock %}
|
{% block title %}Harmonogramy{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{# {{ navigation.month_menu('app_schedule',months,currentMonth) }}#}
|
<div class="row reports-months-all">
|
||||||
<div class="row row-cols-2 reports-months-all">
|
<ul class="nav nav-underline nav-fill">
|
||||||
<div class="col">
|
<li class="nav-item position-relative">
|
||||||
<a href="{{ path('app_schedule', {typeId:2}) }}" class="card text-center text-white {% if typeId == 2 %}bg-primary{% else %}bg-secondary{% endif %}">
|
<a href="{{ path('app_schedule', {typeId:2}) }}" class="nav-link {% if typeId == 2 %}active{% endif %}">Zaległe</a>
|
||||||
<div class="card-title"><h2>Zaległe</h2></div>
|
{% if isOverdue %}
|
||||||
</a>
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
{# <a href="{{ path('app_schedule', {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>#}
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ path('app_schedule', {typeId:1}) }}" class="nav-link {% if typeId == 1 %}active{% endif %}">Aktualne</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="row row-cols-auto schedule-all">
|
||||||
<a href="{{ path('app_schedule', {typeId:1}) }}" class="card text-center text-white {% if typeId == 1 %}bg-primary{% else %}bg-secondary{% endif %}">
|
|
||||||
<div class="card-title"><h2>Aktualne</h2></div>
|
|
||||||
</a>
|
|
||||||
{# <a href="{{ path('app_schedule', {monthId:-1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Zaległe</a>#}
|
|
||||||
</div>
|
|
||||||
{# <div class="col">#}
|
|
||||||
{# <a href="{{ path('app_schedule', {monthId:1}) }}" class="btn {% if currentMonth is null %}btn-success{% else %}btn-secondary{% endif %}">Aktualne</a>#}
|
|
||||||
{# </div>#}
|
|
||||||
</div>
|
|
||||||
<div class="row row-cols-auto reports-all">
|
|
||||||
{% for schedule in schedules %}
|
{% for schedule in schedules %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card text-white bg-{{ schedule.getStatus.backgroundColor }}">
|
<div class="card border-{{ schedule.getStatus.borderColor }}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">
|
<h5 class="card-title">
|
||||||
{% if is_granted('clientView') %}
|
{% if is_granted('clientView') %}
|
||||||
<a href="{{ path('app_client',{id: schedule.client.id}) }}" class="link-dark">{{ schedule.client.strName }}</a>
|
<a href="{{ path('app_client',{id: schedule.client.id}) }}">{{ schedule.client.strName }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="link-dark">{{ schedule.client.strName }}</div>
|
<div class="link-dark">{{ schedule.client.strName }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h5>
|
</h5>
|
||||||
|
{% if enum(schedule.getStatus, 'OVERDUE') %}
|
||||||
|
<h6 class="card-subtitle text-muted text-danger-emphasis">Czas minął: {{ schedule.getTimeLeft }} dni</h6>
|
||||||
|
<div class="spinner-grow spinner-grow-sm text-danger overdue"></div>
|
||||||
|
{% else %}
|
||||||
<h6 class="card-subtitle text-muted">Pozostały czas: {{ schedule.getTimeLeft }} dni</h6>
|
<h6 class="card-subtitle text-muted">Pozostały czas: {{ schedule.getTimeLeft }} dni</h6>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<form action="{{ path('app_schedule_status') }}" method="post">
|
<form action="{{ path('app_schedule_status',{id:schedule.id}) }}" method="post">
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('schedule-status') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('schedule-status') }}">
|
||||||
<input type="hidden" name="scheduleId" value="{{ schedule.id }}">
|
<button type="submit" class="btn btn-outline-success w-100">Wysłano</button>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success">Wysłano</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user