1818use  Icinga \Web \Session ;
1919use  ipl \Html \Attributes ;
2020use  ipl \Html \DeferredText ;
21+ use  ipl \Html \FormDecoration \DescriptionDecorator ;
2122use  ipl \Html \FormElement \FieldsetElement ;
2223use  ipl \Html \HtmlDocument ;
2324use  ipl \Html \HtmlElement ;
3031use  ipl \Validator \GreaterThanValidator ;
3132use  ipl \Web \Common \CsrfCounterMeasure ;
3233use  ipl \Web \Compat \CompatForm ;
34+ use  ipl \Web \FormDecorator \IcingaFormDecorator ;
3335use  ipl \Web \FormElement \TermInput ;
3436use  ipl \Web \Url ;
3537use  LogicException ;
@@ -190,6 +192,8 @@ public function __construct(int $scheduleId, Connection $db)
190192    {
191193        $ this db  = $ db
192194        $ this scheduleId  = $ scheduleId
195+ 
196+         $ this applyDefaultElementDecorators ();
193197    }
194198
195199    /** 
@@ -599,7 +603,9 @@ protected function assembleModeSelection(): string
599603            '24-7 '  => $ this translate ('24/7 ' )
600604        ];
601605
602-         $ modeListnew  HtmlElement ('ul ' );
606+         $ modeListnew  HtmlElement ('ul ' , Attributes::create ([
607+             'class '  => ['rotation-mode ' , $ this disableModeSelection  ? 'disabled '  : '' ]
608+         ]));
603609        foreach  ($ modesas  $ mode$ label
604610            $ radio$ this createElement ('input ' , 'mode ' , [
605611                'type '  => 'radio ' ,
@@ -681,8 +687,14 @@ protected function assembleModeSelection(): string
681687
682688        $ this addHtml (new  HtmlElement (
683689            'div ' ,
684-             Attributes::create (['class '  => ['rotation-mode ' , $ this disableModeSelection  ? 'disabled '  : '' ]]),
685-             new  HtmlElement ('h2 ' , null , Text::create ($ this translate ('Mode ' ))),
690+             Attributes::create ([
691+                 'class '  => ['control-group ' ]
692+             ]),
693+             new  HtmlElement (
694+                 'div ' ,
695+                 Attributes::create (['class '  => 'control-label-group ' ]),
696+                 Text::create ($ this translate ('Rotation Mode ' ))
697+             ),
686698            $ modeList
687699        ));
688700
@@ -701,12 +713,15 @@ protected function assembleTwentyFourSevenOptions(FieldsetElement $options): Dat
701713        $ optionsaddElement ('number ' , 'interval ' , [
702714            'required '  => true ,
703715            'label '  => $ this translate ('Handoff every ' ),
716+             'description '  => $ this translate ('Have multiple rotation members take turns after this interval. ' ),
704717            'step '  => 1 ,
705718            'min '  => 1 ,
706719            'value '  => 1 ,
707720            'validators '  => [new  GreaterThanValidator ()]
708721        ]);
709722        $ interval$ optionsgetElement ('interval ' );
723+         $ intervalgetDecorators ()
724+             ->replaceDecorator ('Description ' , DescriptionDecorator::class, ['class '  => 'description ' ]);
710725
711726        $ frequency$ optionscreateElement ('select ' , 'frequency ' , [
712727            'required '  => true ,
@@ -793,11 +808,15 @@ protected function assemblePartialDayOptions(FieldsetElement $options): DateTime
793808        $ optionsaddElement ('number ' , 'interval ' , [
794809            'required '  => true ,
795810            'label '  => $ this translate ('Handoff every ' ),
811+             'description '  => $ this translate ('Have multiple rotation members take turns after this interval. ' ),
796812            'step '  => 1 ,
797813            'min '  => 1 ,
798814            'value '  => 1 ,
799815            'validators '  => [new  GreaterThanValidator ()]
800816        ]);
817+         $ interval$ optionsgetElement ('interval ' );
818+         $ intervalgetDecorators ()
819+             ->replaceDecorator ('Description ' , DescriptionDecorator::class, ['class '  => 'description ' ]);
801820
802821        $ selectedFromTime$ fromgetValue ();
803822        foreach  ($ timeOptionsas  $ key$ value
@@ -827,7 +846,6 @@ protected function assemblePartialDayOptions(FieldsetElement $options): DateTime
827846            )
828847        );
829848
830-         $ interval$ optionsgetElement ('interval ' );
831849        $ intervalprependWrapper (
832850            (new  HtmlDocument ())->addHtml (
833851                $ interval
@@ -909,8 +927,12 @@ protected function assembleMultiDayOptions(FieldsetElement $options): DateTime
909927            'step '  => 1 ,
910928            'min '  => 1 ,
911929            'value '  => 1 ,
912-             'label '  => $ this translate ('Handoff every ' )
930+             'label '  => $ this translate ('Handoff every ' ),
931+             'description '  => $ this translate ('Have multiple rotation members take turns after this interval. ' )
913932        ]);
933+         $ interval$ optionsgetElement ('interval ' );
934+         $ intervalgetDecorators ()
935+             ->replaceDecorator ('Description ' , DescriptionDecorator::class, ['class '  => 'description ' ]);
914936
915937        $ timeOptions$ this getTimeOptions ();
916938        $ fromAt$ optionscreateElement ('select ' , 'from_at ' , [
@@ -985,7 +1007,6 @@ protected function assembleMultiDayOptions(FieldsetElement $options): DateTime
9851007            )
9861008        );
9871009
988-         $ interval$ optionsgetElement ('interval ' );
9891010        $ intervalprependWrapper (
9901011            (new  HtmlDocument ())->addHtml (
9911012                $ interval
@@ -1026,17 +1047,9 @@ protected function assemble()
10261047
10271048        $ this addElement ('hidden ' , 'priority ' , ['ignore '  => true ]);
10281049
1029-         $ mode$ this assembleModeSelection ();
1030- 
1031-         $ autoSubmittedBy$ this getRequest ()->getHeader ('X-Icinga-Autosubmittedby ' )[0 ] ?? '' ;
1032-         if  ($ autoSubmittedBy'mode ' ) {
1033-             $ this clearPopulatedValue ('options ' );
1034-             $ this clearPopulatedValue ('first_handoff ' );
1035-         }
1036- 
10371050        $ this addElement ('text ' , 'name ' , [
10381051            'required '  => true ,
1039-             'label '  => $ this translate ('Title ' ),
1052+             'label '  => $ this translate ('Rotation Name ' ),
10401053            'validators '  => [
10411054                new  CallbackValidator (function  ($ value$ validator
10421055                    $ rotationson ($ this db )
@@ -1048,7 +1061,7 @@ protected function assemble()
10481061                    }
10491062
10501063                    if  ($ rotationsfirst () !== null ) {
1051-                         $ validatoraddMessage ($ this translate ('A rotation with this title  already exists ' ));
1064+                         $ validatoraddMessage ($ this translate ('A rotation with this name  already exists ' ));
10521065
10531066                        return  false ;
10541067                    }
@@ -1058,8 +1071,76 @@ protected function assemble()
10581071            ]
10591072        ]);
10601073
1061-         $ optionsnew  FieldsetElement ('options ' );
1062-         $ this addElement ($ options
1074+         $ termValidatorfunction  (array  $ terms
1075+             $ contactTerms
1076+             $ groupTerms
1077+             foreach  ($ termsas  $ term
1078+                 /** @var TermInput\Term $term */ 
1079+                 if  (strpos ($ termgetSearchValue (), ': ' ) === false ) {
1080+                     // TODO: Auto-correct this to a valid type:id pair, if possible 
1081+                     $ termsetMessage ($ this translate ('Is not a contact nor a group of contacts ' ));
1082+                     continue ;
1083+                 }
1084+ 
1085+                 list ($ type$ idexplode (': ' , $ termgetSearchValue (), 2 );
1086+                 if  ($ type'contact ' ) {
1087+                     $ contactTerms$ id$ term
1088+                 } elseif  ($ type'group ' ) {
1089+                     $ groupTerms$ id$ term
1090+                 }
1091+             }
1092+ 
1093+             if  (! empty ($ contactTerms
1094+                 $ contactson (Database::get ()))
1095+                     ->filter (Filter::equal ('id ' , array_keys ($ contactTerms
1096+                 foreach  ($ contactsas  $ contact
1097+                     $ contactTerms$ contactid ]
1098+                         ->setLabel ($ contactfull_name )
1099+                         ->setClass ('contact ' );
1100+                 }
1101+             }
1102+ 
1103+             if  (! empty ($ groupTerms
1104+                 $ groupson (Database::get ()))
1105+                     ->filter (Filter::equal ('id ' , array_keys ($ groupTerms
1106+                 foreach  ($ groupsas  $ group
1107+                     $ groupTerms$ groupid ]
1108+                         ->setLabel ($ groupname )
1109+                         ->setClass ('group ' );
1110+                 }
1111+             }
1112+         };
1113+ 
1114+         $ membersnew  TermInput ('members ' ))
1115+             ->setIgnored ()
1116+             ->setRequired ()
1117+             ->setOrdered ()
1118+             ->setReadOnly ()
1119+             ->setVerticalTermDirection ()
1120+             ->setLabel ($ this translate ('Rotation Members ' ))
1121+             ->setSuggestionUrl ($ this suggestionUrl ->with (['showCompact '  => true , '_disableLayout '  => 1 ]))
1122+             ->on (TermInput::ON_ENRICH , $ termValidator
1123+             ->on (TermInput::ON_ADD , $ termValidator
1124+             ->on (TermInput::ON_SAVE , $ termValidator
1125+             ->on (TermInput::ON_PASTE , $ termValidator
1126+         $ this addElement ($ members
1127+ 
1128+         // TODO: TermInput is not compatible with the new decorators yet: https://github.com/Icinga/ipl-web/pull/317 
1129+         $ legacyDecoratornew  IcingaFormDecorator ();
1130+         $ memberssetDefaultElementDecorator ($ legacyDecorator
1131+         $ legacyDecoratordecorate ($ members
1132+ 
1133+         $ mode$ this assembleModeSelection ();
1134+ 
1135+         $ autoSubmittedBy$ this getRequest ()->getHeader ('X-Icinga-Autosubmittedby ' )[0 ] ?? '' ;
1136+         if  ($ autoSubmittedBy'mode ' ) {
1137+             $ this clearPopulatedValue ('options ' );
1138+             $ this clearPopulatedValue ('first_handoff ' );
1139+         }
1140+ 
1141+         $ this addElement ('fieldset ' , 'options ' );
1142+         /** @var FieldsetElement $options */ 
1143+         $ options$ this getElement ('options ' );
10631144
10641145        if  ($ mode'24-7 ' ) {
10651146            $ firstHandoff$ this assembleTwentyFourSevenOptions ($ options
@@ -1094,7 +1175,7 @@ protected function assemble()
10941175            'aria-describedby '  => 'first-handoff-description ' ,
10951176            'min '  => $ earliestHandoffnull  ? $ earliestHandoffformat ('Y-m-d ' ) : null ,
10961177            'max '  => $ latestHandoffformat ('Y-m-d ' ),
1097-             'label '  => $ this translate ('First Handoff ' ),
1178+             'label '  => $ this translate ('Rotation Start ' ),
10981179            'value '  => $ firstHandoffDefault
10991180            'validators '  => [
11001181                new  CallbackValidator (
@@ -1106,14 +1187,14 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando
11061187                        );
11071188                        if  ($ earliestHandoffnull  && $ chosenHandoff$ earliestHandoff
11081189                            $ validatoraddMessage (sprintf (
1109-                                 $ this translate ('The first handoff  can only happen  after %s ' ),
1190+                                 $ this translate ('The rotation  can only start  after %s ' ),
11101191                                $ earliestHandoffformat ('Y-m-d ' ) // TODO: Use intl here 
11111192                            ));
11121193
11131194                            return  false ;
11141195                        } elseif  ($ chosenHandoff$ latestHandoff
11151196                            $ validatoraddMessage (sprintf (
1116-                                 $ this translate ('The first handoff  can only happen  before %s ' ),
1197+                                 $ this translate ('The rotation  can only start  before %s ' ),
11171198                                $ latestHandoffformat ('Y-m-d ' ) // TODO: Use intl here 
11181199                            ));
11191200
@@ -1138,10 +1219,10 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando
11381219
11391220                    $ actualFirstHandoff$ ruleGeneratorcurrent ()[0 ]->getStartDate ();
11401221                    if  ($ actualFirstHandoffnew  DateTime ()) {
1141-                         return  $ this translate ('The first handoff  will happen  immediately ' );
1222+                         return  $ this translate ('The rotation  will start  immediately ' );
11421223                    } else  {
11431224                        return  sprintf (
1144-                             $ this translate ('The first handoff  will happen  on %s ' ),
1225+                             $ this translate ('The rotation  will start  on %s ' ),
11451226                            (new  \IntlDateFormatter (
11461227                                \Locale::getDefault (),
11471228                                \IntlDateFormatter::MEDIUM ,
@@ -1153,61 +1234,6 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando
11531234            ));
11541235        }
11551236
1156-         $ termValidatorfunction  (array  $ terms
1157-             $ contactTerms
1158-             $ groupTerms
1159-             foreach  ($ termsas  $ term
1160-                 /** @var TermInput\Term $term */ 
1161-                 if  (strpos ($ termgetSearchValue (), ': ' ) === false ) {
1162-                     // TODO: Auto-correct this to a valid type:id pair, if possible 
1163-                     $ termsetMessage ($ this translate ('Is not a contact nor a group of contacts ' ));
1164-                     continue ;
1165-                 }
1166- 
1167-                 list ($ type$ idexplode (': ' , $ termgetSearchValue (), 2 );
1168-                 if  ($ type'contact ' ) {
1169-                     $ contactTerms$ id$ term
1170-                 } elseif  ($ type'group ' ) {
1171-                     $ groupTerms$ id$ term
1172-                 }
1173-             }
1174- 
1175-             if  (! empty ($ contactTerms
1176-                 $ contactson (Database::get ()))
1177-                     ->filter (Filter::equal ('id ' , array_keys ($ contactTerms
1178-                 foreach  ($ contactsas  $ contact
1179-                     $ contactTerms$ contactid ]
1180-                         ->setLabel ($ contactfull_name )
1181-                         ->setClass ('contact ' );
1182-                 }
1183-             }
1184- 
1185-             if  (! empty ($ groupTerms
1186-                 $ groupson (Database::get ()))
1187-                     ->filter (Filter::equal ('id ' , array_keys ($ groupTerms
1188-                 foreach  ($ groupsas  $ group
1189-                     $ groupTerms$ groupid ]
1190-                         ->setLabel ($ groupname )
1191-                         ->setClass ('group ' );
1192-                 }
1193-             }
1194-         };
1195- 
1196-         $ this addElement (
1197-             (new  TermInput ('members ' ))
1198-                 ->setIgnored ()
1199-                 ->setRequired ()
1200-                 ->setOrdered ()
1201-                 ->setReadOnly ()
1202-                 ->setVerticalTermDirection ()
1203-                 ->setLabel ($ this translate ('Members ' ))
1204-                 ->setSuggestionUrl ($ this suggestionUrl ->with (['showCompact '  => true , '_disableLayout '  => 1 ]))
1205-                 ->on (TermInput::ON_ENRICH , $ termValidator
1206-                 ->on (TermInput::ON_ADD , $ termValidator
1207-                 ->on (TermInput::ON_SAVE , $ termValidator
1208-                 ->on (TermInput::ON_PASTE , $ termValidator
1209-         );
1210- 
12111237        $ this addElement ('submit ' , 'submit ' , [
12121238            'label '  => $ this getSubmitLabel ()
12131239        ]);
@@ -1235,7 +1261,7 @@ function ($value, $validator) use ($earliestHandoff, $firstHandoff, $latestHando
12351261            $ this getElement ('submit ' )->prependWrapper ((new  HtmlDocument ())->setHtmlContent (...$ removeButtons
12361262        }
12371263
1238-         $ this addElement ( $ this -> createCsrfCounterMeasure ( Session::getSession ()->getId () ));
1264+         $ this addCsrfCounterMeasure ( Session::getSession ()->getId ());
12391265    }
12401266
12411267    /** 
0 commit comments