Release 2.0.13 (#3955)
- added missing escape to prevent HTML injection - added missing color attribute - upgrade theme - use dropdown submenu if title is set, otherwise dropdown tends to get too long - allow to use card-table instead of card-body - added `required` attribute to username and password field - fix pagination back to page 1 - prevent tag name too long - re-add missing user preferences link
This commit is contained in:
@@ -115,18 +115,24 @@ export default class KimaiFormSelect extends KimaiFormPlugin {
|
||||
if (node.dataset['renderer'] !== undefined && node.dataset['renderer'] === 'color') {
|
||||
options.render = {...render, ...{
|
||||
option: function(data, escape) {
|
||||
let color = data.value;
|
||||
let item = '<div class="list-group-item border-0 p-1 ps-2 text-nowrap">';
|
||||
if (data.color !== undefined) {
|
||||
color = data.color;
|
||||
item += '<span style="background-color:' + data.color + '" class="color-choice-item"> </span>';
|
||||
} else {
|
||||
item += '<span class="color-choice-item"> </span>';
|
||||
}
|
||||
return '<div class="list-group-item border-0 p-1 ps-2 text-nowrap"><span style="background-color:' + color + '" class="color-choice-item"> </span>' + escape(data.text) + '</div>';
|
||||
item += escape(data.text) + '</div>';
|
||||
return item;
|
||||
},
|
||||
item: function(data, escape) {
|
||||
let color = data.value;
|
||||
let item = '<div class="text-nowrap">';
|
||||
if (data.color !== undefined) {
|
||||
color = data.color;
|
||||
item += '<span style="background-color:' + data.color + '" class="color-choice-item"> </span>';
|
||||
} else {
|
||||
item += '<span class="color-choice-item"> </span>';
|
||||
}
|
||||
return '<div class="text-nowrap"><span style="background-color:' + color + '" class="color-choice-item"> </span>' + escape(data.text) + '</div>';
|
||||
item += escape(data.text) + '</div>';
|
||||
return item;
|
||||
}
|
||||
}};
|
||||
} else {
|
||||
|
||||
@@ -65,6 +65,8 @@ export default class KimaiTeamForm extends KimaiFormPlugin {
|
||||
*/
|
||||
_createMember(option)
|
||||
{
|
||||
/** @type {KimaiEscape} ESCAPER */
|
||||
const ESCAPER = this.getPlugin('escape');
|
||||
const prototype = this._getPrototype();
|
||||
let counter = prototype.dataset['widgetCounter'] || prototype.childNodes.length;
|
||||
let newWidget = prototype.dataset['prototype'];
|
||||
@@ -72,11 +74,11 @@ export default class KimaiTeamForm extends KimaiFormPlugin {
|
||||
newWidget = newWidget.replace(/__name__/g, counter);
|
||||
|
||||
newWidget = newWidget.replace(/#000000/g, KimaiColor.calculateContrastColor(option.dataset.color));
|
||||
newWidget = newWidget.replace(/__DISPLAY__/g, option.dataset.display);
|
||||
newWidget = newWidget.replace(/__DISPLAY__/g, ESCAPER.escapeForHtml(option.dataset.display));
|
||||
newWidget = newWidget.replace(/__COLOR__/g, option.dataset.color);
|
||||
newWidget = newWidget.replace(/__INITIALS__/g, option.dataset.initials);
|
||||
newWidget = newWidget.replace(/__TITLE__/g, option.dataset.title);
|
||||
newWidget = newWidget.replace(/__USERNAME__/g, option.text);
|
||||
newWidget = newWidget.replace(/__INITIALS__/g, ESCAPER.escapeForHtml(option.dataset.initials));
|
||||
newWidget = newWidget.replace(/__TITLE__/g, ESCAPER.escapeForHtml(option.dataset.title));
|
||||
newWidget = newWidget.replace(/__USERNAME__/g, ESCAPER.escapeForHtml(option.text));
|
||||
|
||||
prototype.dataset['widgetCounter'] = (++counter).toString();
|
||||
|
||||
|
||||
@@ -163,7 +163,12 @@ export default class KimaiToolbar extends KimaiPlugin {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
let urlParts = target.href.split('/');
|
||||
pager.value = urlParts[urlParts.length-1];
|
||||
let pageNumber = urlParts[urlParts.length - 1];
|
||||
// page number usually is the default value and is therefor missing from the URL
|
||||
if (!/\d/.test(pageNumber)) {
|
||||
pageNumber = 1;
|
||||
}
|
||||
pager.value = pageNumber;
|
||||
pager.dispatchEvent(new Event('change'));
|
||||
document.dispatchEvent(new Event('pagination-change'));
|
||||
return false;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"friendsofsymfony/rest-bundle": "^3.0",
|
||||
"gedmo/doctrine-extensions": "^3.6",
|
||||
"jms/serializer-bundle": "^5.0",
|
||||
"kevinpapst/tabler-bundle": "dev-main",
|
||||
"kevinpapst/tabler-bundle": "^0.14",
|
||||
"league/csv": "^9.4",
|
||||
"mpdf/mpdf": "^8.0",
|
||||
"nelmio/api-doc-bundle": "^4.0",
|
||||
|
||||
70
composer.lock
generated
70
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "dfc85100677cacc71615a6442646ff39",
|
||||
"content-hash": "1bdbdd73cd12f5111c5e34db51d7ad10",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -816,21 +816,21 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/doctrine-bundle",
|
||||
"version": "2.8.3",
|
||||
"version": "2.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/DoctrineBundle.git",
|
||||
"reference": "fd67ba64db3c806f626a33dcab15a4db0c77652e"
|
||||
"reference": "9819c00c2eea750b99902f244309b824911b72b2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/fd67ba64db3c806f626a33dcab15a4db0c77652e",
|
||||
"reference": "fd67ba64db3c806f626a33dcab15a4db0c77652e",
|
||||
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/9819c00c2eea750b99902f244309b824911b72b2",
|
||||
"reference": "9819c00c2eea750b99902f244309b824911b72b2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/cache": "^1.11 || ^2.0",
|
||||
"doctrine/dbal": "^3.4.0",
|
||||
"doctrine/dbal": "^3.6.0",
|
||||
"doctrine/persistence": "^2.2 || ^3",
|
||||
"doctrine/sql-formatter": "^1.0.1",
|
||||
"php": "^7.4 || ^8.0",
|
||||
@@ -846,11 +846,12 @@
|
||||
"conflict": {
|
||||
"doctrine/annotations": ">=3.0",
|
||||
"doctrine/orm": "<2.11 || >=3.0",
|
||||
"twig/twig": "<1.34 || >=2.0,<2.4"
|
||||
"twig/twig": "<1.34 || >=2.0 <2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1 || ^2",
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"doctrine/deprecations": "^1.0",
|
||||
"doctrine/orm": "^2.11 || ^3.0",
|
||||
"friendsofphp/proxy-manager-lts": "^1.0",
|
||||
"phpunit/phpunit": "^9.5.26 || ^10.0",
|
||||
@@ -911,7 +912,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/DoctrineBundle/issues",
|
||||
"source": "https://github.com/doctrine/DoctrineBundle/tree/2.8.3"
|
||||
"source": "https://github.com/doctrine/DoctrineBundle/tree/2.9.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -927,7 +928,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T09:32:42+00:00"
|
||||
"time": "2023-03-23T20:02:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/doctrine-migrations-bundle",
|
||||
@@ -2415,16 +2416,16 @@
|
||||
},
|
||||
{
|
||||
"name": "kevinpapst/tabler-bundle",
|
||||
"version": "dev-main",
|
||||
"version": "0.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kevinpapst/TablerBundle.git",
|
||||
"reference": "f0a8cdae6b4a243ee9acce60e2ffbb5f0c107c03"
|
||||
"reference": "49db98ed5923cdd45aeb4316f08c914979722731"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kevinpapst/TablerBundle/zipball/f0a8cdae6b4a243ee9acce60e2ffbb5f0c107c03",
|
||||
"reference": "f0a8cdae6b4a243ee9acce60e2ffbb5f0c107c03",
|
||||
"url": "https://api.github.com/repos/kevinpapst/TablerBundle/zipball/49db98ed5923cdd45aeb4316f08c914979722731",
|
||||
"reference": "49db98ed5923cdd45aeb4316f08c914979722731",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2454,7 +2455,6 @@
|
||||
"suggest": {
|
||||
"knplabs/knp-menu-bundle": "Allows easy menu integration"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -2474,7 +2474,7 @@
|
||||
"description": "Admin/Backend theme bundle for Symfony based on Tabler.io",
|
||||
"support": {
|
||||
"issues": "https://github.com/kevinpapst/TablerBundle/issues",
|
||||
"source": "https://github.com/kevinpapst/TablerBundle/tree/main"
|
||||
"source": "https://github.com/kevinpapst/TablerBundle/tree/0.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2486,7 +2486,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-03-23T14:18:33+00:00"
|
||||
"time": "2023-03-29T10:36:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-escaper",
|
||||
@@ -11165,16 +11165,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.7",
|
||||
"version": "1.10.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "b10ceb526d9607903c5b2673f1fc8775dbe48975"
|
||||
"reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/b10ceb526d9607903c5b2673f1fc8775dbe48975",
|
||||
"reference": "b10ceb526d9607903c5b2673f1fc8775dbe48975",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/0166aef76e066f0dd2adc2799bdadfa1635711e9",
|
||||
"reference": "0166aef76e066f0dd2adc2799bdadfa1635711e9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11223,7 +11223,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-03-16T15:24:20+00:00"
|
||||
"time": "2023-03-24T10:28:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-doctrine",
|
||||
@@ -11297,16 +11297,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
"version": "1.3.10",
|
||||
"version": "1.3.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||
"reference": "4cc5c6cc38e56bce7ea47c4091814e516d172dc3"
|
||||
"reference": "9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4cc5c6cc38e56bce7ea47c4091814e516d172dc3",
|
||||
"reference": "4cc5c6cc38e56bce7ea47c4091814e516d172dc3",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c",
|
||||
"reference": "9e1b9de6d260461f6e99b6a8f2dbb0bbb98b579c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11343,22 +11343,22 @@
|
||||
"description": "PHPUnit extensions and rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.10"
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.11"
|
||||
},
|
||||
"time": "2023-03-02T10:25:13+00:00"
|
||||
"time": "2023-03-25T19:42:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2"
|
||||
"reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b7dd96a5503919a43b3cd06a2dced9d4252492f2",
|
||||
"reference": "b7dd96a5503919a43b3cd06a2dced9d4252492f2",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b21c03d4f6f3a446e4311155f4be9d65048218e6",
|
||||
"reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11392,9 +11392,9 @@
|
||||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.0"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.1"
|
||||
},
|
||||
"time": "2023-02-21T10:17:10+00:00"
|
||||
"time": "2023-03-29T14:47:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-symfony",
|
||||
@@ -13345,9 +13345,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"kevinpapst/tabler-bundle": 20
|
||||
},
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
||||
70
phpstan.neon
70
phpstan.neon
@@ -1310,41 +1310,11 @@ parameters:
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ProjectViewController.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method modify\\(\\) on DateTime\\|null\\.$#"
|
||||
count: 4
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Cannot clone non\\-object variable \\$start of type DateTime\\|null\\.$#"
|
||||
count: 3
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Controller\\\\Reporting\\\\ReportUsersMonthController\\:\\:getData\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$begin of class App\\\\Model\\\\DailyStatistic constructor expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$begin of method App\\\\Timesheet\\\\TimesheetStatisticService\\:\\:getDailyStatistics\\(\\) expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$end of class App\\\\Model\\\\DailyStatistic constructor expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$end of method App\\\\Timesheet\\\\TimesheetStatisticService\\:\\:getDailyStatistics\\(\\) expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$users of method App\\\\Timesheet\\\\TimesheetStatisticService\\:\\:getDailyStatistics\\(\\) expects array\\<App\\\\Entity\\\\User\\>, iterable\\<App\\\\Entity\\\\User\\> given\\.$#"
|
||||
count: 1
|
||||
@@ -1385,51 +1355,11 @@ parameters:
|
||||
count: 1
|
||||
path: src/Controller/Reporting/ReportUsersYearController.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method modify\\(\\) on DateTime\\|null\\.$#"
|
||||
count: 4
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Cannot clone non\\-object variable \\$start of type DateTime\\|null\\.$#"
|
||||
count: 3
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Controller\\\\Reporting\\\\UserMonthController\\:\\:getData\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$begin of class App\\\\Model\\\\DailyStatistic constructor expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$begin of method App\\\\Controller\\\\Reporting\\\\AbstractUserReportController\\:\\:prepareReport\\(\\) expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$end of class App\\\\Model\\\\DailyStatistic constructor expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$end of method App\\\\Controller\\\\Reporting\\\\AbstractUserReportController\\:\\:prepareReport\\(\\) expects DateTime, DateTime\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$user of class App\\\\Model\\\\DailyStatistic constructor expects App\\\\Entity\\\\User, App\\\\Entity\\\\User\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$user of method App\\\\Controller\\\\Reporting\\\\AbstractUserReportController\\:\\:prepareReport\\(\\) expects App\\\\Entity\\\\User, App\\\\Entity\\\\User\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/Controller/Reporting/UserMonthController.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Controller\\\\Reporting\\\\UserWeekController\\:\\:getData\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
public/build/app.cd312ca8.js
Normal file
2
public/build/app.cd312ca8.js
Normal file
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
||||
"app": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/app.a6b63f34.js"
|
||||
"/build/app.cd312ca8.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/app.b10b16e5.css"
|
||||
@@ -63,7 +63,7 @@
|
||||
},
|
||||
"integrity": {
|
||||
"/build/runtime.f0079159.js": "sha384-H22sAW1aTvyIPqvHOvGXWSWTxf0y6mptp+MsVmyXCfjx/WJjBbhX9gbUZ+qIuihV",
|
||||
"/build/app.a6b63f34.js": "sha384-gYC58lsaQMGHSI811cimIwsqDcwhnKasGWsvFQODG0FrxVb2dDV9VvtFo9V5I8JL",
|
||||
"/build/app.cd312ca8.js": "sha384-lS1VK+quldXkQU0DjsipiX8sXWvojX/NY0+kAUHFh69HlZZG36ubhkNbcV0crl35",
|
||||
"/build/app.b10b16e5.css": "sha384-dwEgmHAQRm4PP7XTYkJfIoB+Iumd+0WuH5FyoC/+qC3WQ/e1gCTmlx9M2mIBxPuK",
|
||||
"/build/export-pdf.587575e7.js": "sha384-J50GStmmfVwUTN4dIRQ02eg9hyzGFPSzpTtpPody92j0V6zCqw+s5l8+ZhVTugeW",
|
||||
"/build/export-pdf.d8a6c23b.css": "sha384-ztepocHE4rnGE9eKZ4kL6jTKaePUyiwiB9TjJjstjpf/ckcKg1HedrEOOk/8ElJg",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"build/app.css": "/build/app.b10b16e5.css",
|
||||
"build/app.js": "/build/app.a6b63f34.js",
|
||||
"build/app.js": "/build/app.cd312ca8.js",
|
||||
"build/export-pdf.css": "/build/export-pdf.d8a6c23b.css",
|
||||
"build/export-pdf.js": "/build/export-pdf.587575e7.js",
|
||||
"build/invoice.css": "/build/invoice.3c80ee80.css",
|
||||
|
||||
@@ -17,11 +17,11 @@ class Constants
|
||||
/**
|
||||
* The current release version
|
||||
*/
|
||||
public const VERSION = '2.0.12';
|
||||
public const VERSION = '2.0.13';
|
||||
/**
|
||||
* The current release: major * 10000 + minor * 100 + patch
|
||||
*/
|
||||
public const VERSION_ID = 20012;
|
||||
public const VERSION_ID = 20013;
|
||||
/**
|
||||
* The software name
|
||||
*/
|
||||
|
||||
@@ -87,6 +87,7 @@ final class ReportUsersMonthController extends AbstractController
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
}
|
||||
|
||||
/** @var \DateTime $start */
|
||||
$start = $values->getDate();
|
||||
$start->modify('first day of 00:00:00');
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Controller\Reporting;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\DailyStatistic;
|
||||
use App\Reporting\MonthByUser\MonthByUser;
|
||||
use App\Reporting\MonthByUser\MonthByUserForm;
|
||||
@@ -64,12 +65,14 @@ final class UserMonthController extends AbstractUserReportController
|
||||
$values->setDate($dateTimeFactory->getStartOfMonth());
|
||||
}
|
||||
|
||||
/** @var \DateTime $start */
|
||||
$start = $values->getDate();
|
||||
$start->modify('first day of 00:00:00');
|
||||
|
||||
$end = clone $start;
|
||||
$end->modify('last day of 23:59:59');
|
||||
|
||||
/** @var User $selectedUser */
|
||||
$selectedUser = $values->getUser();
|
||||
|
||||
$previousMonth = clone $start;
|
||||
|
||||
@@ -55,12 +55,12 @@ final class TagFixtures extends Fixture
|
||||
$tagName = $faker->text(rand(5, 10));
|
||||
}
|
||||
|
||||
if (\in_array($tagName, $existing)) {
|
||||
if (\in_array(mb_strtolower($tagName), $existing, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing[] = $tagName;
|
||||
$tag->setName($tagName);
|
||||
$existing[] = mb_strtolower($tagName);
|
||||
$tag->setName(mb_substr($tagName, 0, 100));
|
||||
|
||||
$manager->persist($tag);
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
namespace App\DataFixtures;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Tag;
|
||||
use App\Entity\Timesheet;
|
||||
@@ -58,12 +57,8 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface
|
||||
|
||||
public function load(ObjectManager $manager): void
|
||||
{
|
||||
$results = $this->findRandom($manager, Customer::class, 50);
|
||||
|
||||
$allUser = $this->getAllUsers($manager);
|
||||
|
||||
$faker = Factory::create();
|
||||
|
||||
$all = 0;
|
||||
|
||||
foreach ($allUser as $user) {
|
||||
|
||||
@@ -47,6 +47,10 @@ final class UserSubscriber extends AbstractActionsSubscriber
|
||||
$event->addActionToSubmenu('edit', $id, $action);
|
||||
}
|
||||
|
||||
if ($this->isGranted('preferences', $user)) {
|
||||
$event->addConfig($this->path('user_profile_preferences', ['username' => $user->getUserIdentifier()]));
|
||||
}
|
||||
|
||||
if (($event->getUser()->getId() === $user->getId() && $this->isGranted('report:user')) || $this->isGranted('report:other')) {
|
||||
$event->addActionToSubmenu('report', 'weekly', ['url' => $this->path('report_user_week', ['user' => $user->getId()]), 'translation_domain' => 'reporting', 'title' => 'report_user_week']);
|
||||
$event->addActionToSubmenu('report', 'monthly', ['url' => $this->path('report_user_month', ['user' => $user->getId()]), 'translation_domain' => 'reporting', 'title' => 'report_user_month']);
|
||||
|
||||
@@ -60,7 +60,7 @@ final class TagArrayToStringTransformer implements DataTransformerInterface
|
||||
|
||||
foreach ($newNames as $name) {
|
||||
$tag = new Tag();
|
||||
$tag->setName($name);
|
||||
$tag->setName(mb_substr($name, 0, 100));
|
||||
$tags[] = $tag;
|
||||
|
||||
// new tags persist automatically thanks to the cascade={"persist"}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Form\Type;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Constants;
|
||||
use App\Utils\Color;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
@@ -39,6 +40,13 @@ final class ColorChoiceType extends AbstractType implements DataTransformerInter
|
||||
],
|
||||
'label' => 'color',
|
||||
'empty_data' => null,
|
||||
'choice_attr' => function ($color, $name) {
|
||||
if ($color === null) {
|
||||
$color = (new Color())->getRandom($name);
|
||||
}
|
||||
|
||||
return ['data-color' => $color];
|
||||
},
|
||||
];
|
||||
|
||||
$choices = [];
|
||||
|
||||
@@ -80,7 +80,7 @@ final class TagsSelectType extends AbstractType
|
||||
$newNames = array_diff($newNames, $foundTagNames);
|
||||
foreach ($newNames as $name) {
|
||||
$tag = new Tag();
|
||||
$tag->setName($name);
|
||||
$tag->setName(mb_substr($name, 0, 100));
|
||||
$this->tagRepository->saveTag($tag);
|
||||
$newData[] = $tag->getId();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace App\Model;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\Statistic\StatisticDate;
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class DailyStatistic implements DateStatisticInterface
|
||||
@@ -19,16 +18,14 @@ final class DailyStatistic implements DateStatisticInterface
|
||||
/**
|
||||
* @var array<string, StatisticDate>
|
||||
*/
|
||||
private $days = [];
|
||||
private $begin;
|
||||
private $end;
|
||||
private $user;
|
||||
private array $days = [];
|
||||
private DateTimeInterface $begin;
|
||||
private DateTimeInterface $end;
|
||||
|
||||
public function __construct(DateTime $begin, DateTime $end, User $user)
|
||||
public function __construct(DateTimeInterface $begin, DateTimeInterface $end, private User $user)
|
||||
{
|
||||
$this->begin = clone $begin;
|
||||
$this->end = clone $end;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function getUser(): User
|
||||
@@ -42,7 +39,7 @@ final class DailyStatistic implements DateStatisticInterface
|
||||
return;
|
||||
}
|
||||
|
||||
$tmp = clone $this->begin;
|
||||
$tmp = \DateTime::createFromInterface($this->begin);
|
||||
$tmp->setTime(0, 0, 0);
|
||||
while ($tmp < $this->end) {
|
||||
$id = $tmp->format('Y-m-d');
|
||||
|
||||
@@ -116,7 +116,7 @@ final class LocaleFormatExtensions extends AbstractExtension implements LocaleAw
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
public function isWeekend(DateTime|string|null $dateTime): bool
|
||||
public function isWeekend(\DateTimeInterface|string|null $dateTime): bool
|
||||
{
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
return false;
|
||||
@@ -141,7 +141,7 @@ final class LocaleFormatExtensions extends AbstractExtension implements LocaleAw
|
||||
return ($day === 0 || $day === 6);
|
||||
}
|
||||
|
||||
public function dateShort(DateTime|string|null $date): string
|
||||
public function dateShort(\DateTimeInterface|string|null $date): string
|
||||
{
|
||||
return (string) $this->getFormatter()->dateShort($date);
|
||||
}
|
||||
@@ -158,17 +158,17 @@ final class LocaleFormatExtensions extends AbstractExtension implements LocaleAw
|
||||
return new DateTime($date, new \DateTimeZone($timezone));
|
||||
}
|
||||
|
||||
public function dateFormat(DateTime|string|null $date, string $format): string
|
||||
public function dateFormat(\DateTimeInterface|string|null $date, string $format): string
|
||||
{
|
||||
return (string) $this->getFormatter()->dateFormat($date, $format);
|
||||
}
|
||||
|
||||
public function dateWeekday(DateTime $date): string
|
||||
public function dateWeekday(\DateTimeInterface $date): string
|
||||
{
|
||||
return $this->dayName($date, true) . ' ' . $this->getFormatter()->dateFormat($date, 'd');
|
||||
}
|
||||
|
||||
public function time(DateTime|string|null $date): string
|
||||
public function time(\DateTimeInterface|string|null $date): string
|
||||
{
|
||||
return (string) $this->getFormatter()->time($date);
|
||||
}
|
||||
@@ -192,12 +192,12 @@ final class LocaleFormatExtensions extends AbstractExtension implements LocaleAw
|
||||
return $months;
|
||||
}
|
||||
|
||||
public function monthName(\DateTime $dateTime, bool $withYear = false): string
|
||||
public function monthName(\DateTimeInterface $dateTime, bool $withYear = false): string
|
||||
{
|
||||
return $this->getFormatter()->monthName($dateTime, $withYear);
|
||||
}
|
||||
|
||||
public function dayName(\DateTime $dateTime, bool $short = false): string
|
||||
public function dayName(\DateTimeInterface $dateTime, bool $short = false): string
|
||||
{
|
||||
return $this->getFormatter()->dayName($dateTime, $short);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ final class LocaleFormatter
|
||||
/**
|
||||
* @see https://unicode-org.github.io/icu/userguide/format_parse/datetime/
|
||||
*/
|
||||
private function formatIntl(\DateTime $dateTime, string $format): string
|
||||
private function formatIntl(\DateTimeInterface $dateTime, string $format): string
|
||||
{
|
||||
$formatter = new IntlDateFormatter(
|
||||
$this->locale,
|
||||
@@ -303,12 +303,12 @@ final class LocaleFormatter
|
||||
return (string) $formatted;
|
||||
}
|
||||
|
||||
public function monthName(\DateTime $dateTime, bool $withYear = false): string
|
||||
public function monthName(\DateTimeInterface $dateTime, bool $withYear = false): string
|
||||
{
|
||||
return $this->formatIntl($dateTime, ($withYear ? 'LLLL yyyy' : 'LLLL'));
|
||||
}
|
||||
|
||||
public function dayName(\DateTime $dateTime, bool $short = false): string
|
||||
public function dayName(\DateTimeInterface $dateTime, bool $short = false): string
|
||||
{
|
||||
return $this->formatIntl($dateTime, ($short ? 'EE' : 'EEEE'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user