Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demo/app/Sharp/Categories/CategoryList.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Code16\Sharp\EntityList\Fields\EntityListField;
use Code16\Sharp\EntityList\Fields\EntityListFieldsContainer;
use Code16\Sharp\EntityList\SharpEntityList;
use Code16\Sharp\Utils\Filters\CheckFilter;
use Code16\Sharp\Filters\CheckFilter;
use Illuminate\Contracts\Support\Arrayable;

class CategoryList extends SharpEntityList
Expand Down
2 changes: 1 addition & 1 deletion demo/app/Sharp/DummyGlobalFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\Sharp;

use Code16\Sharp\Utils\Filters\GlobalRequiredFilter;
use Code16\Sharp\Filters\GlobalRequiredFilter;

class DummyGlobalFilter extends GlobalRequiredFilter
{
Expand Down
13 changes: 12 additions & 1 deletion demo/app/Sharp/Posts/PostList.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Sharp\Posts;

use App\Models\Post;
use App\Models\PostAttachment;
use App\Sharp\Entities\PostEntity;
use App\Sharp\Posts\Commands\BulkPublishPostsCommand;
use App\Sharp\Posts\Commands\ComposeEmailWithPostsWizardCommand;
Expand All @@ -12,12 +13,13 @@
use App\Sharp\Utils\Filters\AuthorFilter;
use App\Sharp\Utils\Filters\CategoryFilter;
use App\Sharp\Utils\Filters\PeriodFilter;
use App\Sharp\Utils\Filters\PostAttachmentFilter;
use App\Sharp\Utils\Filters\StateFilter;
use Code16\Sharp\EntityList\Fields\EntityListField;
use Code16\Sharp\EntityList\Fields\EntityListFieldsContainer;
use Code16\Sharp\EntityList\Fields\EntityListStateField;
use Code16\Sharp\EntityList\SharpEntityList;
use Code16\Sharp\Utils\Filters\DateRangeFilterValue;
use Code16\Sharp\Filters\DateRange\DateRangeFilterValue;
use Code16\Sharp\Utils\Links\LinkToEntityList;
use Code16\Sharp\Utils\PageAlerts\PageAlert;
use Code16\Sharp\Utils\Transformers\Attributes\Eloquent\SharpTagsTransformer;
Expand Down Expand Up @@ -86,6 +88,7 @@ protected function getFilters(): ?array
StateFilter::class,
AuthorFilter::class,
CategoryFilter::class,
PostAttachmentFilter::class,
PeriodFilter::class,
];
}
Expand Down Expand Up @@ -147,6 +150,14 @@ function (Builder $builder, $categories) {
});
},
)
->when(
$this->queryParams->filterFor(PostAttachmentFilter::class),
function (Builder $builder, int $attachmentId) {
$builder->whereHas('attachments', function (Builder $builder) use ($attachmentId) {
$builder->where('title', PostAttachment::find($attachmentId)->title);
});
},
)

// Handle search words
->when(
Expand Down
5 changes: 3 additions & 2 deletions demo/app/Sharp/Utils/Filters/AuthorFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace App\Sharp\Utils\Filters;

use App\Models\User;
use Code16\Sharp\EntityList\Filters\EntityListSelectFilter;
use Code16\Sharp\Filters\SelectFilter;

class AuthorFilter extends EntityListSelectFilter
class AuthorFilter extends SelectFilter
{
public function buildFilterConfig(): void
{
Expand All @@ -16,6 +16,7 @@ public function values(): array
{
return User::whereHas('posts')
->orderBy('name')
->get()
->pluck('name', 'id')
->map(fn ($name, $id) => auth()->id() === $id ? "$name (me)" : $name)
->toArray();
Expand Down
4 changes: 2 additions & 2 deletions demo/app/Sharp/Utils/Filters/CategoryFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace App\Sharp\Utils\Filters;

use App\Models\Category;
use Code16\Sharp\EntityList\Filters\EntityListSelectMultipleFilter;
use Code16\Sharp\Filters\SelectMultipleFilter;

class CategoryFilter extends EntityListSelectMultipleFilter
class CategoryFilter extends SelectMultipleFilter
{
public function buildFilterConfig(): void
{
Expand Down
4 changes: 2 additions & 2 deletions demo/app/Sharp/Utils/Filters/PeriodFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Sharp\Utils\Filters;

use Code16\Sharp\EntityList\Filters\EntityListDateRangeFilter;
use Code16\Sharp\Filters\DateRangeFilter;

class PeriodFilter extends EntityListDateRangeFilter
class PeriodFilter extends DateRangeFilter
{
public function buildFilterConfig(): void
{
Expand Down
4 changes: 2 additions & 2 deletions demo/app/Sharp/Utils/Filters/PeriodRequiredFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Sharp\Utils\Filters;

use Code16\Sharp\Dashboard\Filters\DashboardDateRangeRequiredFilter;
use Code16\Sharp\Filters\DateRangeRequiredFilter;

class PeriodRequiredFilter extends DashboardDateRangeRequiredFilter
class PeriodRequiredFilter extends DateRangeRequiredFilter
{
public function buildFilterConfig(): void
{
Expand Down
32 changes: 32 additions & 0 deletions demo/app/Sharp/Utils/Filters/PostAttachmentFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Sharp\Utils\Filters;

use App\Models\PostAttachment;
use Code16\Sharp\Filters\AutocompleteRemoteFilter;

class PostAttachmentFilter extends AutocompleteRemoteFilter
{
public function buildFilterConfig(): void
{
$this->configureLabel('Attachment');
}

public function values(string $query): array
{
return PostAttachment::query()
->orderBy('title')
->when($query, function ($builder) use ($query) {
$builder->where('title', 'like', "%$query%");
})
->get()
->pluck('title', 'id')
->unique()
->toArray();
}

public function valueLabelFor(string $id): string
{
return PostAttachment::find($id)->title ?? '';
}
}
4 changes: 2 additions & 2 deletions demo/app/Sharp/Utils/Filters/StateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Sharp\Utils\Filters;

use Code16\Sharp\EntityList\Filters\EntityListSelectFilter;
use Code16\Sharp\Filters\SelectFilter;

class StateFilter extends EntityListSelectFilter
class StateFilter extends SelectFilter
{
public function buildFilterConfig(): void
{
Expand Down
5 changes: 4 additions & 1 deletion demo/database/factories/PostAttachmentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

namespace Database\Factories;

use Database\Seeders\WithTextFixtures;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostAttachmentFactory extends Factory
{
use WithTextFixtures;

public function definition()
{
return [
'title' => $this->faker->sentence,
'title' => $this->faker->randomElement(static::$attachmentTitles),
'is_link' => $this->faker->boolean,
'link_url' => $this->faker->url,
];
Expand Down
10 changes: 10 additions & 0 deletions demo/database/seeders/WithTextFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,14 @@ trait WithTextFixtures
'The chair sat in the corner where it had been for over 25 years. The only difference was there was someone actually sitting in it. How long had it been since someone had done that? Ten years or more he imagined. Yet there was no denying the presence in the chair now.',
"Things aren't going well at all with mom today. She is just a limp noodle and wants to sleep all the time. I sure hope that things get better soon.",
];
protected static array $attachmentTitles = [
'Newspaper article',
'Charts',
'PDF specifications',
'Book preview',
'Code example',
'Photo of my lamborghini',
'Photo of my cat',
'Sales growth chart',
];
}
57 changes: 45 additions & 12 deletions docs/guide/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ php artisan sharp:make:entity-list-filter <class_name> [--required,--multiple,--

## Write the filter class

First, we need to write a class which extends `Code16\Sharp\EntityList\Filters\EntityListSelectFilter`, and therefore declare a `values()` function. This function must return an `[{id} => {label}]` array. For instance, with Eloquent:
First, we need to write a class which extends `Code16\Sharp\Filters\SelectFilter`, and therefore declare a `values()` function. This function must return an `[{id} => {label}]` array. For instance, with Eloquent:

```php
class ProductCategoryFilter extends EntityListSelectFilter
class ProductCategoryFilter extends SelectFilter
{
public function values(): array
{
Expand All @@ -31,7 +31,7 @@ class ProductCategoryFilter extends EntityListSelectFilter
You can implement the optional `buildFilterConfig()` method to configure the filter:

```php
class ProductCategoryFilter extends EntityListSelectFilter
class ProductCategoryFilter extends SelectFilter
{
public function buildFilterConfig(): void
{
Expand Down Expand Up @@ -94,7 +94,7 @@ class ProductList extends SharpEntityList

## Multiple filter

First, notice that you can have as many filters as you want for an EntityList. The "multiple filter" here designate something else: allowing the user to select more than one value for a filter. To achieve this, make your filter extend `Code16\Sharp\EntityList\Filters\EntityListSelectMultipleFilter`.
First, notice that you can have as many filters as you want for an EntityList. The "multiple filter" here designate something else: allowing the user to select more than one value for a filter. To achieve this, make your filter extend `Code16\Sharp\Filters\SelectMultipleFilter`.

In this case, with Eloquent for instance, your might have to modify your code to ensure that you have an array (Sharp will return either null, and id or an array of id, depending on the user selection):

Expand All @@ -120,7 +120,7 @@ Note that a filter can't be required AND multiple.

## Date range filter

You might find useful to filter list elements on a specific date range. Date range filters enable you to show only data that meets a given time period. To implement such a filter, your filter class must extend `Code16\Sharp\EntityList\Filters\EntityListDateRangeFilter`.
You might find useful to filter list elements on a specific date range. Date range filters enable you to show only data that meets a given time period. To implement such a filter, your filter class must extend `Code16\Sharp\Filters\DateRangeFilter`.

Then you need to adjust the query with selected range; in this case, with Eloquent for instance, you might add a condition like:

Expand Down Expand Up @@ -148,7 +148,7 @@ You can define the date display format (default is `MM-DD-YYYY`, using [Carbon i
With `configureShowPresets()`, a list of buttons is displayed allowing the user to quickly select a date range.

```php
class ProductCreationDateFilter extends EntityListDateRangeFilter
class ProductCreationDateFilter extends DateRangeFilter
{
public function buildFilterConfig(): void
{
Expand All @@ -161,14 +161,47 @@ class ProductCreationDateFilter extends EntityListDateRangeFilter
}
```

## Autocomplete remote filter

If you want to use a remote filter, you can use the `Code16\Sharp\Filters\AutocompleteRemoteFilter` class. It is very similar to the `Code16\Sharp\Filters\SelectFilter` class, but it uses a remote endpoint to fetch the values.

```php
class ProductCategoryFilter extends AutocompleteRemoteFilter
{
public function buildFilterConfig(): void
{
$this
->configureLabel('Category')
->configureDebounceDelay(200) // 300ms per default
->configureSearchMinChars(2); // 1 per default, set 0 to search directly on opening the filter
}

public function values(string $query): array
{
return ProductCategory::orderBy('label')
->where('label', 'like', "%$query%")
->pluck('label', 'id')
->toArray();
}

public function valueLabelFor(string $id): ?string
{
return ProductCategory::find($id)?->label;
}
}
```

The `values()` method must return an `[{id} => {label}]` array. The `valueLabelFor()` method is used to display the label in the dropdown for the selected id.


## Required filters

It is sometimes useful to have a filter which can't be null: to achieve this you need to extend the right "Required" subclass (`EntityListSelectRequiredFilter` or `EntityListDateRangeRequiredFilter`), and define a proper default value.
It is sometimes useful to have a filter which can't be null: to achieve this you need to extend the right "Required" subclass (`SelectRequiredFilter` or `DateRangeRequiredFilter`), and define a proper default value.

Example for a select filter:

```php
class ProductCategoryFilter extends EntityListSelectRequiredFilter
class ProductCategoryFilter extends SelectRequiredFilter
{
public function defaultValue(): mixed
{
Expand All @@ -184,7 +217,7 @@ Note that a filter can't be required AND multiple.
Example for a date range filter:

```php
class ProductCreationDateFilter extends EntityListDateRangeRequiredFilter
class ProductCreationDateFilter extends DateRangeRequiredFilter
{
public function defaultValue(): array
{
Expand All @@ -211,7 +244,7 @@ public function buildFilterConfig(): void

## Check filter

In case of a filter that is just a matter on true / false ("only show admins" for example), just make your filter class extend `Code16\Sharp\EntityList\Filters\EntityListCheckFilter`.
In case of a filter that is just a matter on true / false ("only show admins" for example), just make your filter class extend `Code16\Sharp\Filters\CheckFilter`.

## Master filter

Expand Down Expand Up @@ -272,14 +305,14 @@ class OrderList extends SharpEntityList

## Filters for Dashboards

[Dashboards](building-dashboard.md) also can take advantage of filters; the API the same, but base classes are specific: `Code16\Sharp\Dashboard\Filters\DashboardSelectFilter`, `Code16\Sharp\Dashboard\Filters\DashboardDateRangeFilter`,`Code16\Sharp\Dashboard\DashboardCheckFilter` and so on.
[Dashboards](building-dashboard.md) also can take advantage of filters; the API the same, but base classes are specific: `Code16\Sharp\Filters\SelectFilter`, `Code16\Sharp\Filters\DateRangeFilter`,`Code16\Sharp\Filters\CheckFilter` and so on.

## Global menu Filters

You may want to "scope" the entire data set: an example of this could be a user which can manage several organizations. Instead of adding a filter on almost every Entity List, in this case, you can define a global filter, which will appear on top of the global menu.

To achieve this, first write the filter class, like any filter, except it must
extend `\Code16\Sharp\Utils\Filters\GlobalRequiredFilter` — meaning it must be a required filter.
extend `\Code16\Sharp\Filters\GlobalRequiredFilter` — meaning it must be a required filter.

```php
class OrganizationGlobalFilter extends GlobalRequiredFilter
Expand Down
5 changes: 4 additions & 1 deletion resources/js/Pages/Dashboard/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
DialogTrigger
} from "@/components/ui/dialog";
import { Filter } from "lucide-vue-next";
import { CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";

const props = defineProps<{
Expand Down Expand Up @@ -108,6 +107,7 @@
:filter="filter"
:value="filters.currentValues[filter.key]"
:valuated="filters.isValuated([filter])"
:entity-key="dashboardKey"
inline
@input="onFilterChange(filter, $event)"
/>
Expand Down Expand Up @@ -140,6 +140,7 @@
:filter="filter"
:value="filters.currentValues[filter.key]"
:valuated="filters.isValuated([filter])"
:entity-key="dashboardKey"
@input="onFilterChange(filter, $event)"
/>
</template>
Expand Down Expand Up @@ -205,6 +206,7 @@
:filter="filter"
:value="filters.currentValues[filter.key]"
:valuated="filters.isValuated([filter])"
:entity-key="dashboardKey"
inline
@input="onFilterChange(filter, $event)"
/>
Expand Down Expand Up @@ -237,6 +239,7 @@
:filter="filter"
:value="filters.currentValues[filter.key]"
:valuated="filters.isValuated([filter])"
:entity-key="dashboardKey"
@input="onFilterChange(filter, $event)"
/>
</template>
Expand Down
Loading
Loading