mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 12:42:15 +01:00
Added is_imported flag to time entries
This commit is contained in:
committed by
Constantin Graf
parent
802d9558a3
commit
20f9b344f6
@@ -11,6 +11,8 @@ use Illuminate\Database\Eloquent\Builder;
|
|||||||
|
|
||||||
class ActiveUserOverview extends BaseWidget
|
class ActiveUserOverview extends BaseWidget
|
||||||
{
|
{
|
||||||
|
protected static ?int $sort = 1;
|
||||||
|
|
||||||
protected static ?string $heading = 'A Registrations';
|
protected static ?string $heading = 'A Registrations';
|
||||||
|
|
||||||
protected function getCards(): array
|
protected function getCards(): array
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class TimeEntriesCreated extends ChartWidget
|
|||||||
|
|
||||||
public ?string $filter = 'week';
|
public ?string $filter = 'week';
|
||||||
|
|
||||||
|
protected static ?int $sort = 3;
|
||||||
|
|
||||||
protected function getData(): array
|
protected function getData(): array
|
||||||
{
|
{
|
||||||
$filter = $this->filter;
|
$filter = $this->filter;
|
||||||
@@ -27,7 +29,9 @@ class TimeEntriesCreated extends ChartWidget
|
|||||||
} else {
|
} else {
|
||||||
$start = now()->subWeek();
|
$start = now()->subWeek();
|
||||||
}
|
}
|
||||||
$trend = Trend::model(TimeEntry::class)
|
$trend = Trend::query(
|
||||||
|
TimeEntry::query()->where('is_imported', '=', false)
|
||||||
|
)
|
||||||
->between(
|
->between(
|
||||||
start: $start,
|
start: $start,
|
||||||
end: now(),
|
end: now(),
|
||||||
|
|||||||
77
app/Filament/Widgets/TimeEntriesImported.php
Normal file
77
app/Filament/Widgets/TimeEntriesImported.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Filament\Widgets;
|
||||||
|
|
||||||
|
use App\Models\TimeEntry;
|
||||||
|
use Filament\Widgets\ChartWidget;
|
||||||
|
use Flowframe\Trend\Trend;
|
||||||
|
use Flowframe\Trend\TrendValue;
|
||||||
|
|
||||||
|
class TimeEntriesImported extends ChartWidget
|
||||||
|
{
|
||||||
|
protected static ?string $heading = 'Time Entries Imported';
|
||||||
|
|
||||||
|
public ?string $filter = 'week';
|
||||||
|
|
||||||
|
protected static ?int $sort = 4;
|
||||||
|
|
||||||
|
protected function getData(): array
|
||||||
|
{
|
||||||
|
$filter = $this->filter;
|
||||||
|
if ($filter === 'week') {
|
||||||
|
$start = now()->subWeek();
|
||||||
|
} elseif ($filter === 'month') {
|
||||||
|
$start = now()->subMonth();
|
||||||
|
} elseif ($filter === 'year') {
|
||||||
|
$start = now()->subYear();
|
||||||
|
} else {
|
||||||
|
$start = now()->subWeek();
|
||||||
|
}
|
||||||
|
$trend = Trend::query(
|
||||||
|
TimeEntry::query()->where('is_imported', '=', true)
|
||||||
|
)
|
||||||
|
->between(
|
||||||
|
start: $start,
|
||||||
|
end: now(),
|
||||||
|
)
|
||||||
|
->perDay();
|
||||||
|
|
||||||
|
if ($filter === 'week') {
|
||||||
|
$trend->perDay();
|
||||||
|
} elseif ($filter === 'month') {
|
||||||
|
$trend->perDay();
|
||||||
|
} elseif ($filter === 'year') {
|
||||||
|
$trend->perMonth();
|
||||||
|
} else {
|
||||||
|
$trend->perDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $trend->count();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'datasets' => [
|
||||||
|
[
|
||||||
|
'label' => self::$heading,
|
||||||
|
'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'labels' => $data->map(fn (TrendValue $value) => $value->date),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFilters(): ?array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'week' => 'Last week',
|
||||||
|
'month' => 'Last month',
|
||||||
|
'year' => 'Last year',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getType(): string
|
||||||
|
{
|
||||||
|
return 'line';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@ class UserRegistrations extends ChartWidget
|
|||||||
|
|
||||||
public ?string $filter = 'week';
|
public ?string $filter = 'week';
|
||||||
|
|
||||||
|
protected static ?int $sort = 2;
|
||||||
|
|
||||||
protected function getData(): array
|
protected function getData(): array
|
||||||
{
|
{
|
||||||
$filter = $this->filter;
|
$filter = $this->filter;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use Korridor\LaravelComputedAttributes\ComputedAttributes;
|
|||||||
* @property array $tags
|
* @property array $tags
|
||||||
* @property string $user_id
|
* @property string $user_id
|
||||||
* @property string $member_id
|
* @property string $member_id
|
||||||
|
* @property bool $is_imported
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @property-read Member $member
|
* @property-read Member $member
|
||||||
* @property string $organization_id
|
* @property string $organization_id
|
||||||
@@ -57,6 +58,7 @@ class TimeEntry extends Model
|
|||||||
'billable' => 'bool',
|
'billable' => 'bool',
|
||||||
'tags' => 'array',
|
'tags' => 'array',
|
||||||
'billable_rate' => 'int',
|
'billable_rate' => 'int',
|
||||||
|
'is_imported' => 'bool',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace App\Providers\Filament;
|
|||||||
|
|
||||||
use App\Filament\Widgets\ActiveUserOverview;
|
use App\Filament\Widgets\ActiveUserOverview;
|
||||||
use App\Filament\Widgets\TimeEntriesCreated;
|
use App\Filament\Widgets\TimeEntriesCreated;
|
||||||
|
use App\Filament\Widgets\TimeEntriesImported;
|
||||||
use App\Filament\Widgets\UserRegistrations;
|
use App\Filament\Widgets\UserRegistrations;
|
||||||
use Filament\Http\Middleware\Authenticate;
|
use Filament\Http\Middleware\Authenticate;
|
||||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||||
@@ -46,6 +47,7 @@ class AdminPanelProvider extends PanelProvider
|
|||||||
ActiveUserOverview::class,
|
ActiveUserOverview::class,
|
||||||
UserRegistrations::class,
|
UserRegistrations::class,
|
||||||
TimeEntriesCreated::class,
|
TimeEntriesCreated::class,
|
||||||
|
TimeEntriesImported::class,
|
||||||
])
|
])
|
||||||
->plugins([
|
->plugins([
|
||||||
EnvironmentIndicatorPlugin::make()
|
EnvironmentIndicatorPlugin::make()
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
|
|||||||
], [
|
], [
|
||||||
'client_id' => $clientId,
|
'client_id' => $clientId,
|
||||||
'color' => $this->colorService->getRandomColor(),
|
'color' => $this->colorService->getRandomColor(),
|
||||||
|
'is_billable' => false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$taskId = null;
|
$taskId = null;
|
||||||
@@ -105,6 +106,7 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
|
|||||||
}
|
}
|
||||||
$timeEntry->billable = $record['Billable'] === 'Yes';
|
$timeEntry->billable = $record['Billable'] === 'Yes';
|
||||||
$timeEntry->tags = $this->getTags($record['Tags']);
|
$timeEntry->tags = $this->getTags($record['Tags']);
|
||||||
|
$timeEntry->is_imported = true;
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class TogglTimeEntriesImporter extends DefaultImporter
|
|||||||
'organization_id' => $this->organization->id,
|
'organization_id' => $this->organization->id,
|
||||||
], [
|
], [
|
||||||
'client_id' => $clientId,
|
'client_id' => $clientId,
|
||||||
|
'is_billable' => false,
|
||||||
'color' => $this->colorService->getRandomColor(),
|
'color' => $this->colorService->getRandomColor(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -102,6 +103,7 @@ class TogglTimeEntriesImporter extends DefaultImporter
|
|||||||
}
|
}
|
||||||
$timeEntry->billable = $record['Billable'] === 'Yes';
|
$timeEntry->billable = $record['Billable'] === 'Yes';
|
||||||
$timeEntry->tags = $this->getTags($record['Tags']);
|
$timeEntry->tags = $this->getTags($record['Tags']);
|
||||||
|
$timeEntry->is_imported = true;
|
||||||
try {
|
try {
|
||||||
$start = Carbon::createFromFormat('Y-m-d H:i:s', $record['Start date'].' '.$record['Start time'], $timezone);
|
$start = Carbon::createFromFormat('Y-m-d H:i:s', $record['Start date'].' '.$record['Start time'], $timezone);
|
||||||
} catch (InvalidFormatException) {
|
} catch (InvalidFormatException) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class TimeEntryFactory extends Factory
|
|||||||
'start' => $start,
|
'start' => $start,
|
||||||
'end' => $this->faker->dateTimeBetween($start, 'now'),
|
'end' => $this->faker->dateTimeBetween($start, 'now'),
|
||||||
'billable' => $this->faker->boolean(),
|
'billable' => $this->faker->boolean(),
|
||||||
|
'is_imported' => false,
|
||||||
'tags' => [],
|
'tags' => [],
|
||||||
'user_id' => User::factory(),
|
'user_id' => User::factory(),
|
||||||
'member_id' => Member::factory(),
|
'member_id' => Member::factory(),
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('time_entries', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_imported')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('time_entries', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('is_imported');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -33,6 +33,7 @@ class ClockifyTimeEntriesImporterTest extends ImporterTestAbstract
|
|||||||
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->start->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->start->toDateTimeString());
|
||||||
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->end->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->end->toDateTimeString());
|
||||||
$this->assertFalse($timeEntry1->billable);
|
$this->assertFalse($timeEntry1->billable);
|
||||||
|
$this->assertTrue($timeEntry1->is_imported);
|
||||||
$this->assertSame([$testScenario->tag1->getKey(), $testScenario->tag2->getKey()], $timeEntry1->tags);
|
$this->assertSame([$testScenario->tag1->getKey(), $testScenario->tag2->getKey()], $timeEntry1->tags);
|
||||||
$timeEntry2 = $timeEntries->firstWhere('description', 'Working hard');
|
$timeEntry2 = $timeEntries->firstWhere('description', 'Working hard');
|
||||||
$this->assertNotNull($timeEntry2);
|
$this->assertNotNull($timeEntry2);
|
||||||
@@ -40,6 +41,7 @@ class ClockifyTimeEntriesImporterTest extends ImporterTestAbstract
|
|||||||
$this->assertSame('2024-03-04 10:23:00', $timeEntry2->start->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:00', $timeEntry2->start->toDateTimeString());
|
||||||
$this->assertSame('2024-03-04 11:23:01', $timeEntry2->end->toDateTimeString());
|
$this->assertSame('2024-03-04 11:23:01', $timeEntry2->end->toDateTimeString());
|
||||||
$this->assertTrue($timeEntry2->billable);
|
$this->assertTrue($timeEntry2->billable);
|
||||||
|
$this->assertTrue($timeEntry2->is_imported);
|
||||||
$this->assertSame([], $timeEntry2->tags);
|
$this->assertSame([], $timeEntry2->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ class ClockifyTimeEntriesImporterTest extends ImporterTestAbstract
|
|||||||
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->start->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->start->toDateTimeString());
|
||||||
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->end->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:52', $timeEntry1->end->toDateTimeString());
|
||||||
$this->assertFalse($timeEntry1->billable);
|
$this->assertFalse($timeEntry1->billable);
|
||||||
|
$this->assertTrue($timeEntry1->is_imported);
|
||||||
$this->assertSame([$testScenario->tag1->getKey(), $testScenario->tag2->getKey()], $timeEntry1->tags);
|
$this->assertSame([$testScenario->tag1->getKey(), $testScenario->tag2->getKey()], $timeEntry1->tags);
|
||||||
$timeEntry2 = $timeEntries->firstWhere('description', 'Working hard');
|
$timeEntry2 = $timeEntries->firstWhere('description', 'Working hard');
|
||||||
$this->assertNotNull($timeEntry2);
|
$this->assertNotNull($timeEntry2);
|
||||||
@@ -75,6 +78,7 @@ class ClockifyTimeEntriesImporterTest extends ImporterTestAbstract
|
|||||||
$this->assertSame('2024-03-04 10:23:00', $timeEntry2->start->toDateTimeString());
|
$this->assertSame('2024-03-04 10:23:00', $timeEntry2->start->toDateTimeString());
|
||||||
$this->assertSame('2024-03-04 11:23:01', $timeEntry2->end->toDateTimeString());
|
$this->assertSame('2024-03-04 11:23:01', $timeEntry2->end->toDateTimeString());
|
||||||
$this->assertTrue($timeEntry2->billable);
|
$this->assertTrue($timeEntry2->billable);
|
||||||
|
$this->assertTrue($timeEntry2->is_imported);
|
||||||
$this->assertSame([], $timeEntry2->tags);
|
$this->assertSame([], $timeEntry2->tags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user