Skip to content

Commit 3963bde

Browse files
committed
Add tree class generators and interactive prompts
Introduce interactive class generation for tree pages/widgets and refactor make commands. Adds a CanAskTreeNodeConfiguration trait to collect model/static-node/multiple-tree info, and new FileGenerator classes (BaseTreeClassGenerator, TreePageClassGenerator, TreeWidgetClassGenerator) to build page/widget classes programmatically. Refactors MakeTreePageCommand and MakeTreeWidgetCommand to use Filament command concerns, panel/cluster/resource prompts, and the new generators; wire up prompt-based namespace/location selection and collision checks. Removes the old MakeTreeResourcePageCommand and template stubs plus stub publishing from the service provider, and updates the service provider command list accordingly.
1 parent f64de3c commit 3963bde

13 files changed

Lines changed: 1097 additions & 265 deletions

README.md

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,32 @@
11
# Filament Nestable Tree
22

3-
[![Latest Version on Packagist](https://img.shields.io/packagist/v/solutionforest/filament-nestable-tree.svg?style=flat-square)](https://packagist.org/packages/solutionforest/filament-nestable-tree)
4-
[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/solutionforest/filament-nestable-tree/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/solutionforest/filament-nestable-tree/actions?query=workflow%3Arun-tests+branch%3Amain)
5-
[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/solutionforest/filament-nestable-tree/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/solutionforest/filament-nestable-tree/actions?query=workflow%3A"Fix+PHP+code+styling"+branch%3Amain)
6-
[![Total Downloads](https://img.shields.io/packagist/dt/solutionforest/filament-nestable-tree.svg?style=flat-square)](https://packagist.org/packages/solutionforest/filament-nestable-tree)
3+
[![Laravel Compatibility](https://badge.laravel.cloud/badge/solution-forest/filament-nestable-tree)](https://packagist.org/packages/solution-forest/filament-nestable-tree)
4+
[![Latest Version on Packagist](https://img.shields.io/packagist/v/solution-forest/filament-nestable-tree.svg?style=flat-square)](https://packagist.org/packages/solution-forest/filament-nestable-tree)
5+
[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/solutionforest/filament-nestable-tree/run-tests.yml?branch=1.x&label=tests&style=flat-square)](https://github.com/solutionforest/filament-nestable-tree/actions?query=workflow%3Arun-tests+branch%3A1.x)
6+
[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/solutionforest/filament-nestable-tree/fix-php-code-style-issues.yml?branch=1.x&label=code%20style&style=flat-square)](https://github.com/solutionforest/filament-nestable-tree/actions?query=workflow%3A"Fix+PHP+code+styling"+branch%3A1.x)
7+
[![Total Downloads](https://img.shields.io/packagist/dt/solution-forest/filament-nestable-tree.svg?style=flat-square)](https://packagist.org/packages/solution-forest/filament-nestable-tree)
78

8-
A nestable drag-and-drop tree component for [Filament](https://filamentphp.com) v5. Supports Eloquent models (including [`kalnoy/nestedset`](https://github.com/lazychaser/laravel-nestedset)), static record arrays, per-node actions, multi-tree pages, cross-tree drag-and-drop, lazy loading, and async child loading.
9+
A nestable drag-and-drop tree component for [Filament](https://filamentphp.com) v4 and v5. Supports Eloquent models (including [`kalnoy/nestedset`](https://github.com/lazychaser/laravel-nestedset)), static record arrays, per-node actions, multi-tree pages, cross-tree drag-and-drop, lazy loading, and async child loading.
910

10-
> **Example usage** — see the [demo application](https://github.com/solutionforest/filament-nestable-tree-dev) and the ready-to-run [fixture pages](tests/fixtures/Pages) in this repository.
11+
> **Example usage** — see the [fixture pages](tests/fixtures/Pages) in this repository.
1112
1213
---
1314

1415
## Installation
1516

1617
```bash
17-
composer require solutionforest/filament-nestable-tree
18+
composer require solution-forest/filament-nestable-tree
1819
```
1920

2021
> [!IMPORTANT]
2122
> If you are using Filament Panels with a custom theme, add the plugin's views to your theme CSS file so Tailwind can scan them:
2223
>
2324
> ```css
24-
> @source '../../../../vendor/solutionforest/filament-nestable-tree/resources/**/*.blade.php';
25+
> @source '../../../../vendor/solution-forest/filament-nestable-tree/resources/**/*.blade.php';
2526
> ```
2627
>
2728
> If you have not yet set up a custom theme, follow the [Filament theming guide](https://filamentphp.com/docs/4.x/styling/overview#creating-a-custom-theme) first.
2829
29-
Optionally publish the stub files:
30-
31-
```bash
32-
php artisan vendor:publish --tag="filament-nestable-tree-stubs"
33-
```
34-
3530
---
3631
3732
## Quick Start
@@ -422,7 +417,7 @@ The MIT License (MIT). Please see [License File](LICENSE.md) for more informatio
422417
You can install the package via composer:
423418

424419
```bash
425-
composer require solutionforest/filament-nestable-tree
420+
composer require solution-forest/filament-nestable-tree
426421
```
427422

428423
> [!IMPORTANT]
@@ -431,7 +426,7 @@ composer require solutionforest/filament-nestable-tree
431426
After setting up a custom theme add the plugin's views to your theme css file or your app's css file if using the standalone packages.
432427

433428
```css
434-
@source '../../../../vendor/solutionforest/filament-nestable-tree/resources/**/*.blade.php';
429+
@source '../../../../vendor/solution-forest/filament-nestable-tree/resources/**/*.blade.php';
435430
```
436431

437432
You can publish and run the migrations with:
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
namespace SolutionForest\FilamentNestableTree\Commands\Concerns;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
use function Filament\Support\discover_app_classes;
8+
use function Laravel\Prompts\confirm;
9+
use function Laravel\Prompts\text;
10+
use function Laravel\Prompts\suggest;
11+
12+
trait CanAskTreeNodeConfiguration
13+
{
14+
protected ?string $treeModelFqn = null;
15+
16+
protected ?string $treeStaticNodePropertyName = null;
17+
18+
protected array $multipleTreeKeys = [];
19+
20+
protected function askTreeNodeConfigurationForWidget(): void
21+
{
22+
$treeUseStaticNodes = confirm(
23+
label: 'Will this tree use static nodes (i.e. not backed by a database model)?',
24+
default: false,
25+
);
26+
27+
if ($treeUseStaticNodes) {
28+
29+
$this->treeStaticNodePropertyName = text(
30+
label: 'What is the name of the property that will hold the nodes for the tree? ',
31+
placeholder: 'e.g. nodes',
32+
required: true,
33+
default: 'nodes',
34+
validate: function ($value) {
35+
if (str_contains($value, ' ')) {
36+
return 'The property name cannot contain spaces.';
37+
}
38+
39+
return null;
40+
}
41+
);
42+
} else {
43+
44+
45+
$modelFqns = discover_app_classes(parentClass: Model::class);
46+
47+
$this->treeModelFqn = suggest(
48+
label: 'What is the model?',
49+
options: function (string $search) use ($modelFqns): array {
50+
$search = str($search)->trim()->replace(['\\', '/'], '');
51+
52+
if (blank($search)) {
53+
return $modelFqns;
54+
}
55+
56+
return array_filter(
57+
$modelFqns,
58+
fn (string $class): bool => str($class)->replace(['\\', '/'], '')->contains($search, ignoreCase: true),
59+
);
60+
},
61+
placeholder: app()->getNamespace() . 'Models\\BlogPost',
62+
required: true,
63+
validate: function ($value) {
64+
$checkValue = (string) $value;
65+
$trimmedValue = (string) str($checkValue)->trim();
66+
if (empty($trimmedValue)) {
67+
return 'The model class name is required.';
68+
}
69+
return null;
70+
}
71+
);
72+
}
73+
}
74+
75+
protected function askTreeNodeConfigurationForPage(bool $hasResource) : void
76+
{
77+
$treeUseStaticNodes = confirm(
78+
label: 'Will this tree use static nodes (i.e. not backed by a database model)?',
79+
default: ! $hasResource,
80+
);
81+
82+
if ($treeUseStaticNodes) {
83+
84+
$this->treeStaticNodePropertyName = text(
85+
label: 'What is the name of the property that will hold the nodes for the tree? ',
86+
placeholder: 'e.g. nodes',
87+
required: true,
88+
default: 'nodes',
89+
validate: function ($value) {
90+
if (str_contains($value, ' ')) {
91+
return 'The property name cannot contain spaces.';
92+
}
93+
94+
return null;
95+
}
96+
);
97+
} else {
98+
$useResourceModel = $hasResource
99+
? confirm(
100+
label: 'Do you want to use the model from the associated Filament Resource for the tree?',
101+
default: true,
102+
)
103+
: false;
104+
105+
if (! $useResourceModel) {
106+
107+
$modelFqns = discover_app_classes(parentClass: Model::class);
108+
109+
$this->treeModelFqn = suggest(
110+
label: 'What is the model?',
111+
options: function (string $search) use ($modelFqns): array {
112+
$search = str($search)->trim()->replace(['\\', '/'], '');
113+
114+
if (blank($search)) {
115+
return $modelFqns;
116+
}
117+
118+
return array_filter(
119+
$modelFqns,
120+
fn (string $class): bool => str($class)->replace(['\\', '/'], '')->contains($search, ignoreCase: true),
121+
);
122+
},
123+
placeholder: app()->getNamespace() . 'Models\\BlogPost',
124+
required: true,
125+
validate: function ($value) {
126+
$checkValue = (string) $value;
127+
$trimmedValue = (string) str($checkValue)->trim();
128+
if (empty($trimmedValue)) {
129+
return 'The model class name is required.';
130+
}
131+
return null;
132+
}
133+
);
134+
}
135+
}
136+
137+
$isMultipleTrees = confirm(
138+
label: 'Will this page contain multiple trees?',
139+
default: false,
140+
);
141+
142+
if ($isMultipleTrees) {
143+
144+
$this->multipleTreeKeys = str(
145+
text(
146+
label: 'Please provide unique keys for each tree, separated by commas. ',
147+
placeholder: 'e.g. categories,tags',
148+
validate: function ($value) {
149+
$keys = array_map('trim', explode(',', $value));
150+
foreach ($keys as $key) {
151+
if (str_contains($key, ' ')) {
152+
return 'Tree keys cannot contain spaces.';
153+
}
154+
}
155+
156+
return null;
157+
}
158+
)
159+
)
160+
->explode(',')
161+
->map(fn ($key) => trim($key))
162+
->filter()
163+
->values()
164+
->all();
165+
}
166+
}
167+
}

0 commit comments

Comments
 (0)