-
Notifications
You must be signed in to change notification settings - Fork 0
Improve ContactForm #301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Improve ContactForm #301
Changes from all commits
0d9801e
e488979
8372804
44caf92
d2289fb
85d9cb0
9c29277
3e6234b
fe8d14d
d4c76d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,15 +13,20 @@ | |
use Icinga\Module\Notifications\Model\RotationMember; | ||
use Icinga\Module\Notifications\Model\RuleEscalationRecipient; | ||
use Icinga\Web\Session; | ||
use ipl\Html\Attributes; | ||
use ipl\Html\Contract\FormSubmitElement; | ||
use ipl\Html\FormElement\FieldsetElement; | ||
use ipl\Html\HtmlElement; | ||
use ipl\Html\Text; | ||
use ipl\Sql\Connection; | ||
use ipl\Stdlib\Filter; | ||
use ipl\Validator\CallbackValidator; | ||
use ipl\Validator\EmailAddressValidator; | ||
use ipl\Validator\StringLengthValidator; | ||
use ipl\Web\Common\CsrfCounterMeasure; | ||
use ipl\Web\Compat\CompatForm; | ||
use ipl\Web\FormElement\SuggestionElement; | ||
use ipl\Web\Url; | ||
|
||
class ContactForm extends CompatForm | ||
{ | ||
|
@@ -71,7 +76,8 @@ public function isValidEvent($event) | |
|
||
protected function assemble() | ||
{ | ||
$this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); | ||
$this->addAttributes(['class' => 'contact-form']); | ||
$this->addCsrfCounterMeasure(Session::getSession()->getId()); | ||
|
||
// Fieldset for contact full name and username | ||
$contact = (new FieldsetElement( | ||
|
@@ -83,61 +89,106 @@ protected function assemble() | |
|
||
$this->addElement($contact); | ||
|
||
$channelOptions = ['' => sprintf(' - %s - ', $this->translate('Please choose'))]; | ||
$channelOptions += Channel::fetchChannelNames($this->db); | ||
|
||
$contact->addElement( | ||
'text', | ||
'full_name', | ||
[ | ||
'label' => $this->translate('Full Name'), | ||
'label' => $this->translate('Contact Name'), | ||
'required' => true | ||
] | ||
)->addElement( | ||
'text', | ||
'username', | ||
[ | ||
'label' => $this->translate('Username'), | ||
'validators' => [ | ||
new StringLengthValidator(['max' => 254]), | ||
new CallbackValidator(function ($value, $validator) { | ||
$contact = Contact::on($this->db) | ||
->filter(Filter::equal('username', $value)); | ||
if ($this->contactId) { | ||
$contact->filter(Filter::unequal('id', $this->contactId)); | ||
} | ||
|
||
if ($contact->first() !== null) { | ||
$validator->addMessage($this->translate( | ||
'A contact with the same username already exists.' | ||
)); | ||
|
||
return false; | ||
} | ||
|
||
return true; | ||
}) | ||
] | ||
] | ||
)->addElement( | ||
); | ||
|
||
$contact | ||
->addElement( | ||
new SuggestionElement( | ||
'username', | ||
Url::fromPath( | ||
'notifications/contact/suggest-icinga-web-user', | ||
['showCompact' => true, '_disableLayout' => 1] | ||
), | ||
[ | ||
'label' => $this->translate('Icinga Web User'), | ||
'validators' => [ | ||
new StringLengthValidator(['max' => 254]), | ||
new CallbackValidator(function ($value, $validator) { | ||
$contact = Contact::on($this->db) | ||
->filter(Filter::equal('username', $value)); | ||
if ($this->contactId) { | ||
$contact->filter(Filter::unequal('id', $this->contactId)); | ||
} | ||
|
||
if ($contact->first() !== null) { | ||
$validator->addMessage($this->translate( | ||
'A contact with the same username already exists.' | ||
)); | ||
|
||
return false; | ||
} | ||
|
||
return true; | ||
}) | ||
] | ||
] | ||
) | ||
) | ||
->addHtml( | ||
new HtmlElement( | ||
'p', | ||
new Attributes(['class' => 'description']), | ||
new Text($this->translate( | ||
'Add an Icinga Web user to associate with this contact. Users from external authentication' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, but Add an Icinga Web user to associate with this contact. and Link existing Icinga Web users. both describe the same outcome. Use this:
|
||
. " backends won't be suggested and must be entered manually." | ||
)) | ||
) | ||
); | ||
|
||
$channelQuery = Channel::on($this->db) | ||
->columns(['id', 'name', 'type']); | ||
|
||
$channelNames = []; | ||
$channelTypes = []; | ||
foreach ($channelQuery as $channel) { | ||
$channelNames[$channel->id] = $channel->name; | ||
$channelTypes[$channel->id] = $channel->type; | ||
} | ||
|
||
$defaultChannel = $this->createElement( | ||
'select', | ||
'default_channel_id', | ||
[ | ||
'label' => $this->translate('Default Channel'), | ||
'required' => true, | ||
'class' => 'autosubmit', | ||
'disabledOptions' => [''], | ||
'options' => $channelOptions | ||
'options' => [ | ||
'' => sprintf(' - %s - ', $this->translate('Please choose')) | ||
] + $channelNames, | ||
] | ||
); | ||
|
||
$this->addAddressElements(); | ||
$contact->registerElement($defaultChannel); | ||
|
||
$this->addAddressElements($channelTypes[$defaultChannel->getValue()] ?? null); | ||
|
||
$this->addHtml(new HtmlElement('hr')); | ||
|
||
$this->decorate($defaultChannel); | ||
$this->addHtml($defaultChannel); | ||
$this->addHtml(new HtmlElement( | ||
'p', | ||
new Attributes(['class' => 'description']), | ||
new Text($this->translate( | ||
'Use this to associate actions in the UI, such as incident management, with this contact.' | ||
. ' To successfully receive desktop notifications, this is also required.' | ||
)) | ||
)); | ||
|
||
$this->addElement( | ||
'submit', | ||
'submit', | ||
[ | ||
'label' => $this->contactId === null ? | ||
$this->translate('Add Contact') : | ||
$this->translate('Create Contact') : | ||
$this->translate('Save Changes') | ||
] | ||
); | ||
|
@@ -147,7 +198,7 @@ protected function assemble() | |
'submit', | ||
'delete', | ||
[ | ||
'label' => $this->translate('Delete'), | ||
'label' => $this->translate('Delete Contact'), | ||
'class' => 'btn-remove', | ||
'formnovalidate' => true | ||
] | ||
|
@@ -380,7 +431,7 @@ private function fetchDbValues(): array | |
throw new HttpNotFoundException(t('Contact not found')); | ||
} | ||
|
||
$values['contact'] = [ | ||
$values['contact'] = [ | ||
'full_name' => $contact->full_name, | ||
'username' => $contact->username, | ||
'default_channel_id' => (string) $contact->default_channel_id | ||
|
@@ -399,9 +450,11 @@ private function fetchDbValues(): array | |
/** | ||
* Add address elements for all existing channel plugins | ||
* | ||
* @param ?string $defaultType The selected default channel type | ||
* | ||
* @return void | ||
*/ | ||
private function addAddressElements(): void | ||
private function addAddressElements(?string $defaultType): void | ||
{ | ||
$plugins = $this->db->fetchPairs( | ||
AvailableChannelType::on($this->db) | ||
|
@@ -413,13 +466,20 @@ private function addAddressElements(): void | |
return; | ||
} | ||
|
||
$address = new FieldsetElement('contact_address', ['label' => $this->translate('Addresses')]); | ||
$address = new FieldsetElement('contact_address', ['label' => $this->translate('Channels')]); | ||
$address->addHtml(new HtmlElement( | ||
'p', | ||
new Attributes(['class' => 'description']), | ||
new Text($this->translate('Configure the channels available for this contact here.')) | ||
)); | ||
|
||
$this->addElement($address); | ||
|
||
foreach ($plugins as $type => $label) { | ||
foreach ($plugins as $type => $name) { | ||
$element = $this->createElement('text', $type, [ | ||
'label' => $label, | ||
'validators' => [new StringLengthValidator(['max' => 255])] | ||
'label' => $name, | ||
'validators' => [new StringLengthValidator(['max' => 255])], | ||
'required' => $type === $defaultType | ||
]); | ||
|
||
if ($type === 'email') { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
phpstan: