[frio] Make addon settings panels keyboard actionable

- Keep the addon panel open after form was submitted
This commit is contained in:
Hypolite Petovan 2021-11-20 04:46:45 -05:00
parent 22a8be5f96
commit 0ca420c949
8 changed files with 153 additions and 17 deletions

View file

@ -242,7 +242,57 @@ Called when the Settings pages are submitted.
### addon_settings
Called when generating the HTML for the addon settings page.
`$b` is the (string) HTML of the addon settings page before the final `</form>` tag.
`$data` is an array containing:
- **addon** (output): Required. The addon folder name.
- **title** (output): Required. The addon settings panel title.
- **href** (output): Optional. If set, will reduce the panel to a link pointing to this URL, can be relative. Incompatible with the following keys.
- **html** (output): Optional. Raw HTML of the addon form elements. Both the `<form>` tags and the submit buttons are taken care of elsewhere.
- **submit** (output): Optional. If unset, a default submit button with `name="<addon name>-submit"` will be generated.
Can take different value types:
- **string**: The label to replace the default one.
- **associative array**: A list of submit button, the key is the value of the `name` attribute, the value is the displayed label.
The first submit button in this list is considered the main one and themes might emphasize its display.
#### Examples
##### With link
```php
$data = [
'addon' => 'advancedcontentfilter',
'title' => DI::l10n()->t('Advanced Content Filter'),
'href' => 'advancedcontentfilter',
];
```
##### With default submit button
```php
$data = [
'addon' => 'fromapp',
'title' => DI::l10n()->t('FromApp Settings'),
'html' => $html,
];
```
##### With no HTML, just a submit button
```php
$data = [
'addon' => 'opmlexport',
'title' => DI::l10n()->t('OPML Export'),
'submit' => DI::l10n()->t('Export RSS/Atom contacts'),
];
```
##### With multiple submit buttons
```php
$data = [
'addon' => 'catavar',
'title' => DI::l10n()->t('Cat Avatar Settings'),
'html' => $html,
'submit' => [
'catavatar-usecat' => DI::l10n()->t('Use Cat as Avatar'),
'catavatar-morecat' => DI::l10n()->t('Another random Cat!'),
'catavatar-emailcat' => DI::pConfig()->get(local_user(), 'catavatar', 'seed', false) ? DI::l10n()->t('Reset to email Cat') : null,
],
];
```
### addon_settings_post
Called when the Addon Settings pages are submitted.

View file

@ -62,9 +62,10 @@ function settings_post(App $a)
}
if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] == 'addon')) {
BaseModule::checkFormSecurityTokenRedirectOnError('/settings/addon', 'settings_addon');
BaseModule::checkFormSecurityTokenRedirectOnError(DI::args()->getQueryString(), 'settings_addon');
Hook::callAll('addon_settings_post', $_POST);
DI::baseUrl()->redirect(DI::args()->getQueryString());
return;
}
@ -438,11 +439,27 @@ function settings_content(App $a)
if ((DI::args()->getArgc() > 1) && (DI::args()->getArgv()[1] === 'addon')) {
$addon_settings_forms = [];
foreach (DI::dba()->selectToArray('hook', ['file', 'function'], ['hook' => 'addon_settings']) as $hook) {
$data = '';
$data = [];
Hook::callSingle(DI::app(), 'addon_settings', [$hook['file'], $hook['function']], $data);
$addon_settings_forms[] = $data;
if (!empty($data['href'])) {
$tpl = Renderer::getMarkupTemplate('settings/addon/link.tpl');
$addon_settings_forms[] = Renderer::replaceMacros($tpl, [
'$addon' => $data['addon'],
'$title' => $data['title'],
'$href' => $data['href'],
]);
} elseif(!empty($data['addon'])) {
$tpl = Renderer::getMarkupTemplate('settings/addon/panel.tpl');
$addon_settings_forms[$data['addon']] = Renderer::replaceMacros($tpl, [
'$addon' => $data['addon'],
'$title' => $data['title'],
'$open' => (DI::args()->getArgv()[2] ?? '') === $data['addon'],
'$html' => $data['html'] ?? '',
'$submit' => $data['submit'] ?? DI::l10n()->t('Save Settings'),
]);
}
}
$tpl = Renderer::getMarkupTemplate('settings/addons.tpl');

View file

@ -0,0 +1 @@
<span class="settings-block fakelink" style="display: block;"><h3><a href="{{$href}}">{{$title}} <i class="glyphicon glyphicon-share"></i></a></h3></span>

View file

@ -0,0 +1,33 @@
<span id="settings_{{$addon}}_inflated" class="settings-block fakelink" style="display: {{if $open}}none{{else}}block{{/if}};" onclick="openClose('settings_{{$addon}}_expanded'); openClose('settings_{{$addon}}_inflated');">
<h3>{{$title}}</h3>
</span>
<div id="settings_{{$addon}}_expanded" class="settings-block" style="display: {{if $open}}block{{else}}none{{/if}};">
<span class="fakelink" onclick="openClose('settings_{{$addon}}_expanded'); openClose('settings_{{$addon}}_inflated');">
<h3>{{$title}}</h3>
</span>
{{$html nofilter}}
{{if $submit}}
<div class="settings-submit-wrapper panel-footer">
{{if $submit|is_string}}
<button type="submit" name="{{$addon}}-submit" class="btn btn-primary settings-submit" value="{{$submit}}">{{$submit}}</button>
{{else}}
{{$count = 1}}
{{foreach $submit as $name => $label}}{{if $label}}
{{if $count == 1}}
<button type="submit" name="{{$name}}" class="btn btn-primary settings-submit" value="{{$label}}">{{$label}}</button>
{{/if}}
{{if $count == 2}}
<div class="btn-group" role="group" aria-label="...">
{{/if}}
{{if $count != 1}}
<button type="submit" name="{{$name}}" class="btn btn-default settings-submit" value="{{$label}}">{{$label}}</button>
{{/if}}
{{$count = $count + 1}}
{{/if}}{{/foreach}}
{{if $submit|count > 1}}
</div>
{{/if}}
{{/if}}
</div>
{{/if}}
</div>

View file

@ -1,8 +1,8 @@
<h1>{{$title}}</h1>
{{foreach $addon_settings_forms as $addon_settings_form}}
{{foreach $addon_settings_forms as $addon => $addon_settings_form}}
<form action="settings/addon" method="post" autocomplete="off">
<form action="settings/addon/{{$addon}}" method="post" autocomplete="off">
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
{{$addon_settings_form nofilter}}
</form>

View file

@ -0,0 +1 @@
<div class="settings-block"><h3><a href="{{$href}}">{{$title}} <i class="glyphicon glyphicon-share"></i></a></h3></div>

View file

@ -0,0 +1,36 @@
<div class="section-subtitle-wrapper panel-heading" role="tab" id="{{$addon}}-settings-title">
<h2>
<button class="btn-link accordion-toggle{{if !$open}} collapsed{{/if}}" data-toggle="collapse" data-parent="#settings-addons" href="#{{$addon}}-settings-content" aria-expanded="false" aria-controls="{{$addon}}-settings-content">
{{$title}}
</button>
</h2>
</div>
<div id="{{$addon}}-settings-content" class="panel-collapse collapse{{if $open}} in{{/if}}" role="tabpanel" aria-labelledby="{{$addon}}-settings-title">
<div class="panel-body">
{{$html nofilter}}
</div>
<div class="panel-footer">
{{if $submit}}
{{if $submit|is_string}}
<button type="submit" name="{{$addon}}-submit" class="btn btn-primary settings-submit" value="{{$submit}}">{{$submit}}</button>
{{else}}
{{$count = 1}}
{{foreach $submit as $name => $label}}{{if $label}}
{{if $count == 1}}
<button type="submit" name="{{$name}}" class="btn btn-primary settings-submit" value="{{$label}}">{{$label}}</button>
{{/if}}
{{if $count == 2}}
<div class="btn-group" role="group" aria-label="...">
{{/if}}
{{if $count != 1}}
<button type="submit" name="{{$name}}" class="btn btn-default settings-submit" value="{{$label}}">{{$label}}</button>
{{/if}}
{{$count = $count + 1}}
{{/if}}{{/foreach}}
{{if $submit|count > 1}}
</div>
{{/if}}
{{/if}}
{{/if}}
</div>
</div>

View file

@ -2,17 +2,15 @@
{{* include the title template for the settings title *}}
{{include file="section_title.tpl" title=$title}}
{{foreach $addon_settings_forms as $addon_settings_form}}
<form action="settings/addon" method="post" autocomplete="off">
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
{{$addon_settings_form nofilter}}
</form>
<div class="panel-group panel-group-settings" id="settings-addons" role="tablist" aria-multiselectable="true">
{{foreach $addon_settings_forms as $addon => $addon_settings_form}}
<form action="settings/addon/{{$addon}}" method="post" autocomplete="off" class="panel">
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
{{$addon_settings_form nofilter}}
</form>
{{foreachelse}}
<div class="alert alert-info" role="alert">{{$no_addon_settings_configured}}</div>
<div class="alert alert-info" role="alert">{{$no_addon_settings_configured}}</div>
{{/foreach}}
</div>
</div>