Refactor: Standardize menu data (DRY!)
VectorTemplate has various functions that repeat themselves, only differing in their choice of names. This refactor begins by focusing on the personal menu and introducing a generic getMenuData function. Hardcoded `p-personal` is replaced with an `id` template key and `msg-label` is renamed `label`. Future patches will simplify VectorTemplate by using this new function. You'll note the resulting PersonalMenu.mustache file is identical to VectorTabs. These will be merged in I098e6921e8f7ef65dacacf09b9c25f70c945e58e Bug: T249372 Change-Id: I5ae44a1008b065381eeff93f9fa625be5c5a9de9
This commit is contained in:
parent
16670834d7
commit
63ee9450b7
|
@ -29,6 +29,13 @@ use MediaWiki\MediaWikiServices;
|
|||
* @ingroup Skins
|
||||
*/
|
||||
class VectorTemplate extends BaseTemplate {
|
||||
/* @var int */
|
||||
private const MENU_TYPE_DEFAULT = 0;
|
||||
/* @var int */
|
||||
private const MENU_TYPE_TABS = 1;
|
||||
/* @var int */
|
||||
private const MENU_TYPE_DROPDOWN = 2;
|
||||
|
||||
/**
|
||||
* T243281: Code used to track clicks to opt-out link.
|
||||
*
|
||||
|
@ -179,7 +186,6 @@ class VectorTemplate extends BaseTemplate {
|
|||
'array-footer-rows' => $this->getTemplateFooterRows(),
|
||||
],
|
||||
'html-navigation-heading' => $this->getMsg( 'navigation-heading' ),
|
||||
'data-personal-menu' => $this->buildPersonalProps(),
|
||||
'data-namespace-tabs' => $this->buildNamespacesProps(),
|
||||
'data-variants' => $this->buildVariantsProps(),
|
||||
'data-page-actions' => $this->buildViewsProps(),
|
||||
|
@ -193,7 +199,7 @@ class VectorTemplate extends BaseTemplate {
|
|||
]
|
||||
)
|
||||
] + $this->buildSidebarProps( $this->get( 'sidebar', [] ) ),
|
||||
];
|
||||
] + $this->getMenuProps();
|
||||
|
||||
// The following logic is unqiue to Vector (not used by legacy Vector) and
|
||||
// is planned to be moved in a follow-up patch.
|
||||
|
@ -491,38 +497,80 @@ class VectorTemplate extends BaseTemplate {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $label to be used to derive the id and human readable label of the menu
|
||||
* @param array $urls to convert to list items stored as string in html-items key
|
||||
* @param int $type of menu (optional) - a plain list (MENU_TYPE_DEFAULT),
|
||||
* a tab (MENU_TYPE_TABS) or a dropdown (MENU_TYPE_DROPDOWN)
|
||||
* @param array $options (optional) to be passed to makeListItem
|
||||
* @return array
|
||||
*/
|
||||
private function buildPersonalProps() : array {
|
||||
$personalTools = $this->getPersonalTools();
|
||||
$props = [
|
||||
'empty-portlet' => ( count( $this->get( 'personal_urls', [] ) ) == 0 ) ? 'emptyPortlet' : '',
|
||||
'msg-label' => $this->getMsg( 'personaltools' )->text(),
|
||||
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
||||
'html-loggedin' => '',
|
||||
'html-personal-tools' => '',
|
||||
'html-lang-selector' => '',
|
||||
|
||||
private function getMenuData(
|
||||
string $label, array $urls = [],
|
||||
int $type = self::MENU_TYPE_DEFAULT, array $options = []
|
||||
) : array {
|
||||
$class = ( count( $urls ) == 0 ) ? 'emptyPortlet' : '';
|
||||
$extraClasses = [
|
||||
self::MENU_TYPE_DROPDOWN => 'vectorMenu',
|
||||
self::MENU_TYPE_TABS => 'vectorTabs',
|
||||
self::MENU_TYPE_DEFAULT => '',
|
||||
];
|
||||
|
||||
$props = [
|
||||
'id' => "p-$label",
|
||||
'label-id' => "p-{$label}-label",
|
||||
'label' => $this->getMsg( $label )->text(),
|
||||
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
||||
'html-items' => '',
|
||||
'class' => trim( "$class $extraClasses[$type]" ),
|
||||
];
|
||||
|
||||
foreach ( $urls as $key => $item ) {
|
||||
$props['html-items'] .= $this->makeListItem( $key, $item, $options );
|
||||
}
|
||||
return $props;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getMenuProps() : array {
|
||||
$personalTools = $this->getPersonalTools();
|
||||
|
||||
// For logged out users Vector shows a "Not logged in message"
|
||||
// This should be upstreamed to core, with instructions for how to hide it for skins
|
||||
// that do not want it.
|
||||
// For now we create a dedicated list item to avoid having to sync the API internals
|
||||
// of makeListItem.
|
||||
if ( !$this->getSkin()->getUser()->isLoggedIn() && User::groupHasPermission( '*', 'edit' ) ) {
|
||||
$props['html-loggedin'] =
|
||||
$loggedIn =
|
||||
Html::element( 'li',
|
||||
[ 'id' => 'pt-anonuserpage' ],
|
||||
$this->getMsg( 'notloggedin' )->text()
|
||||
);
|
||||
} else {
|
||||
$loggedIn = '';
|
||||
}
|
||||
|
||||
// This code doesn't belong here, it belongs in the UniversalLanguageSelector
|
||||
// It is here to workaround the fact that it wants to be the first item in the personal menus.
|
||||
if ( array_key_exists( 'uls', $personalTools ) ) {
|
||||
$props['html-lang-selector'] = $this->makeListItem( 'uls', $personalTools[ 'uls' ] );
|
||||
$uls = $this->makeListItem( 'uls', $personalTools[ 'uls' ] );
|
||||
unset( $personalTools[ 'uls' ] );
|
||||
} else {
|
||||
$uls = '';
|
||||
}
|
||||
|
||||
foreach ( $personalTools as $key => $item ) {
|
||||
$props['html-personal-tools'] .= $this->makeListItem( $key, $item );
|
||||
}
|
||||
$ptools = $this->getMenuData( 'personal', $personalTools );
|
||||
// Append additional link items if present.
|
||||
$ptools['html-items'] = $uls . $loggedIn . $ptools['html-items'];
|
||||
// Unlike other menu items, there is no language key corresponding with its menu key.
|
||||
// Inconsistently this language key lives inside `personaltools`
|
||||
// This line can be removed once the core message `personal` has been added.
|
||||
$ptools['label'] = $this->getMsg( 'personaltools' )->text();
|
||||
|
||||
return $props;
|
||||
return [
|
||||
'data-personal-menu' => $ptools,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
{{!
|
||||
string|null empty-portlet
|
||||
string msg-label
|
||||
string|null html-userlangattributes
|
||||
string|null html-lang-selector
|
||||
string|null html-loggedin
|
||||
string|null html-personal-tools
|
||||
@see MenuDefinition
|
||||
}}
|
||||
|
||||
<div id="p-personal" role="navigation" {{#empty-portlet}}class="{{empty-portlet}}"{{/empty-portlet}} aria-labelledby="p-personal-label">
|
||||
<h3 id="p-personal-label">{{msg-label}}</h3>
|
||||
<div id="{{id}}" role="navigation" class="{{class}}" aria-labelledby="{{label-id}}">
|
||||
<h3 id="{{label-id}}">{{label}}</h3>
|
||||
<ul {{{html-userlangattributes}}}>
|
||||
{{{html-lang-selector}}}
|
||||
{{{html-loggedin}}}
|
||||
{{{html-personal-tools}}}
|
||||
{{{html-items}}}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
string html-dataAfterContent
|
||||
string html-navigation-heading heading for entire navigation that is usually hidden to screen
|
||||
readers
|
||||
object data-personal-menu See PersonalMenu.mustache for documentation.
|
||||
MenuDefinition data-personal-menu See PersonalMenu.mustache for documentation.
|
||||
object data-namespace-tabs. See VectorTabs.mustache for documentation.
|
||||
object data-variants. See VectorMenu.mustache for documentation.
|
||||
object data-page-actions. See VectorTabs.mustache for documentation.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
string html-dataAfterContent
|
||||
string html-navigation-heading heading for entire navigation that is
|
||||
usually hidden to screen readers
|
||||
object data-personal-menu See PersonalMenu.mustache for documentation.
|
||||
MenuDefinition data-personal-menu See PersonalMenu.mustache for documentation.
|
||||
object data-namespace-tabs. See VectorTabs.mustache for documentation.
|
||||
object data-variants. See VectorMenu.mustache for documentation.
|
||||
object data-page-actions. See VectorTabs.mustache for documentation.
|
||||
|
|
|
@ -1,28 +1,45 @@
|
|||
import personalMenuTemplate from '!!raw-loader!../includes/templates/PersonalMenu.mustache';
|
||||
import { htmluserlangattributes } from './utils';
|
||||
|
||||
/**
|
||||
* @type {MenuDefinition}
|
||||
*/
|
||||
const loggedOut = {
|
||||
'msg-label': 'Personal tools',
|
||||
id: 'p-personal',
|
||||
class: '',
|
||||
'label-id': 'p-personal-label',
|
||||
label: 'Personal tools',
|
||||
'html-userlangattributes': htmluserlangattributes,
|
||||
'html-loggedin': '<li id="pt-anonuserpage">Not logged in</li>',
|
||||
'html-personal-tools': `<li id="pt-anontalk"><a href="/wiki/Special:MyTalk" title="Discussion about edits from this IP address [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-anoncontribs"><a href="/wiki/Special:MyContributions" title="A list of edits made from this IP address [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-createaccount"><a href="/w/index.php?title=Special:CreateAccount&returnto=Main+Page" title="You are encouraged to create an account and log in; however, it is not mandatory">Create account</a></li><li id="pt-login"><a href="/w/index.php?title=Special:UserLogin&returnto=Main+Page" title="You're encouraged to log in; however, it's not mandatory. [⌃⌥o]" accesskey="o">Log in</a></li>`
|
||||
'html-items': `'<li id="pt-anonuserpage">Not logged in</li><li id="pt-anontalk"><a href="/wiki/Special:MyTalk" title="Discussion about edits from this IP address [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-anoncontribs"><a href="/wiki/Special:MyContributions" title="A list of edits made from this IP address [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-createaccount"><a href="/w/index.php?title=Special:CreateAccount&returnto=Main+Page" title="You are encouraged to create an account and log in; however, it is not mandatory">Create account</a></li><li id="pt-login"><a href="/w/index.php?title=Special:UserLogin&returnto=Main+Page" title="You're encouraged to log in; however, it's not mandatory. [⌃⌥o]" accesskey="o">Log in</a></li>`
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {MenuDefinition}
|
||||
*/
|
||||
const loggedInWithEcho = {
|
||||
'msg-label': 'Personal tools',
|
||||
id: 'p-personal',
|
||||
'label-id': 'p-personal-label',
|
||||
label: 'Personal tools',
|
||||
'html-userlangattributes': htmluserlangattributes,
|
||||
'html-loggedin': '',
|
||||
'html-personal-tools': `<li id="pt-userpage"><a href="/wiki/User:Jdlrobson" dir="auto" title="Your user page [⌃⌥.]" accesskey=".">Jdlrobson</a></li><li id="pt-notifications-alert"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your alerts">Alerts (0)</a></li><li id="pt-notifications-notice"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray" data-counter-num="3" data-counter-text="3" title="Your notices">Notices (3)</a></li><li id="pt-mytalk"><a href="/wiki/User_talk:Jdlrobson" title="Your talk page [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-sandbox"><a href="/wiki/User:Jdlrobson/sandbox" title="Your sandbox">Sandbox</a></li><li id="pt-preferences"><a href="/wiki/Special:Preferences" title="Your preferences">Preferences</a></li><li id="pt-betafeatures"><a href="/wiki/Special:Preferences#mw-prefsection-betafeatures" title="Beta features">Beta</a></li><li id="pt-watchlist"><a href="/wiki/Special:Watchlist" title="A list of pages you are monitoring for changes [⌃⌥l]" accesskey="l">Watchlist</a></li><li id="pt-mycontris"><a href="/wiki/Special:Contributions/Jdlrobson" title="A list of your contributions [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-logout"><a href="/w/index.php?title=Special:UserLogout&returnto=Main+Page&returntoquery=useskin%3Dvector" title="Log out">Log out</a></li>`
|
||||
'html-items': `<li id="pt-userpage"><a href="/wiki/User:Jdlrobson" dir="auto" title="Your user page [⌃⌥.]" accesskey=".">Jdlrobson</a></li><li id="pt-notifications-alert"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your alerts">Alerts (0)</a></li><li id="pt-notifications-notice"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray" data-counter-num="3" data-counter-text="3" title="Your notices">Notices (3)</a></li><li id="pt-mytalk"><a href="/wiki/User_talk:Jdlrobson" title="Your talk page [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-sandbox"><a href="/wiki/User:Jdlrobson/sandbox" title="Your sandbox">Sandbox</a></li><li id="pt-preferences"><a href="/wiki/Special:Preferences" title="Your preferences">Preferences</a></li><li id="pt-betafeatures"><a href="/wiki/Special:Preferences#mw-prefsection-betafeatures" title="Beta features">Beta</a></li><li id="pt-watchlist"><a href="/wiki/Special:Watchlist" title="A list of pages you are monitoring for changes [⌃⌥l]" accesskey="l">Watchlist</a></li><li id="pt-mycontris"><a href="/wiki/Special:Contributions/Jdlrobson" title="A list of your contributions [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-logout"><a href="/w/index.php?title=Special:UserLogout&returnto=Main+Page&returntoquery=useskin%3Dvector" title="Log out">Log out</a></li>`
|
||||
};
|
||||
|
||||
const ULS_LANGUAGE_SELECTOR = '<li class="uls-trigger active"><a href="#">English</a></li>';
|
||||
|
||||
/**
|
||||
* @type {MenuDefinition}
|
||||
*/
|
||||
const loggedInWithULS = {
|
||||
'msg-label': 'Personal tools',
|
||||
id: 'p-personal',
|
||||
'label-id': 'p-personal-label',
|
||||
label: 'Personal tools',
|
||||
'html-userlangattributes': htmluserlangattributes,
|
||||
'html-lang-selector': '<li class="uls-trigger active"><a href="#">English</a></li>',
|
||||
'html-loggedin': '',
|
||||
'html-personal-tools': `<li id="pt-userpage"><a href="/wiki/User:Jdlrobson" dir="auto" title="Your user page [⌃⌥.]" accesskey=".">Jdlrobson</a></li><li id="pt-notifications-alert"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your alerts">Alerts (0)</a></li><li id="pt-notifications-notice"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray" data-counter-num="3" data-counter-text="3" title="Your notices">Notices (3)</a></li><li id="pt-mytalk"><a href="/wiki/User_talk:Jdlrobson" title="Your talk page [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-sandbox"><a href="/wiki/User:Jdlrobson/sandbox" title="Your sandbox">Sandbox</a></li><li id="pt-preferences"><a href="/wiki/Special:Preferences" title="Your preferences">Preferences</a></li><li id="pt-betafeatures"><a href="/wiki/Special:Preferences#mw-prefsection-betafeatures" title="Beta features">Beta</a></li><li id="pt-watchlist"><a href="/wiki/Special:Watchlist" title="A list of pages you are monitoring for changes [⌃⌥l]" accesskey="l">Watchlist</a></li><li id="pt-mycontris"><a href="/wiki/Special:Contributions/Jdlrobson" title="A list of your contributions [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-logout"><a href="/w/index.php?title=Special:UserLogout&returnto=Main+Page&returntoquery=useskin%3Dvector" title="Log out">Log out</a></li>`
|
||||
'html-items': `${ULS_LANGUAGE_SELECTOR}<li id="pt-userpage"><a href="/wiki/User:Jdlrobson" dir="auto" title="Your user page [⌃⌥.]" accesskey=".">Jdlrobson</a></li><li id="pt-notifications-alert"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-bell mw-echo-notifications-badge-all-read" data-counter-num="0" data-counter-text="0" title="Your alerts">Alerts (0)</a></li><li id="pt-notifications-notice"><a href="/wiki/Special:Notifications" class="mw-echo-notifications-badge mw-echo-notification-badge-nojs oo-ui-icon-tray" data-counter-num="3" data-counter-text="3" title="Your notices">Notices (3)</a></li><li id="pt-mytalk"><a href="/wiki/User_talk:Jdlrobson" title="Your talk page [⌃⌥n]" accesskey="n">Talk</a></li><li id="pt-sandbox"><a href="/wiki/User:Jdlrobson/sandbox" title="Your sandbox">Sandbox</a></li><li id="pt-preferences"><a href="/wiki/Special:Preferences" title="Your preferences">Preferences</a></li><li id="pt-betafeatures"><a href="/wiki/Special:Preferences#mw-prefsection-betafeatures" title="Beta features">Beta</a></li><li id="pt-watchlist"><a href="/wiki/Special:Watchlist" title="A list of pages you are monitoring for changes [⌃⌥l]" accesskey="l">Watchlist</a></li><li id="pt-mycontris"><a href="/wiki/Special:Contributions/Jdlrobson" title="A list of your contributions [⌃⌥y]" accesskey="y">Contributions</a></li><li id="pt-logout"><a href="/w/index.php?title=Special:UserLogout&returnto=Main+Page&returntoquery=useskin%3Dvector" title="Log out">Log out</a></li>`
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object.<string, MenuDefinition>}
|
||||
*/
|
||||
const PERSONAL_MENU_TEMPLATE_DATA = {
|
||||
loggedOut,
|
||||
loggedInWithEcho,
|
||||
|
|
|
@ -4,18 +4,6 @@ import '../resources/skins.vector.styles/Portal.less';
|
|||
import '../.storybook/common.less';
|
||||
import { placeholder, htmluserlangattributes } from './utils';
|
||||
|
||||
/**
|
||||
* @typedef {Object} PortletContext
|
||||
* @prop {string} portal-id
|
||||
* @prop {string} html-tooltip
|
||||
* @prop {string} msg-label-id
|
||||
* @prop {string} [html-userlangattributes]
|
||||
* @prop {string} msg-label
|
||||
* @prop {string} html-portal-content
|
||||
* @prop {string} [html-after-portal]
|
||||
* @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {PortletContext} data
|
||||
* @return {HTMLElement}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @typedef {Object} MenuDefinition
|
||||
* @prop {string} id
|
||||
* @prop {string} label-id
|
||||
* @prop {string} label
|
||||
* @prop {string} html-items
|
||||
* @prop {string} [class] of menu
|
||||
* @prop {string} [html-userlangattributes]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PortletContext
|
||||
* @prop {string} portal-id
|
||||
* @prop {string} html-tooltip
|
||||
* @prop {string} msg-label-id
|
||||
* @prop {string} [html-userlangattributes]
|
||||
* @prop {string} msg-label
|
||||
* @prop {string} html-portal-content
|
||||
* @prop {string} [html-after-portal]
|
||||
* @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal.
|
||||
*/
|
Loading…
Reference in New Issue