diff --git a/CHANGELOG.md b/CHANGELOG.md index b4cd109ed..f3912cce5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to `laravel-livewire-tables` will be documented in this file ## UNRELEASED ### New Features - Add capability to use as a Full Page Component +- Add DateColumn ### Tweaks - Internal - modify GitHub workflows to improve caching, but use unique caches per workflow matrix diff --git a/database/sqlite.database b/database/sqlite.database index 957f99638..953fb91ee 100644 Binary files a/database/sqlite.database and b/database/sqlite.database differ diff --git a/docs/columns/other-column-types.md b/docs/columns/other-column-types.md index c5298c48f..6378dd7f6 100644 --- a/docs/columns/other-column-types.md +++ b/docs/columns/other-column-types.md @@ -82,6 +82,31 @@ BooleanColumn::make('Active') ->yesNo() ``` +## Date Columns + +Date columns provide an easy way to display dates in a given format, without having to use repetitive format() methods or partial views. + +You may pass either a DateTime object, in which you can define an "outputFormat" +```php +DateColumn::make('Updated At', 'updated_at') + ->outputFormat('Y-m-d H:i:s), +``` + +Or you may pass a string, in which case you can define an "inputFormat" in addition to the outputFormat: +```php +DateColumn::make('Last Charged', 'last_charged_at') + ->inputFormat('Y-m-d H:i:s') + ->outputFormat('Y-m-d'), +``` + +You may also set an "emptyValue" to use when there is no value from the database: +```php +DateColumn::make('Last Charged', 'last_charged_at') + ->inputFormat('Y-m-d H:i:s') + ->outputFormat('Y-m-d') + ->emptyValue('Not Found'), +``` + ## Image Columns Image columns provide a way to display images in your table without having to use `format()` or partial views: diff --git a/resources/views/includes/columns/date.blade.php b/resources/views/includes/columns/date.blade.php new file mode 100644 index 000000000..096f40658 --- /dev/null +++ b/resources/views/includes/columns/date.blade.php @@ -0,0 +1,3 @@ +
+ {{ $value }} +
diff --git a/src/Views/Columns/DateColumn.php b/src/Views/Columns/DateColumn.php new file mode 100644 index 000000000..badbbcf67 --- /dev/null +++ b/src/Views/Columns/DateColumn.php @@ -0,0 +1,52 @@ +getValue($row); + if (! ($dateTime instanceof \DateTime)) { + try { + // Check if format matches what is expected + if (! \Carbon\Carbon::hasFormatWithModifiers($dateTime, $this->getInputFormat())) { + throw new \Exception('DateColumn Received Invalid Format'); + } + + // Create DateTime Object + $dateTime = \DateTime::createFromFormat($this->getInputFormat(), $dateTime); + } catch (\Exception $exception) { + report($exception); + + // Return Null + return $this->getEmptyValue(); + } + } + + // Return + return $dateTime->format($this->getOutputFormat()); + + } +} diff --git a/src/Views/Traits/Configuration/DateColumnConfiguration.php b/src/Views/Traits/Configuration/DateColumnConfiguration.php new file mode 100644 index 000000000..9846fbd9a --- /dev/null +++ b/src/Views/Traits/Configuration/DateColumnConfiguration.php @@ -0,0 +1,36 @@ +outputFormat = $outputFormat; + + return $this; + } + + /** + * Define the inputFormat to use for the Column + */ + public function inputFormat(string $inputFormat): self + { + $this->inputFormat = $inputFormat; + + return $this; + } + + /** + * Define the Empty Value to use for the Column + */ + public function emptyValue(string $emptyValue): self + { + $this->emptyValue = $emptyValue; + + return $this; + } +} diff --git a/src/Views/Traits/Helpers/DateColumnHelpers.php b/src/Views/Traits/Helpers/DateColumnHelpers.php new file mode 100644 index 000000000..1a43ed375 --- /dev/null +++ b/src/Views/Traits/Helpers/DateColumnHelpers.php @@ -0,0 +1,30 @@ +outputFormat ?? 'Y-m-d'; + } + + /** + * Retrieve the inputFormat to use for the Column + */ + public function getInputFormat(): ?string + { + return $this->inputFormat ?? null; + } + + /** + * Retrieve the Empty Value to use for the Column + */ + public function getEmptyValue(): string + { + return $this->emptyValue; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 2623b0438..33cfd5315 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -52,11 +52,11 @@ protected function setUp(): void ]); Pet::insert([ - ['id' => 1, 'name' => 'Cartman', 'age' => 22, 'species_id' => 1, 'breed_id' => 4], - ['id' => 2, 'name' => 'Tux', 'age' => 8, 'species_id' => 1, 'breed_id' => 4], - ['id' => 3, 'name' => 'May', 'age' => 2, 'species_id' => 2, 'breed_id' => 102], - ['id' => 4, 'name' => 'Ben', 'age' => 5, 'species_id' => 3, 'breed_id' => 200], - ['id' => 5, 'name' => 'Chico', 'age' => 7, 'species_id' => 3, 'breed_id' => 202], + ['id' => 1, 'name' => 'Cartman', 'age' => 22, 'species_id' => 1, 'breed_id' => 4, 'last_visit' => '2023-01-04'], + ['id' => 2, 'name' => 'Tux', 'age' => 8, 'species_id' => 1, 'breed_id' => 4, 'last_visit' => '2023-02-04'], + ['id' => 3, 'name' => 'May', 'age' => 2, 'species_id' => 2, 'breed_id' => 102, 'last_visit' => null], + ['id' => 4, 'name' => 'Ben', 'age' => 5, 'species_id' => 3, 'breed_id' => 200, 'last_visit' => '2023-04-04'], + ['id' => 5, 'name' => 'Chico', 'age' => 7, 'species_id' => 3, 'breed_id' => 202, 'last_visit' => '2023-05-04'], ]); Veterinary::insert([ diff --git a/tests/Views/Columns/DateColumnTest.php b/tests/Views/Columns/DateColumnTest.php new file mode 100644 index 000000000..c582cc9b6 --- /dev/null +++ b/tests/Views/Columns/DateColumnTest.php @@ -0,0 +1,103 @@ +assertSame('Last Visit', $column->getTitle()); + } + + /** @test */ + public function can_infer_field_name_from_title_if_no_from(): void + { + $column = DateColumn::make('My Title'); + + $this->assertSame('my_title', $column->getField()); + } + + /** @test */ + public function can_set_base_field_from_from(): void + { + $column = DateColumn::make('Name', 'last_visit'); + + $this->assertSame('last_visit', $column->getField()); + } + + /** @test */ + public function can_set_relation_field_from_from(): void + { + $column = DateColumn::make('Name', 'last_visit'); + + $this->assertSame('last_visit', $column->getField()); + } + + /** @test */ + public function can_get_column_formatted_contents(): void + { + $column = DateColumn::make('Name', 'last_visit')->inputFormat('Y-m-d')->outputFormat('Y-m-d'); + + $rows = $this->basicTable->getRows(); + + $this->assertSame($rows->last()->last_visit, $column->getContents($rows->last())); + $this->assertSame($rows->last()->last_visit, '2023-05-04'); + } + + /** @test */ + public function can_get_column_reformatted_contents(): void + { + $column = DateColumn::make('Name', 'last_visit')->inputFormat('Y-m-d')->outputFormat('d-m-Y'); + + $rows = $this->basicTable->getRows(); + + $this->assertSame('04-05-2023', $column->getContents($rows->last())); + } + + /** @test */ + public function can_not_get_column_reformatted_contents_with_bad_values(): void + { + $column = DateColumn::make('Name', 'last_visit')->inputFormat('d-m-Y')->outputFormat('d-m-Y'); + + $firstRow = $this->basicTable->getRows()->first(); + + $firstRow->last_visit = '44-12-2023'; + + $this->assertSame('', $column->getContents($firstRow)); + + $firstRow->last_visit = '04-01-2023'; + + $this->assertSame('04-01-2023', $column->getContents($firstRow)); + + $this->assertSame('04-01-2023', $column->emptyValue('Unknown')->getContents($firstRow)); + + $firstRow->last_visit = '44-12-2023'; + + $this->assertSame('Unknown', $column->emptyValue('Unknown')->getContents($firstRow)); + + } + + /** @test */ + public function can_set_column_empty_value(): void + { + $column = DateColumn::make('Name', 'last_visit')->inputFormat('d-m-Y')->outputFormat('d-m-Y'); + $this->assertSame('', $column->getEmptyValue()); + + $column->emptyValue('Not Found'); + $this->assertSame('Not Found', $column->getEmptyValue()); + + $thirdRow = $this->basicTable->getRows()->slice(3, 1)->first(); + + $this->assertSame('Not Found', $column->getContents($thirdRow)); + + $column->emptyValue(''); + $this->assertSame('', $column->getContents($thirdRow)); + + } +}