Release 2.0.10 (#3927)

* allow API calls via GET
* allow to stop timesheet via GET
* improve form handling and validation
* improve stop button handling
* bump version
This commit is contained in:
Kevin Papst
2023-03-15 23:02:28 +01:00
committed by GitHub
parent 1a8c78944a
commit f007697a73
15 changed files with 34 additions and 99 deletions

View File

@@ -85,20 +85,20 @@ export default class KimaiAPILink extends KimaiPlugin {
API.handleError(message, error);
};
let data = {};
if (attributes['payload'] !== undefined) {
data = attributes['payload'];
}
if (method === 'PATCH') {
let data = {};
if (attributes['payload'] !== undefined) {
data = attributes['payload'];
}
API.patch(url, data, successHandle, errorHandle);
} else if (method === 'POST') {
let data = {};
if (attributes['payload'] !== undefined) {
data = attributes['payload'];
}
API.post(url, data, successHandle, errorHandle);
} else if (method === 'DELETE') {
API.delete(url, successHandle, errorHandle);
} else if (method === 'GET') {
API.get(url, data, successHandle, errorHandle);
}
}

View File

@@ -112,7 +112,7 @@ export default class KimaiActiveRecords extends KimaiPlugin {
}
/**
* Adapts the ticktac menus accordingg to the given entries (amount and duration).
* Adapts the ticktac menus according to the given entries (amount and duration).
* Does not influence listing pages, as those refresh themselves.
*
* @param {array} entries
@@ -168,7 +168,7 @@ export default class KimaiActiveRecords extends KimaiPlugin {
for (let link of allReplacer) {
const replacerName = link.dataset['replacer'];
if (replacerName === 'url') {
link.href = node.dataset['href'].replace('000', timesheet.id);
link.dataset['href'] = node.dataset['href'].replace('000', timesheet.id);
} else if (replacerName === 'activity') {
link.innerText = timesheet.activity.name;
} else if (replacerName === 'project') {

View File

@@ -140,26 +140,11 @@ parameters:
count: 1
path: src/API/TagController.php
-
message: "#^Parameter \\#1 \\$activity of method App\\\\Entity\\\\Timesheet\\:\\:setActivity\\(\\) expects App\\\\Entity\\\\Activity, App\\\\Entity\\\\Activity\\|null given\\.$#"
count: 1
path: src/API/TimesheetController.php
-
message: "#^Parameter \\#1 \\$datetime of method App\\\\Timesheet\\\\DateTimeFactory\\:\\:createDateTime\\(\\) expects string, mixed given\\.$#"
count: 3
path: src/API/TimesheetController.php
-
message: "#^Parameter \\#1 \\$description of method App\\\\Entity\\\\Timesheet\\:\\:setDescription\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/API/TimesheetController.php
-
message: "#^Parameter \\#1 \\$project of method App\\\\Entity\\\\Timesheet\\:\\:setProject\\(\\) expects App\\\\Entity\\\\Project, App\\\\Entity\\\\Project\\|null given\\.$#"
count: 1
path: src/API/TimesheetController.php
-
message: "#^Parameter \\#1 \\$user of class App\\\\Event\\\\RecentActivityEvent constructor expects App\\\\Entity\\\\User, App\\\\Entity\\\\User\\|null given\\.$#"
count: 1
@@ -1250,16 +1235,6 @@ parameters:
count: 1
path: src/Controller/QuickEntryController.php
-
message: "#^Parameter \\#1 \\$activity of method App\\\\Entity\\\\Timesheet\\:\\:setActivity\\(\\) expects App\\\\Entity\\\\Activity, App\\\\Entity\\\\Activity\\|null given\\.$#"
count: 1
path: src/Controller/QuickEntryController.php
-
message: "#^Parameter \\#1 \\$project of method App\\\\Entity\\\\Timesheet\\:\\:setProject\\(\\) expects App\\\\Entity\\\\Project, App\\\\Entity\\\\Project\\|null given\\.$#"
count: 1
path: src/Controller/QuickEntryController.php
-
message: "#^Method App\\\\Controller\\\\Reporting\\\\AbstractUserReportController\\:\\:getStatisticDataRaw\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@@ -1745,11 +1720,6 @@ parameters:
count: 1
path: src/Controller/TimesheetTeamController.php
-
message: "#^Parameter \\#1 \\$user of method App\\\\Entity\\\\Timesheet\\:\\:setUser\\(\\) expects App\\\\Entity\\\\User, mixed given\\.$#"
count: 1
path: src/Controller/TimesheetTeamController.php
-
message: "#^Method App\\\\Controller\\\\UserController\\:\\:exportAction\\(\\) has no return type specified\\.$#"
count: 1
@@ -1860,11 +1830,6 @@ parameters:
count: 1
path: src/DataFixtures/TimesheetFixtures.php
-
message: "#^Parameter \\#1 \\$description of method App\\\\Entity\\\\Timesheet\\:\\:setDescription\\(\\) expects string, string\\|null given\\.$#"
count: 1
path: src/DataFixtures/TimesheetFixtures.php
-
message: "#^Parameter \\#1 \\$user of method App\\\\DataFixtures\\\\TimesheetFixtures\\:\\:createTimesheetEntry\\(\\) expects App\\\\Entity\\\\User, App\\\\Entity\\\\User\\|null given\\.$#"
count: 2
@@ -4880,11 +4845,6 @@ parameters:
count: 1
path: src/Form/Type/QuickEntryWeekType.php
-
message: "#^Parameter \\#1 \\$user of method App\\\\Entity\\\\Timesheet\\:\\:setUser\\(\\) expects App\\\\Entity\\\\User, mixed given\\.$#"
count: 1
path: src/Form/Type/QuickEntryWeekType.php
-
message: "#^Method App\\\\Form\\\\Type\\\\SearchTermType\\:\\:buildForm\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
count: 1

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
"app": {
"js": [
"/build/runtime.f0079159.js",
"/build/app.bd3fd9c1.js"
"/build/app.454ad090.js"
],
"css": [
"/build/app.c429ff5b.css"
@@ -63,7 +63,7 @@
},
"integrity": {
"/build/runtime.f0079159.js": "sha384-H22sAW1aTvyIPqvHOvGXWSWTxf0y6mptp+MsVmyXCfjx/WJjBbhX9gbUZ+qIuihV",
"/build/app.bd3fd9c1.js": "sha384-lz7W4QdKZkFcM0r1sScURXhxrv/ezU2DXgjGgubQsorHuaQDcKKoucOvSK3yxW/U",
"/build/app.454ad090.js": "sha384-5EqTkHqGv38S0Z8pXK2h0tHtGoCxbBkAYeSg1S0pe5eTWItPP4fiIfgJkD6eVH9U",
"/build/app.c429ff5b.css": "sha384-m7RJ9g2fW3tENrf+oi/FsH8wTu6fsjuhvpDztfqr+YjNN0AvCapER6yvmGkqwp+I",
"/build/export-pdf.587575e7.js": "sha384-J50GStmmfVwUTN4dIRQ02eg9hyzGFPSzpTtpPody92j0V6zCqw+s5l8+ZhVTugeW",
"/build/export-pdf.d8a6c23b.css": "sha384-ztepocHE4rnGE9eKZ4kL6jTKaePUyiwiB9TjJjstjpf/ckcKg1HedrEOOk/8ElJg",

View File

@@ -1,6 +1,6 @@
{
"build/app.css": "/build/app.c429ff5b.css",
"build/app.js": "/build/app.bd3fd9c1.js",
"build/app.js": "/build/app.454ad090.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",

View File

@@ -106,6 +106,7 @@ final class TimesheetController extends BaseApiController
if ('all' === $userId) {
$query->setUser(null);
} else {
/** @var User|null $user */
$user = $userRepository->find($userId);
if ($user === null) {
throw $this->createNotFoundException('Unknown user: ' . $userId);
@@ -447,11 +448,15 @@ final class TimesheetController extends BaseApiController
}
/**
* Stops an active timesheet record
* Stops an active timesheet record.
*
* This route is available via GET and PATCH, as users over and over again run into errors when stopping.
* Likely caused by a slow JS engine and a fast-click after page reload.
*/
#[IsGranted('stop', 'timesheet')]
#[OA\Response(response: 200, description: 'Stops an active timesheet record and returns it afterwards.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))]
#[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to stop', required: true)]
#[Rest\Get(path: '/{id}/stop', name: 'stop_timesheet_get', requirements: ['id' => '\d+'])]
#[Rest\Patch(path: '/{id}/stop', name: 'stop_timesheet', requirements: ['id' => '\d+'])]
#[ApiSecurity(name: 'apiUser')]
#[ApiSecurity(name: 'apiToken')]

View File

@@ -17,11 +17,11 @@ class Constants
/**
* The current release version
*/
public const VERSION = '2.0.9';
public const VERSION = '2.0.10';
/**
* The current release: major * 10000 + minor * 100 + patch
*/
public const VERSION_ID = 20009;
public const VERSION_ID = 20010;
/**
* The software name
*/

View File

@@ -88,6 +88,7 @@ final class TimesheetTeamController extends TimesheetAbstractController
/** @var ArrayCollection<Team> $teams */
$teams = $createForm->get('teams')->getData();
/** @var array<User> $allUsers */
$allUsers = $users->toArray();
/** @var Team $team */
foreach ($teams as $team) {

View File

@@ -337,11 +337,7 @@ class Timesheet implements EntityWithMetaFields, ExportableItem
return null;
}
/**
* @param User $user
* @return Timesheet
*/
public function setUser(User $user): Timesheet
public function setUser(?User $user): Timesheet
{
$this->user = $user;
@@ -353,11 +349,7 @@ class Timesheet implements EntityWithMetaFields, ExportableItem
return $this->user;
}
/**
* @param Activity $activity
* @return Timesheet
*/
public function setActivity($activity): Timesheet
public function setActivity(?Activity $activity): Timesheet
{
$this->activity = $activity;
@@ -374,22 +366,14 @@ class Timesheet implements EntityWithMetaFields, ExportableItem
return $this->project;
}
/**
* @param Project $project
* @return Timesheet
*/
public function setProject(Project $project): Timesheet
public function setProject(?Project $project): Timesheet
{
$this->project = $project;
return $this;
}
/**
* @param string $description
* @return Timesheet
*/
public function setDescription($description): Timesheet
public function setDescription(?string $description): Timesheet
{
$this->description = $description;

View File

@@ -9,6 +9,7 @@
namespace App\Form\Type;
use App\Entity\User;
use App\Model\QuickEntryModel;
use App\Validator\Constraints\QuickEntryTimesheet;
use DateTime;
@@ -129,8 +130,12 @@ final class QuickEntryWeekType extends AbstractType
return $transformValue;
}
$user = $transformValue->getUser();
if ($user === null && $options['user'] instanceof User) {
$user = $options['user'];
}
foreach ($transformValue->getTimesheets() as $timesheet) {
$timesheet->setUser($transformValue->getUser() ?? $options['user']);
$timesheet->setUser($user);
$timesheet->setProject($project);
$timesheet->setActivity($activity);
}

View File

@@ -12,7 +12,7 @@
{% endif %}
{% set entry = active_timesheets[0] %}
<div class="ticktac-menu" data-api="{{ path('active_timesheet') }}" data-href="{{ path('stop_timesheet', {'id' : '000'}) }}" style="{% if not hasActiveRecords %}display:none{% endif %}">
<a data-replacer="url" class="api-link ticktac-running ticktac-stop btn {{ class }} btn-icon px-sm-2" href="{{ path('stop_timesheet', {'id' : entry.id}) }}" data-event="kimai.timesheetStop kimai.timesheetUpdate" data-method="PATCH" data-msg-error="timesheet.stop.error" data-msg-success="timesheet.stop.success"{% if hasActiveRecords %} accesskey="s"{% endif %}>
<a data-replacer="url" class="api-link ticktac-running ticktac-stop btn {{ class }} btn-icon px-sm-2" href="#" data-href="{{ path('stop_timesheet', {'id' : entry.id}) }}" data-event="kimai.timesheetStop kimai.timesheetUpdate" data-method="PATCH" data-msg-error="timesheet.stop.error" data-msg-success="timesheet.stop.success"{% if hasActiveRecords %} accesskey="s"{% endif %}>
<i class="text-red {{ 'stop-small'|icon(false) }} me-0 me-sm-1"></i>
<span class="d-none d-sm-block" data-replacer="duration" data-title="true" data-since="{{ entry.begin is null ? '' : entry.begin|date_format(constant('DATE_ISO8601')) }}">{{ entry is iterable ? 0|duration : entry|duration }}</span>
</a>

View File

@@ -1687,21 +1687,11 @@ parameters:
count: 1
path: API/TimesheetControllerTest.php
-
message: "#^Parameter \\#1 \\$activity of method App\\\\Entity\\\\Timesheet\\:\\:setActivity\\(\\) expects App\\\\Entity\\\\Activity, App\\\\Entity\\\\Activity\\|null given\\.$#"
count: 1
path: API/TimesheetControllerTest.php
-
message: "#^Parameter \\#1 \\$json of function json_decode expects string, string\\|false given\\.$#"
count: 32
path: API/TimesheetControllerTest.php
-
message: "#^Parameter \\#1 \\$project of method App\\\\Entity\\\\Timesheet\\:\\:setProject\\(\\) expects App\\\\Entity\\\\Project, App\\\\Entity\\\\Project\\|null given\\.$#"
count: 1
path: API/TimesheetControllerTest.php
-
message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, mixed given\\.$#"
count: 1
@@ -9007,16 +8997,6 @@ parameters:
count: 1
path: Repository/TimesheetRepositoryTest.php
-
message: "#^Parameter \\#1 \\$activity of method App\\\\Entity\\\\Timesheet\\:\\:setActivity\\(\\) expects App\\\\Entity\\\\Activity, App\\\\Entity\\\\Activity\\|null given\\.$#"
count: 2
path: Repository/TimesheetRepositoryTest.php
-
message: "#^Parameter \\#1 \\$project of method App\\\\Entity\\\\Timesheet\\:\\:setProject\\(\\) expects App\\\\Entity\\\\Project, App\\\\Entity\\\\Project\\|null given\\.$#"
count: 2
path: Repository/TimesheetRepositoryTest.php
-
message: "#^Method App\\\\Tests\\\\Saml\\\\SamlBadgeTest\\:\\:testConstruct\\(\\) has no return type specified\\.$#"
count: 1