Storybook: Add stories for logged in and logged out UserLinks

- Update menu helper params to support additional data
- Add UserLinks typing

Follow up to: 298f945983
Change-Id: I0f9d1ac3289101566f437213714b872f6fa9199b
This commit is contained in:
bwang 2021-05-27 16:47:55 -05:00 committed by Bernard Wang
parent a15fd2eb80
commit b4c0e8e67d
5 changed files with 110 additions and 26 deletions

View file

@ -27,3 +27,7 @@
#pt-userpage a { #pt-userpage a {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAx0lEQVQ4jdXSzQmEQAwFYEuYUixhSwgkA8mQgKXYgS3YgXZgCZagHWgHuxf14t8osssGcv145CVJvjk+hBRFK2TrkK1D0cqHkN7CUBRI7L21KAqXMIDModiwD9oAkLlH0i3L+ooGiTWPAPPfJQTIHLGOB9h46YZnKS+3PI8PISW2GkV7FO2Jrb79h4+ODyElsYJYm437NSRWRCWdylgj++U0u+UAZI5E22hsWW03UWQtr2NT66zlCjz8uzNQbFiDN7F5/xB8aj57Ynp2FKI0bAAAAABJRU5ErkJggg==") !important; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAx0lEQVQ4jdXSzQmEQAwFYEuYUixhSwgkA8mQgKXYgS3YgXZgCZagHWgHuxf14t8osssGcv145CVJvjk+hBRFK2TrkK1D0cqHkN7CUBRI7L21KAqXMIDModiwD9oAkLlH0i3L+ooGiTWPAPPfJQTIHLGOB9h46YZnKS+3PI8PISW2GkV7FO2Jrb79h4+ODyElsYJYm437NSRWRCWdylgj++U0u+UAZI5E22hsWW03UWQtr2NT66zlCjz8uzNQbFiDN7F5/xB8aj57Ynp2FKI0bAAAAABJRU5ErkJggg==") !important;
} }
.mw-ui-icon-wikimedia-ellipsis:before {
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Ctitle%3Eellipsis%3C/title%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3Ccircle cx='3' cy='10' r='2'/%3E%3Ccircle cx='17' cy='10' r='2'/%3E%3C/svg%3E") !important;
}

View file

@ -4,7 +4,8 @@
import { menuTemplate } from './Menu.stories.data'; import { menuTemplate } from './Menu.stories.data';
import userLinksTemplateLegacy from '!!raw-loader!../includes/templates/legacy/UserLinks.mustache'; import userLinksTemplateLegacy from '!!raw-loader!../includes/templates/legacy/UserLinks.mustache';
import userLinksTemplate from '!!raw-loader!../includes/templates/UserLinks.mustache'; import userLinksTemplate from '!!raw-loader!../includes/templates/UserLinks.mustache';
import { helperMakeMenuData } from './utils'; import userMenuTemplate from '!!raw-loader!../includes/templates/UserMenu.mustache';
import { helperClassName, helperMakeMenuData } from './utils';
/** /**
* @type {MenuDefinition} * @type {MenuDefinition}
@ -12,7 +13,7 @@ import { helperMakeMenuData } from './utils';
const loggedOut = helperMakeMenuData( const loggedOut = helperMakeMenuData(
'personal', 'personal',
`<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&amp;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&amp;returnto=Main+Page" title="You're encouraged to log in; however, it's not mandatory. [⌃⌥o]" accesskey="o">Log in</a></li>`, `<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&amp;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&amp;returnto=Main+Page" title="You're encouraged to log in; however, it's not mandatory. [⌃⌥o]" accesskey="o">Log in</a></li>`,
'vector-user-menu-legacy' helperClassName( 'vector-user-menu-legacy' )
); );
const ECHO_ITEMS = `<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>`; const ECHO_ITEMS = `<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>`;
@ -27,7 +28,7 @@ const ULS_LANGUAGE_SELECTOR = '<li class="uls-trigger active"><a href="#">Englis
const loggedInWithEcho = helperMakeMenuData( const loggedInWithEcho = helperMakeMenuData(
'personal', 'personal',
`${USERNAME_ITEM}${ECHO_ITEMS}${REST_ITEMS}${LOGOUT_ITEM}`, `${USERNAME_ITEM}${ECHO_ITEMS}${REST_ITEMS}${LOGOUT_ITEM}`,
'vector-user-menu-legacy' helperClassName( 'vector-user-menu-legacy' )
); );
/** /**
@ -36,7 +37,7 @@ const loggedInWithEcho = helperMakeMenuData(
const loggedInWithULS = helperMakeMenuData( const loggedInWithULS = helperMakeMenuData(
'personal', 'personal',
`${ULS_LANGUAGE_SELECTOR}${USERNAME_ITEM}${ECHO_ITEMS}${REST_ITEMS}${LOGOUT_ITEM}`, `${ULS_LANGUAGE_SELECTOR}${USERNAME_ITEM}${ECHO_ITEMS}${REST_ITEMS}${LOGOUT_ITEM}`,
'vector-user-menu-legacy' helperClassName( 'vector-user-menu-legacy' )
); );
/** /**
@ -49,14 +50,46 @@ const PERSONAL_MENU_TEMPLATE_DATA = {
}; };
/** /**
* @type {Object.<string, MenuDefinition|MenuDefinitions>} * @type {UserLinksDataDefinition}
*/ */
const USER_LINKS_LOGGED_IN_TEMPLATE_DATA = { const userLinksData = {
'data-user-page': helperMakeMenuData( 'user-page', USERNAME_ITEM ), 'html-login': `<a href="/w/index.php?title=Special:UserLogin&amp;returnto=Main+Page" class="vector-menu-content-item" title="You are encouraged to log in; however, it is not mandatory [ctrl-option-o]" accesskey="o">Log in</a>`,
'data-notifications': helperMakeMenuData( 'notifications', ECHO_ITEMS ), 'html-vector-anon-user-menu-pages-learn': `(<a href="/wiki/Help:Introduction">learn more</a>)`,
'data-user-menu': helperMakeMenuData( 'personal', REST_ITEMS ) 'html-create-account': `<a href="/w/index.php?title=Special:CreateAccount&amp;returnto=Main+Page" class="mw-ui-button mw-ui-quiet" title="You are encouraged to create an account and log in; however, it is not mandatory">Create account</a>`
}; };
export { PERSONAL_MENU_TEMPLATE_DATA, const additionalMenuData = {
class: 'vector-user-menu vector-menu-dropdown',
'msg-vector-anon-user-menu-pages': `Pages for logged out editors`,
'heading-class': 'mw-ui-icon mw-ui-icon-element mw-ui-icon-wikimedia-ellipsis'
};
/**
* @type {UserLinksDefinition}
*/
const USER_LINKS_LOGGED_IN_TEMPLATE_DATA = {
'is-anon': false,
'data-user-page': helperMakeMenuData( 'user-page', USERNAME_ITEM ),
'data-notifications': helperMakeMenuData( 'notifications', ECHO_ITEMS ),
'data-user-menu': helperMakeMenuData( 'new-personal', REST_ITEMS, Object.assign( additionalMenuData, { 'is-anon': false } ) ),
'data-userlinks': userLinksData
};
/**
* @type {UserLinksDefinition}
*/
const USER_LINKS_LOGGED_OUT_TEMPLATE_DATA = {
'is-anon': true,
'data-user-menu': helperMakeMenuData( 'new-personal', REST_ITEMS, Object.assign( additionalMenuData, { 'is-anon': true } ) ),
'data-userlinks': userLinksData
};
export {
PERSONAL_MENU_TEMPLATE_DATA,
USER_LINKS_LOGGED_IN_TEMPLATE_DATA, USER_LINKS_LOGGED_IN_TEMPLATE_DATA,
menuTemplate, userLinksTemplateLegacy, userLinksTemplate }; USER_LINKS_LOGGED_OUT_TEMPLATE_DATA,
menuTemplate,
userLinksTemplateLegacy,
userLinksTemplate,
userMenuTemplate
};

View file

@ -1,7 +1,9 @@
import mustache from 'mustache'; import mustache from 'mustache';
import { menuTemplate } from './Menu.stories.data'; import { menuTemplate } from './Menu.stories.data';
import { PERSONAL_MENU_TEMPLATE_DATA, USER_LINKS_LOGGED_IN_TEMPLATE_DATA } from './UserLinks.stories.data'; import { PERSONAL_MENU_TEMPLATE_DATA, USER_LINKS_LOGGED_IN_TEMPLATE_DATA, USER_LINKS_LOGGED_OUT_TEMPLATE_DATA } from './UserLinks.stories.data';
import { userLinksTemplateLegacy, userLinksTemplate } from './UserLinks.stories.data'; import { userLinksTemplateLegacy, userLinksTemplate, userMenuTemplate } from './UserLinks.stories.data';
import '../resources/skins.vector.styles.legacy/components/UserLinks.less';
import '../resources/skins.vector.styles/components/UserLinks.less';
export default { export default {
title: 'UserLinks' title: 'UserLinks'
@ -37,10 +39,20 @@ export const legacyLoggedInWithULS = () => mustache.render(
} }
); );
export const userLinks = () => mustache.render( export const loggedInUserLinks = () => mustache.render(
userLinksTemplate, userLinksTemplate,
USER_LINKS_LOGGED_IN_TEMPLATE_DATA, USER_LINKS_LOGGED_IN_TEMPLATE_DATA,
{ {
Menu: menuTemplate Menu: menuTemplate,
UserMenu: userMenuTemplate
}
);
export const loggedOutUserLinks = () => mustache.render(
userLinksTemplate,
USER_LINKS_LOGGED_OUT_TEMPLATE_DATA,
{
Menu: menuTemplate,
UserMenu: userMenuTemplate
} }
); );

View file

@ -66,10 +66,25 @@
* @typedef {Object.<string, MenuDefinition>} MenuDefinitions * @typedef {Object.<string, MenuDefinition>} MenuDefinitions
*/ */
/* /**
* @typedef {MenuDefinition} UserMenuDefinition * @typedef {Object} UserLinksDataDefinition
* @property {boolean} [is-anon] * @property {string} html-login
* @property {string} [html-login] * @property {string} html-create-account
* @property {string} [msg-vector-anon-user-menu-pages] * @property {string} html-vector-anon-user-menu-pages-learn
* @property {string} [html-vector-anon-user-menu-pages-learn] */
/**
* @typedef {MenuDefinition} UserMenuDefinition
* @property {boolean} is-anon
* @property {string} [msg-vector-anon-user-menu-pages]
* @property {UserLinksDataDefinition} [data-userlinks]
*/
/**
* @typedef {Object} UserLinksDefinition
* @property {boolean} is-anon
* @property {MenuDefinition} [data-notifications]
* @property {MenuDefinition} [data-user-page]
* @property {UserMenuDefinition} data-user-menu
* @property {UserLinksDataDefinition} [data-userlinks]
*/ */

View file

@ -19,13 +19,22 @@ const portletAfter = ( html ) => {
const htmlUserLanguageAttributes = `dir="ltr" lang="en-GB"`; const htmlUserLanguageAttributes = `dir="ltr" lang="en-GB"`;
/**
* @param {string} [additionalClassString] to add to the menu class
* @return {Object}
*/
function helperClassName( additionalClassString = '' ) {
return { class: additionalClassString };
}
/** /**
* @param {string} name of the menu * @param {string} name of the menu
* @param {string} htmlItems * @param {string} htmlItems
* @param {string} [additionalClassString] to add to the menu * @param {Object} [additionalData] to add to the menu template data
* @param {string} [additionalData.class]
* @return {MenuDefinition} * @return {MenuDefinition}
*/ */
function helperMakeMenuData( name, htmlItems, additionalClassString = '' ) { function helperMakeMenuData( name, htmlItems, additionalData = {} ) {
let label; let label;
switch ( name ) { switch ( name ) {
case 'personal': case 'personal':
@ -36,13 +45,24 @@ function helperMakeMenuData( name, htmlItems, additionalClassString = '' ) {
break; break;
} }
return { // Handle "class" property separately to ensure it is appended to existing classes
const additionalClassString = additionalData.class;
const additionalDataWithoutClass = Object.assign( {}, additionalData );
delete additionalDataWithoutClass.class;
return Object.assign( {
id: `p-${name}`, id: `p-${name}`,
class: `mw-portlet mw-portlet-${name} vector-menu ${additionalClassString}`, class: `mw-portlet mw-portlet-${name} vector-menu ${additionalClassString}`,
label, label,
'html-user-language-attributes': htmlUserLanguageAttributes, 'html-user-language-attributes': htmlUserLanguageAttributes,
'html-items': htmlItems 'html-items': htmlItems
}; }, additionalDataWithoutClass );
} }
export { placeholder, htmlUserLanguageAttributes, portletAfter, helperMakeMenuData }; export {
placeholder,
htmlUserLanguageAttributes,
portletAfter,
helperClassName,
helperMakeMenuData
};