[TWIG] Restructure user settings template, making it much easier to use and extend

This commit is contained in:
Hugo Sales 2021-12-08 17:53:29 +00:00
parent 6627006e61
commit d52a043705
Signed by untrusted user: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0
9 changed files with 107 additions and 158 deletions

View File

@ -50,15 +50,16 @@ class Avatar extends Component
/**
* @throws \App\Util\Exception\ClientException
*/
public function onPopulateProfileSettingsTabs(Request $request, &$tabs): bool
public function onPopulateSettingsTabs(Request $request, string $section, &$tabs): bool
{
// TODO avatar template shouldn't be on settings folder
$tabs[] = [
'title' => 'Avatar',
'desc' => 'Change your avatar.',
'controller' => C\Avatar::settings_avatar($request),
];
if ($section === 'profile') {
$tabs[] = [
'title' => 'Avatar',
'desc' => 'Change your avatar.',
'id' => 'settings-avatar',
'controller' => C\Avatar::settings_avatar($request),
];
}
return Event::next;
}

View File

@ -127,6 +127,6 @@ class Avatar extends Controller
}
}
return ['_template' => 'settings/avatar.html.twig', 'avatar' => $form->createView()];
return ['_template' => 'avatar/settings.html.twig', 'avatar' => $form->createView()];
}
}

View File

@ -54,14 +54,16 @@ class Cover extends Plugin
return Event::next;
}
public function onPopulateProfileSettingsTabs(Request $request, &$tabs)
public function onPopulateSettingsTabs(Request $request, string $section, &$tabs)
{
$tabs[] = [
'title' => 'Cover',
'desc' => 'Change your cover.',
'controller' => C\Cover::coverSettings($request),
];
if ($section === 'profile') {
$tabs[] = [
'title' => 'Cover',
'desc' => 'Change your cover.',
'id' => 'settings-cover',
'controller' => C\Cover::coverSettings($request),
];
}
return Event::next;
}

View File

@ -41,9 +41,9 @@ class EmailNotifications extends Plugin
{
public function onAddNotificationTransport(&$form_defs): bool
{
$form_defs['email'] = $form_defs['placeholder'];
$form_defs['email'][] = $form_defs['placeholder']['save']('Email', 'save_email');
unset($form_defs['email']['post_on_status_change']);
$form_defs['Email'] = $form_defs['placeholder'];
$form_defs['Email'][] = $form_defs['placeholder']['save']('Email', 'save_email');
unset($form_defs['Email']['post_on_status_change']);
return Event::next;
}
}

View File

@ -28,17 +28,13 @@ use App\Core\Event;
use App\Core\Modules\Plugin;
use App\Core\Router\RouteLoader;
use App\Core\Router\Router;
use App\Entity\Actor;
use App\Entity\LocalUser;
use App\Util\Common;
use App\Util\Exception\ClientException;
use App\Util\Exception\NotFoundException;
use App\Util\Exception\RedirectException;
use App\Util\Exception\ServerException;
use App\Util\Formatting;
use Plugin\Oomox\Controller as C;
use Symfony\Component\HttpFoundation\Request;
use function App\Core\I18n\_m;
/**
* Profile Colour plugin main class
@ -52,12 +48,8 @@ use function App\Core\I18n\_m;
*/
class Oomox extends Plugin
{
/**
* Map URLs to actions
*
* @param RouteLoader $r
* @return bool
*/
public function onAddRoute(RouteLoader $r): bool
{
@ -66,55 +58,49 @@ class Oomox extends Plugin
return Event::next;
}
/**
* Populates an additional profile user panel section
* Used in templates/settings/base.html.twig
*
* @param Request $request
* @param array $tabs
* @return bool
* @throws \App\Util\Exception\NoLoggedInUser
* @throws RedirectException
* @throws ServerException
* @throws \App\Util\Exception\NoLoggedInUser
*/
public function onPopulateProfileSettingsTabs(Request $request, array &$tabs): bool
public function onPopulateSettingsTabs(Request $request, string $section, array &$tabs): bool
{
$tabs[] = [
'title' => 'Light theme colours',
'desc' => 'Change the theme colours.',
'controller' => C\Oomox::oomoxSettingsLight($request),
];
$tabs[] = [
'title' => 'Dark theme colours',
'desc' => 'Change the theme colours.',
'controller' => C\Oomox::oomoxSettingsDark($request),
];
if ($section === 'colours') {
$tabs[] = [
'title' => 'Light theme colours',
'desc' => 'Change the theme colours.',
'id' => 'settings-light-theme-colours-details',
'controller' => C\Oomox::oomoxSettingsLight($request),
];
$tabs[] = [
'title' => 'Dark theme colours',
'desc' => 'Change the theme colours.',
'id' => 'settings-dark-theme-colours-details',
'controller' => C\Oomox::oomoxSettingsDark($request),
];
}
return Event::next;
}
/**
* Returns Oomox cache key for the given user.
*
* @param LocalUser $user
* @return string
*/
public static function cacheKey(LocalUser $user) :string {
public static function cacheKey(LocalUser $user): string
{
return "oomox-css-{$user->getId()}";
}
/**
* Returns Entity\Oomox if it already exists
*
* @param LocalUser $user
* @return Entity\Oomox|null
*/
public static function getEntity(LocalUser $user): ?Entity\Oomox
{
try {
return Cache::get(self::cacheKey($user), fn() => DB::findOneBy('oomox', ['actor_id' => $user->getId()]));
return Cache::get(self::cacheKey($user), fn () => DB::findOneBy('oomox', ['actor_id' => $user->getId()]));
} catch (NotFoundException $e) {
return null;
}
@ -123,14 +109,12 @@ class Oomox extends Plugin
/**
* Adds to array $styles the generated CSS according to user settings, if any are present.
*
* @param array $styles
* @param string $route
* @return bool
*/
public function onEndShowStyles(array &$styles, string $route)
{
$user = Common::user();
if (!is_null($user) && !is_null(Cache::get(self::cacheKey($user), fn () => self::getEntity($user)))) {
if (!\is_null($user) && !\is_null(Cache::get(self::cacheKey($user), fn () => self::getEntity($user)))) {
$styles[] = Router::url('oomox_css');
}
return Event::next;

View File

@ -61,15 +61,16 @@ class ProfileColor extends Plugin
* @throws RedirectException
* @throws ServerException
*/
public function onPopulateProfileSettingsTabs(Request $request, array &$tabs): bool
public function onPopulateSettingsTabs(Request $request, string $section, array &$tabs): bool
{
// TODO avatar template shouldn't be on settings folder
$tabs[] = [
'title' => 'Color',
'desc' => 'Change your profile color.',
'controller' => C\ProfileColor::profileColorSettings($request),
];
if ($section === 'colours') {
$tabs[] = [
'title' => 'Profile Colour',
'desc' => 'Change your profile colour.',
'id' => 'settings-profile-colour-details',
'controller' => C\ProfileColor::profileColorSettings($request),
];
}
return Event::next;
}

View File

@ -41,8 +41,8 @@ class XMPPNotifications extends Plugin
{
public function onAddNotificationTransport(&$form_defs): bool
{
$form_defs['xmpp'] = $form_defs['placeholder'];
$form_defs['xmpp'][] = $form_defs['placeholder']['save']('XMMP', 'save_xmpp');
$form_defs['XMPP'] = $form_defs['placeholder'];
$form_defs['XMPP'][] = $form_defs['placeholder']['save']('XMMP', 'save_xmpp');
return Event::next;
}
}

View File

@ -95,10 +95,10 @@ class UserPanel extends Controller
return [
'_template' => 'settings/base.html.twig',
'profile' => $personal_form->createView(),
'email' => $email_form->createView(),
'password' => $password_form->createView(),
'language' => $language_form->createView(),
'personal_info_form' => $personal_form->createView(),
'email_form' => $email_form->createView(),
'password_form' => $password_form->createView(),
'language_form' => $language_form->createView(),
'tabbed_forms_notify' => $notifications_form_array,
'open_details_query' => $this->string('open'),
];
@ -327,8 +327,11 @@ class UserPanel extends Controller
$tabbed_forms = [];
foreach ($form_defs as $transport_name => $f) {
unset($f['save']);
$form = Form::create($f);
$tabbed_forms[$transport_name] = $form;
$form = Form::create($f);
$tabbed_forms[$transport_name]['title'] = $transport_name;
$tabbed_forms[$transport_name]['desc'] = _m('{transport} notification settings', ['transport' => $transport_name]);
$tabbed_forms[$transport_name]['id'] = "settings-notifications-{$transport_name}";
$tabbed_forms[$transport_name]['form'] = $form->createView();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
@ -353,7 +356,6 @@ class UserPanel extends Controller
}
}
$tabbed_forms = F\map($tabbed_forms, fn ($f) => $f->createView());
return $tabbed_forms;
}

View File

@ -8,8 +8,11 @@
<link rel="stylesheet" href="{{ asset('assets/default_theme/css/pages/settings.css') }}">
{% endblock stylesheets %}
{% macro settings_details_element(title, summary, form_name, context) %}
<details class="section-title-settings" {{ open_details(context.open_details_query, [ form_name ]) }} id={{ form_name ~ '-details' }}>
{% macro settings_details_element(title, summary, id, details_content, context, details_ids) %}
{% if details_ids is null %}
{% set details_ids = [id] %}
{% endif %}
<details class="section-title-settings" {{ open_details(context.open_details_query, details_ids) }} id={{ id }}>
<summary>
<h3>
{{ title | trans }}
@ -20,87 +23,37 @@
</em>
</summary>
{{ form(attribute(context, form_name) | default) }}
{% if details_content is instanceof('Twig\\Markup') %}
{{ details_content }}
{% else %}
{{ form(details_content) }}
{% endif %}
</details>
{% endmacro settings_details_element %}
{% macro settings_details_container(title, summary, tabs, context) %}
<details class="section-title-settings" {{ open_details(context.open_details_query, tabs) }} id={{ tabs[0] ~ '-details' }}>
<summary>
<h3>
{{ title | trans }}
{{ icon('arrow-down', 'icon icon-details-open') | raw }}
</h3>
<em>
{{ summary | trans }}
</em>
</summary>
{% if title == 'Profile' %}
<li>
<nav class='section-settings-nav'>
<ul>
<li>
{{ _self.settings_details_element('Personal Info', 'Nickname, Homepage, Bio, Self Tags and more.', 'profile', context) }}
</li>
<hr>
{% for tab in context.profile_tabs %}
<li>
<details class="section-title-settings"> {# TODO: add ID and open_details and to parent #}
<summary>
<h3>{{ tab['title'] }}{{ icon('arrow-down', 'icon icon-details-open') | raw }}</h3>
<em>{{ tab['desc'] }}</em>
</summary>
{% include tab['controller']['_template'] with tab['controller'] only %}
</details>
</li>
<hr>
{% endfor %}
</ul>
</nav>
</li>
{% elseif title == 'Email' %}
<li>
{{ form(context.email) }}
</li>
{% elseif title == 'Password' %}
<li>
{{ form(context.password) }}
</li>
{% elseif title == 'Language' %}
<li>
{{ form(context.language) }}
</li>
{% elseif title == 'Notifications' %}
<li>
<nav class='section-settings-nav'>
<ul>
{% for transport, form_transport in context.tabbed_forms_notify %}
<li>
<details class="section-title-settings">
<summary>
<h3>{{ transport }}{{ icon('arrow-down', 'icon icon-details-open') | raw }}</h3>
<em>{{ transport }}'s notification options.</em>
</summary>
<div id="form_{{ transport }}" class='form'>
{{ form(form_transport) }}
</div>
</details>
</li>
<hr>
{% endfor %}
</ul>
</nav>
</li>
{% endif %}
</details>
{% macro settings_details_container(title, summary, container_id, tabs, context) %}
{% set children_ids = [container_id] %}
{% set details_content %}
<nav class='section-settings-nav'>
<ul>
{% for tab in tabs %}
<hr>
<li>
{% set content %}
{% if tab['controller'] is defined %}
{% include tab['controller']['_template'] with tab['controller'] only %}
{% else %}
{{ form(tab['form']) }}
{% endif %}
{% endset %}
{{ _self.settings_details_element(tab['title'], tab['desc'], tab['id'] ~ '-details', content, context) }}
{% set children_ids = children_ids|merge([tab['id'] ~ '-details']) %}
</li>
{% endfor %}
</ul>
</nav>
{% endset %}
{{ _self.settings_details_element(title, summary, container_id, details_content, context, children_ids) }}
{% endmacro settings_details_container %}
{% block body %}
@ -108,22 +61,28 @@
<h2>Settings</h2>
<ul>
<li>
{% set profile_tabs = handle_event('PopulateProfileSettingsTabs', app.request) %}
{{ _self.settings_details_container('Profile', 'Personal Information, Avatar and Profile', ['profile', 'personal-info'], _context) }}
{% set profile_tabs = [{'title': 'Personal Info', 'desc': 'Nickname, Homepage, Bio, Self Tags and more.', 'id': 'settings-personal-info', 'form': personal_info_form}] %}
{% set profile_tabs = profile_tabs|merge(handle_event('PopulateSettingsTabs', app.request, 'profile')) %}
{{ _self.settings_details_container('Profile', 'Personal Information, Avatar and Profile', 'settings-profile-details', profile_tabs, _context) }}
</li>
<hr>
<li>
{{ _self.settings_details_container('Email', 'Set incoming and outgoing email settings', ['email'], _context) }}
{{ _self.settings_details_element('Email', 'Set incoming and outgoing email settings', 'settings-email-details', email_form, _context) }}
</li>
<li>
{{ _self.settings_details_container('Password', 'Change current password', ['password'], _context) }}
{{ _self.settings_details_element('Password', 'Change current password', 'settings-password-details', password_form, _context) }}
</li>
<li>
{{ _self.settings_details_container('Language', 'Select and set language preferences', ['language'], _context) }}
{{ _self.settings_details_element('Language', 'Select and set language preferences', 'settings-language-details', language_form, _context) }}
</li>
<hr>
<li>
{{ _self.settings_details_container('Notifications', 'Enable/disable notifications (Email, XMPP, Replies...)', ['notifications'], _context) }}
{% set colour_tabs = handle_event('PopulateSettingsTabs', app.request, 'colours') %}
{{ _self.settings_details_container('Colours', 'Customize your interface colours', 'settings-colour-details', colour_tabs, _context) }}
</li>
<hr>
<li>
{{ _self.settings_details_container('Notifications', 'Enable/disable notifications (Email, XMPP, Replies...)', 'notifications', tabbed_forms_notify, _context) }}
</li>
</ul>
</nav>