Add skip and meta to resource in time entry endpoint

This commit is contained in:
Constantin Graf
2024-09-19 23:49:50 +02:00
committed by Gregor Vostrak
parent 3ee7839ca9
commit a882ec6ca0
5 changed files with 122 additions and 36 deletions

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Extensions\Scramble;
use App\Http\Resources\PaginatedResourceCollection;
use App\Http\Resources\V1\TimeEntry\TimeEntryCollection;
use Dedoc\Scramble\Extensions\TypeToSchemaExtension;
use Dedoc\Scramble\Support\Generator\Response;
use Dedoc\Scramble\Support\Generator\Schema;
@@ -44,39 +45,49 @@ class PaginatedResourceCollectionTypeToSchema extends TypeToSchemaExtension
return null;
}
$type = new OpenApiObjectType;
$type->addProperty('data', (new ArrayType)->setItems($collectingType));
$type->addProperty(
'links',
(new OpenApiObjectType)
->addProperty('first', (new StringType)->nullable(true))
->addProperty('last', (new StringType)->nullable(true))
->addProperty('prev', (new StringType)->nullable(true))
->addProperty('next', (new StringType)->nullable(true))
->setRequired(['first', 'last', 'prev', 'next'])
);
$type->addProperty(
'meta',
(new OpenApiObjectType)
->addProperty('current_page', new IntegerType)
->addProperty('from', (new IntegerType)->nullable(true))
->addProperty('last_page', new IntegerType)
->addProperty('links', (new ArrayType)->setItems(
(new OpenApiObjectType)
->addProperty('url', (new StringType)->nullable(true))
->addProperty('label', new StringType)
->addProperty('active', new BooleanType)
->setRequired(['url', 'label', 'active'])
)->setDescription('Generated paginator links.'))
->addProperty('path', (new StringType)->nullable(true)->setDescription('Base path for paginator generated URLs.'))
->addProperty('per_page', (new IntegerType)->setDescription('Number of items shown per page.'))
->addProperty('to', (new IntegerType)->nullable(true)->setDescription('Number of the last item in the slice.'))
->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'))
->setRequired(['current_page', 'from', 'last_page', 'links', 'path', 'per_page', 'to', 'total'])
);
$type->setRequired(['data', 'links', 'meta']);
$newType = new OpenApiObjectType;
$newType->addProperty('data', (new ArrayType)->setItems($collectingType));
if ($type instanceof ObjectType && $type->isInstanceOf(TimeEntryCollection::class)) {
$newType->addProperty(
'meta',
(new OpenApiObjectType)
->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'))
->setRequired(['total'])
);
$newType->setRequired(['data', 'meta']);
} else {
$newType->addProperty(
'links',
(new OpenApiObjectType)
->addProperty('first', (new StringType)->nullable(true))
->addProperty('last', (new StringType)->nullable(true))
->addProperty('prev', (new StringType)->nullable(true))
->addProperty('next', (new StringType)->nullable(true))
->setRequired(['first', 'last', 'prev', 'next'])
);
$newType->addProperty(
'meta',
(new OpenApiObjectType)
->addProperty('current_page', new IntegerType)
->addProperty('from', (new IntegerType)->nullable(true))
->addProperty('last_page', new IntegerType)
->addProperty('links', (new ArrayType)->setItems(
(new OpenApiObjectType)
->addProperty('url', (new StringType)->nullable(true))
->addProperty('label', new StringType)
->addProperty('active', new BooleanType)
->setRequired(['url', 'label', 'active'])
)->setDescription('Generated paginator links.'))
->addProperty('path', (new StringType)->nullable(true)->setDescription('Base path for paginator generated URLs.'))
->addProperty('per_page', (new IntegerType)->setDescription('Number of items shown per page.'))
->addProperty('to', (new IntegerType)->nullable(true)->setDescription('Number of the last item in the slice.'))
->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'))
->setRequired(['current_page', 'from', 'last_page', 'links', 'path', 'per_page', 'to', 'total'])
);
$newType->setRequired(['data', 'links', 'meta']);
}
return $type;
return $newType;
}
/**

View File

@@ -46,6 +46,8 @@ class TimeEntryController extends Controller
* If you only need time entries for a specific user, you can filter by `user_id`.
* Users with the permission `time-entries:view:own` can only use this endpoint with their own user ID in the user_id filter.
*
* @return TimeEntryCollection<TimeEntryResource>
*
* @throws AuthorizationException
*
* @operationId getTimeEntries
@@ -76,11 +78,14 @@ class TimeEntryController extends Controller
$filter->addClientIdsFilter($request->input('client_ids'));
$filter->addBillableFilter($request->input('billable'));
$limit = $request->has('limit') ? (int) $request->input('limit', 100) : 100;
$totalCount = $timeEntriesQuery->count();
$limit = $request->getLimit();
if ($limit > 1000) {
$limit = 1000;
}
$timeEntriesQuery->limit($limit);
$timeEntriesQuery->skip($request->getSkip());
$timeEntries = $timeEntriesQuery->get();
@@ -114,7 +119,12 @@ class TimeEntryController extends Controller
}
}
return new TimeEntryCollection($timeEntries);
return (new TimeEntryCollection($timeEntries))
->additional([
'meta' => [
'total' => $totalCount,
],
]);
}
/**

View File

@@ -131,6 +131,11 @@ class TimeEntryIndexRequest extends FormRequest
'min:1',
'max:500',
],
// Skip the first n time entries (default: 0)
'skip' => [
'integer',
'min:0',
],
// Filter makes sure that only time entries of a whole date are returned
'only_full_dates' => [
'string',
@@ -143,4 +148,14 @@ class TimeEntryIndexRequest extends FormRequest
{
return $this->input('only_full_dates', 'false') === 'true';
}
public function getLimit(): int
{
return $this->has('limit') ? (int) $this->validated('limit', 100) : 100;
}
public function getSkip(): int
{
return $this->has('skip') ? (int) $this->validated('skip', 0) : 0;
}
}

View File

@@ -4,9 +4,10 @@ declare(strict_types=1);
namespace App\Http\Resources\V1\TimeEntry;
use App\Http\Resources\PaginatedResourceCollection;
use Illuminate\Http\Resources\Json\ResourceCollection;
class TimeEntryCollection extends ResourceCollection
class TimeEntryCollection extends ResourceCollection implements PaginatedResourceCollection
{
/**
* The resource that this resource collects.