33namespace Backstage \Fields \Fields \FormSchemas ;
44
55use Backstage \Fields \Fields \Helpers \FieldOptionsHelper ;
6+ use Backstage \Fields \Fields \Helpers \ModelAttributeHelper ;
67use Backstage \Fields \Models \Field ;
78use Filament \Forms \Components \Repeater ;
89use Filament \Forms \Components \Select ;
910use Filament \Forms \Components \TextInput ;
11+ use Filament \Schemas \Components \Grid ;
1012use Filament \Schemas \Components \Section ;
1113use Filament \Schemas \Components \Utilities \Get ;
1214
@@ -15,73 +17,163 @@ class VisibilityRulesSchema
1517 public static function make (): array
1618 {
1719 return [
18- Section::make ('Visibility rules ' )
20+ Section::make ('Show/Hide Rules ' )
1921 ->collapsible ()
2022 ->collapsed (false )
2123 ->columnSpanFull ()
2224 ->compact (true )
23- ->description (__ ('Show or hide this field based on the value of another field ' ))
25+ ->description (__ ('Control when this field appears based on other field values or record properties ' ))
2426 ->schema ([
2527 Repeater::make ('config.visibilityRules ' )
2628 ->hiddenLabel ()
2729 ->schema ([
2830 Select::make ('logic ' )
29- ->label (__ ('Logic ' ))
31+ ->label (__ ('When to show this field ' ))
3032 ->options ([
31- 'AND ' => __ ('All conditions must be true (AND) ' ),
32- 'OR ' => __ ('Any condition can be true (OR) ' ),
33+ 'AND ' => __ ('All conditions must be met ' ),
34+ 'OR ' => __ ('Any condition can be met ' ),
3335 ])
3436 ->default ('AND ' )
3537 ->required (),
3638 Repeater::make ('conditions ' )
3739 ->hiddenLabel ()
3840 ->schema ([
39- Select::make ('field ' )
40- ->label (__ ('Field ' ))
41- ->placeholder (__ ('Select a field ' ))
42- ->searchable ()
43- ->live ()
44- ->options (function ($ livewire ) {
45- $ excludeUlid = null ;
46- if (method_exists ($ livewire , 'getMountedTableActionRecord ' )) {
47- $ record = $ livewire ->getMountedTableActionRecord ();
48- if ($ record && isset ($ record ->ulid )) {
49- $ excludeUlid = $ record ->ulid ;
50- }
51- }
52-
53- return FieldOptionsHelper::getFieldOptions ($ livewire , $ excludeUlid );
54- })
55- ->required (),
56- Select::make ('operator ' )
57- ->label (__ ('Condition ' ))
58- ->live ()
59- ->options ([
60- 'equals ' => __ ('Equals ' ),
61- 'not_equals ' => __ ('Does not equal ' ),
62- 'contains ' => __ ('Contains ' ),
63- 'not_contains ' => __ ('Does not contain ' ),
64- 'starts_with ' => __ ('Starts with ' ),
65- 'ends_with ' => __ ('Ends with ' ),
66- 'is_empty ' => __ ('Is empty ' ),
67- 'is_not_empty ' => __ ('Is not empty ' ),
68- 'greater_than ' => __ ('Greater than ' ),
69- 'less_than ' => __ ('Less than ' ),
70- 'greater_than_or_equal ' => __ ('Greater than or equal ' ),
71- 'less_than_or_equal ' => __ ('Less than or equal ' ),
72- 'in ' => __ ('In list ' ),
73- 'not_in ' => __ ('Not in list ' ),
74- ])
75- ->required (),
76- TextInput::make ('value ' )
77- ->label (__ ('Value ' ))
78- ->visible (fn (Get $ get ): bool => ! in_array ($ get ('operator ' ), ['is_empty ' , 'is_not_empty ' ])),
41+ Grid::make (2 )
42+ ->columnSpanFull ()
43+ ->schema ([
44+ Select::make ('source ' )
45+ ->label (__ ('Check ' ))
46+ ->options ([
47+ 'field ' => __ ('Another field ' ),
48+ 'model_attribute ' => __ ('Record property ' ),
49+ ])
50+ ->default ('field ' )
51+ ->live ()
52+ ->required ()
53+ ->columnSpan (1 ),
54+
55+ Select::make ('field ' )
56+ ->label (__ ('Which field ' ))
57+ ->placeholder (__ ('Choose a field ' ))
58+ ->searchable ()
59+ ->live ()
60+ ->visible (fn (Get $ get ): bool => $ get ('source ' ) === 'field ' )
61+ ->options (function ($ livewire ) {
62+ $ excludeUlid = null ;
63+ if (method_exists ($ livewire , 'getMountedTableActionRecord ' )) {
64+ $ record = $ livewire ->getMountedTableActionRecord ();
65+ if ($ record && isset ($ record ->ulid )) {
66+ $ excludeUlid = $ record ->ulid ;
67+ }
68+ }
69+
70+ return FieldOptionsHelper::getFieldOptions ($ livewire , $ excludeUlid );
71+ })
72+ ->required (fn (Get $ get ): bool => $ get ('source ' ) === 'field ' )
73+ ->columnSpan (1 ),
74+
75+ Select::make ('model ' )
76+ ->label (__ ('Record type ' ))
77+ ->placeholder (__ ('Choose record type ' ))
78+ ->searchable ()
79+ ->visible (fn (Get $ get ): bool => $ get ('source ' ) === 'model_attribute ' )
80+ ->options (function () {
81+ return ModelAttributeHelper::getAvailableModels ();
82+ })
83+ ->live ()
84+ ->required (fn (Get $ get ): bool => $ get ('source ' ) === 'model_attribute ' )
85+ ->columnSpan (1 ),
86+ ]),
87+
88+ Grid::make (3 )
89+ ->columnSpanFull ()
90+ ->schema ([
91+ Select::make ('property ' )
92+ ->label (__ ('Property ' ))
93+ ->placeholder (function (Get $ get ): string {
94+ return $ get ('source ' ) === 'field '
95+ ? __ ('Choose a field ' )
96+ : __ ('Choose a property ' );
97+ })
98+ ->searchable ()
99+ ->visible (
100+ fn (Get $ get ): bool => ($ get ('source ' ) === 'field ' ) ||
101+ ($ get ('source ' ) === 'model_attribute ' )
102+ )
103+ ->options (function (Get $ get , $ livewire ) {
104+ if ($ get ('source ' ) === 'field ' ) {
105+ $ excludeUlid = null ;
106+ if (method_exists ($ livewire , 'getMountedTableActionRecord ' )) {
107+ $ record = $ livewire ->getMountedTableActionRecord ();
108+ if ($ record && isset ($ record ->ulid )) {
109+ $ excludeUlid = $ record ->ulid ;
110+ }
111+ }
112+
113+ return FieldOptionsHelper::getFieldOptions ($ livewire , $ excludeUlid );
114+ }
115+
116+ if ($ get ('source ' ) === 'model_attribute ' ) {
117+ $ modelClass = $ get ('model ' );
118+ if (! $ modelClass ) {
119+ return [];
120+ }
121+
122+ return ModelAttributeHelper::getModelAttributesForModel ($ modelClass );
123+ }
124+
125+ return [];
126+ })
127+ ->required (
128+ fn (Get $ get ): bool => ($ get ('source ' ) === 'field ' ) ||
129+ ($ get ('source ' ) === 'model_attribute ' && $ get ('model ' ))
130+ )
131+ ->columnSpan (1 ),
132+
133+ Select::make ('operator ' )
134+ ->label (__ ('Is ' ))
135+ ->live ()
136+ ->options ([
137+ 'equals ' => __ ('equal to ' ),
138+ 'not_equals ' => __ ('not equal to ' ),
139+ 'contains ' => __ ('containing ' ),
140+ 'not_contains ' => __ ('not containing ' ),
141+ 'starts_with ' => __ ('starting with ' ),
142+ 'ends_with ' => __ ('ending with ' ),
143+ 'is_empty ' => __ ('empty ' ),
144+ 'is_not_empty ' => __ ('not empty ' ),
145+ 'greater_than ' => __ ('greater than ' ),
146+ 'less_than ' => __ ('less than ' ),
147+ 'greater_than_or_equal ' => __ ('greater than or equal to ' ),
148+ 'less_than_or_equal ' => __ ('less than or equal to ' ),
149+ 'in ' => __ ('one of ' ),
150+ 'not_in ' => __ ('not one of ' ),
151+ ])
152+ ->required ()
153+ ->columnSpan (1 ),
154+
155+ TextInput::make ('value ' )
156+ ->label (__ ('This value ' ))
157+ ->placeholder (__ ('Enter the value to check ' ))
158+ ->visible (fn (Get $ get ): bool => ! in_array ($ get ('operator ' ), ['is_empty ' , 'is_not_empty ' ]))
159+ ->columnSpan (1 ),
160+ ]),
79161 ])
80162 ->collapsible ()
81163 ->itemLabel (function (array $ state ): ?string {
164+ if (isset ($ state ['source ' ]) && $ state ['source ' ] === 'model_attribute ' ) {
165+ if (isset ($ state ['model ' ]) && isset ($ state ['property ' ])) {
166+ $ modelName = class_basename ($ state ['model ' ]);
167+ $ attributeName = ucfirst (str_replace ('_ ' , ' ' , $ state ['property ' ]));
168+
169+ return "{$ modelName } {$ attributeName }" ;
170+ }
171+
172+ return 'Record property ' ;
173+ }
82174
83- if (isset ($ state ['field ' ])) {
84- $ field = Field::find ($ state ['field ' ]);
175+ if (isset ($ state ['source ' ]) && $ state [ ' source ' ] === ' field ' && isset ( $ state [ ' property ' ])) {
176+ $ field = Field::find ($ state ['property ' ]);
85177
86178 return $ field ->name ?? null ;
87179 }
@@ -94,7 +186,7 @@ public static function make(): array
94186 ->columnSpanFull (),
95187 ])
96188 ->collapsible ()
97- ->itemLabel (fn (array $ state ): string => __ ('Visibility Rule ' ))
189+ ->itemLabel (fn (array $ state ): string => __ ('Show/Hide Rule ' ))
98190 ->defaultItems (0 )
99191 ->maxItems (1 )
100192 ->reorderableWithButtons ()
0 commit comments