Merge "Add opt-out link to Sidebar for Vector/Logged-in Users Without Abstractions"

This commit is contained in:
jenkins-bot 2020-03-27 00:36:29 +00:00 committed by Gerrit Code Review
commit d2b19192c7
14 changed files with 167 additions and 26 deletions

View File

@ -6,6 +6,7 @@
"vector-skin-desc": "Modern version of MonoBook with fresh look and many usability improvements",
"prefs-vector-enable-vector-1-label": "Use Legacy Vector",
"prefs-vector-enable-vector-1-help": "Over the next few years, we will be gradually updating the Vector skin. Legacy Vector will allow you to view the old version of Vector (as of December 2019). To learn more about the updates, go to our [[mw:Reading/Web/Desktop_Improvements|project page]].",
"vector-opt-out": "Switch to old look",
"vector.css": "/* All CSS here will be loaded for users of the Vector skin */",
"vector.js": "/* All JavaScript here will be loaded for users of the Vector skin */",
"vector-action-addsection": "Add topic",

View File

@ -17,6 +17,7 @@
"vector-skin-desc": "{{desc|what=skin|name=Vector|url=https://www.mediawiki.org/wiki/Skin:Vector}}",
"prefs-vector-enable-vector-1-label": "Label for the checkbox to force Legacy Vector operation accessible via Special:Preferences. When this checkbox is enabled, the December 2019 of Vector is used. When this checkbox is disabled, the actively developed version of Vector is used instead.",
"prefs-vector-enable-vector-1-help": "Detail explaining the operation of the prefs-vector-enable-vector-1-label checkbox.",
"vector-opt-out": "Text of link that takes the user to the Special:Preferences page so they can opt-out of the latest version of Vector and go back to legacy Vector.",
"vector.css": "{{optional}}",
"vector.js": "{{optional}}",
"vector-action-addsection": "Used in the Vector skin. See for example {{canonicalurl:Talk:Main_Page|useskin=vector}}\n{{Identical|Add topic}}",

View File

@ -67,8 +67,7 @@ class SkinVector extends SkinTemplate {
public function getDefaultModules() {
$modules = parent::getDefaultModules();
// add vector skin styles and vector module
$module = $this->getUser()->getOption( Constants::PREF_KEY_SKIN_VERSION )
=== Constants::SKIN_VERSION_LEGACY ? 'skins.vector.styles.legacy' : 'skins.vector.styles';
$module = $this->isLegacy() ? 'skins.vector.styles.legacy' : 'skins.vector.styles';
$modules['styles']['skin'][] = $module;
$modules['core'][] = 'skins.vector.js';
@ -85,9 +84,10 @@ class SkinVector extends SkinTemplate {
* @return VectorTemplate
*/
protected function setupTemplate( $classname ) {
$template = new VectorTemplate( $this->getConfig() );
$template->setTemplateParser( new TemplateParser( __DIR__ . '/templates' ) );
return $template;
$tp = new TemplateParser( __DIR__ . '/templates' );
$vectorTemplate = new VectorTemplate( $this->getConfig(), $tp, $this->isLegacy() );
return $vectorTemplate;
}
/**
@ -98,4 +98,15 @@ class SkinVector extends SkinTemplate {
public function shouldPreloadLogo() {
return true;
}
/**
* Whether or not the legacy skin is being used.
*
* @return bool
*/
private function isLegacy() {
// Note: This will be replaced with FeatureManager when it is ready.
return $this->getUser()->getOption( Constants::PREF_KEY_SKIN_VERSION )
=== Constants::SKIN_VERSION_LEGACY;
}
}

View File

@ -29,15 +29,38 @@ use MediaWiki\MediaWikiServices;
* @ingroup Skins
*/
class VectorTemplate extends BaseTemplate {
/**
* T243281: Code used to track clicks to opt-out link.
*
* The "vct" substring is used to describe the newest "Vector" (non-legacy)
* feature. The "w" describes the web platform. The "1" describes the version
* of the feature.
*
* @see https://wikitech.wikimedia.org/wiki/Provenance
* @var string
*/
private const OPT_OUT_LINK_TRACKING_CODE = 'vctw1';
/** @var TemplateParser */
private $templateParser;
/** @var bool */
private $isLegacy;
/**
* @param TemplateParser $parser
* @param Config $config
* @param TemplateParser $templateParser
* @param bool $isLegacy
*/
public function setTemplateParser( TemplateParser $parser ) {
$this->templateParser = $parser;
public function __construct(
Config $config,
TemplateParser $templateParser,
bool $isLegacy
) {
parent::__construct( $config );
$this->templateParser = $templateParser;
$this->isLegacy = $isLegacy;
}
/**
@ -55,9 +78,10 @@ class VectorTemplate extends BaseTemplate {
}
/**
* Outputs the entire contents of the HTML page
* @return array Returns an array of data shared between Vector and legacy
* Vector.
*/
public function execute() {
private function getSkinData() : array {
$contentNavigation = $this->get( 'content_navigation', [] );
$this->set( 'namespace_urls', $contentNavigation[ 'namespaces' ] );
$this->set( 'view_urls', $contentNavigation[ 'views' ] );
@ -92,7 +116,6 @@ class VectorTemplate extends BaseTemplate {
$htmlHookVectorBeforeFooter = ob_get_contents();
ob_end_clean();
$tp = $this->getTemplateParser();
// Naming conventions for Mustache parameters.
//
// Value type (first segment):
@ -109,7 +132,7 @@ class VectorTemplate extends BaseTemplate {
// It should be followed by the name of the hook in hyphenated lowercase.
//
// Conditionally used values must use null to indicate absence (not false or '').
$params = [
$commonSkinData = [
'html-headelement' => $this->get( 'headelement', '' ),
'html-sitenotice' => $this->get( 'sitenotice', null ),
'html-indicators' => $this->getIndicators(),
@ -171,8 +194,30 @@ class VectorTemplate extends BaseTemplate {
],
];
// Prepare and output the HTML response
echo $tp->processTemplate( 'index', $params );
// The following logic is unqiue to Vector (not used by legacy Vector) and
// is planned to be moved in a follow-up patch.
if ( !$this->isLegacy && $this->getSkin()->getUser()->isLoggedIn() ) {
$commonSkinData['data-navigation']['data-sidebar']['data-emphasized-sidebar-action'] = [
'href' => SpecialPage::getTitleFor(
'Preferences',
false,
// FIXME: should be mw-prefsection-rendering-skin-skin-prefs but this doesn't currently work
// possibly due to the issues T246491
'mw-prefsection-rendering'
)->getLinkURL( 'wprov=' . self::OPT_OUT_LINK_TRACKING_CODE ),
'text' => $this->getMsg( 'vector-opt-out' )->text()
];
}
return $commonSkinData;
}
/**
* Renders the entire contents of the HTML page.
*/
public function execute() {
$tp = $this->getTemplateParser();
echo $tp->processTemplate( 'index', $this->getSkinData() );
}
/**

View File

@ -1,6 +1,11 @@
{{!
@typedef object emphasized-sidebar-action
@prop string href
@prop string text
string html-logo-attributes for site logo. Must be used inside tag e.g. `class="logo" lang="en-gb"`
array array-portals contains options for Portal template
emphasized-sidebar-action data-emphasized-sidebar-action For displaying an emphasized action in the sidebar.
}}
<div id="mw-panel">
@ -10,6 +15,11 @@
{{#array-portals-first}}
{{>Portal}}
{{/array-portals-first}}
{{#data-emphasized-sidebar-action}}
<div class="vector-emphasized-sidebar-action">
<a class="vector-emphasized-sidebar-action-link" href="{{href}}">{{text}}</a>
</div>
{{/data-emphasized-sidebar-action}}
{{#array-portals-rest}}
{{>Portal}}
{{/array-portals-rest}}

View File

@ -0,0 +1,12 @@
@import '../../variables.less';
.vector-emphasized-sidebar-action {
// Align with the portal heading/links
// `.portal` + `.portal .body`
margin: 8px 0 8px @margin-start-portal + @margin-start-portal-body;
}
.vector-emphasized-sidebar-action-link {
font-size: @font-size-portal-list-item;
font-weight: bold;
}

View File

@ -2,14 +2,14 @@
@import 'mediawiki.mixins.less';
.portal {
margin: 0 0.6em 0 0.7em;
margin: 0 0.6em 0 @margin-start-portal;
padding: 0.25em 0;
direction: ltr;
h3 {
color: @color-nav-subtle;
font-weight: normal;
margin: 0.5em 0 0 ( @margin-left-nav-main-body / @font-size-nav-main-heading );
margin: 0.5em 0 0 ( @margin-start-nav-main-body / @font-size-nav-main-heading );
padding: 0.25em 0;
cursor: default;
border: 0;
@ -21,7 +21,7 @@
background-image: linear-gradient( to right, transparent 0, #c8ccd1 35%, #c8ccd1 70%, transparent 100% ); // Standard (Firefox 16+, IE 10+, Safari 6.1+, Chrome 26+)
background-repeat: no-repeat;
background-size: 100% @border-width-base;
margin-left: @margin-left-nav-main-body;
margin-left: @margin-start-portal-body;
padding-top: 0;
ul {
@ -33,7 +33,7 @@
li {
margin: 0;
padding: 0.25em 0;
font-size: @font-size-nav-main-body;
font-size: @font-size-portal-list-item;
line-height: @line-height-nav;
word-wrap: break-word;

View File

@ -34,7 +34,7 @@
.body {
background-image: none;
margin-left: @margin-left-nav-main-body;
margin-left: @margin-start-nav-main-body;
}
}
}

View File

@ -12,6 +12,7 @@
@import 'Portal.less';
@import 'Sidebar.less';
@import 'Footer.less';
@import 'EmphasizedSidebarAction.less';
@import 'externalLinks.less';
}

View File

@ -14,6 +14,16 @@ export const NAVIGATION_TEMPLATE_PARTIALS = Object.assign( {}, SIDEBAR_TEMPLATE_
} );
export const NAVIGATION_TEMPLATE_DATA = {
loggedInWithVariantsAndOptOut: {
'data-personal-menu': PERSONAL_MENU_TEMPLATE_DATA.loggedOut,
'data-namespace-tabs': namespaceTabsData,
'data-page-actions': pageActionsData,
'data-variants': variantsData,
'data-search-box': searchBoxData,
'data-sidebar': SIDEBAR_DATA.withPortalsAndOptOut,
'html-navigation-heading': 'Navigation menu',
'html-logo-attributes': `class="mw-wiki-logo" href="/wiki/Main_Page" title="Visit the main page"`
},
loggedOutWithVariants: {
'data-personal-menu': PERSONAL_MENU_TEMPLATE_DATA.loggedOut,
'data-namespace-tabs': namespaceTabsData,

View File

@ -17,6 +17,19 @@ export const SIDEBAR_DATA = {
'array-portals-rest': [],
'html-logo-attributes': HTML_LOGO_ATTRIBUTES
},
withPortalsAndOptOut: {
'array-portals-first': PORTALS.navigation,
'data-emphasized-sidebar-action': {
href: '#',
text: 'Switch to old look'
},
'array-portals-rest': [
PORTALS.toolbox,
PORTALS.otherProjects,
PORTALS.langlinks
],
'html-logo-attributes': HTML_LOGO_ATTRIBUTES
},
withPortals: {
'array-portals-first': PORTALS.navigation,
'array-portals-rest': [

View File

@ -35,7 +35,7 @@ const HTML_INDICATORS = `<div class="mw-indicators mw-body-content">
</div>
`;
export const vector2019LoggedOut = () => mustache.render( skinTemplate, {
export const vectorLegacyLoggedOut = () => mustache.render( skinTemplate, {
'html-title': 'Vector 2019',
'page-isarticle': true,
'msg-tagline': 'From Wikipedia, the free encyclopedia',
@ -60,7 +60,7 @@ export const vector2019LoggedOut = () => mustache.render( skinTemplate, {
'html-subtitle': placeholder( 'Extensions can configure subtitle', 20 )
}, TEMPLATE_PARTIALS );
export const vector2019LoggedIn = () => mustache.render( skinTemplate, {
export const vectorLegacyLoggedIn = () => mustache.render( skinTemplate, {
'html-title': 'Vector 2019',
'page-isarticle': true,
'msg-tagline': 'From Wikipedia, the free encyclopedia',
@ -78,3 +78,22 @@ export const vector2019LoggedIn = () => mustache.render( skinTemplate, {
'html-printfooter': `Retrieved from <a dir="ltr" href="#">https://en.wikipedia.org/w/index.php?title=this&oldid=blah</a>`,
'html-catlinks': placeholder( 'Category links component from mediawiki core', 50 )
}, TEMPLATE_PARTIALS );
export const vectorLoggedIn = () => mustache.render( skinTemplate, {
'html-title': 'Vector 2020',
'page-isarticle': true,
'msg-tagline': 'From Wikipedia, the free encyclopedia',
'html-userlangattributes': htmluserlangattributes,
'msg-jumptonavigation': 'Jump to navigation',
'msg-jumptosearch': 'Jump to search',
'data-navigation': NAVIGATION_TEMPLATE_DATA.loggedInWithVariantsAndOptOut,
// site specific
'data-footer': FOOTER_TEMPLATE_DATA,
'html-sitenotice': placeholder( 'a site notice or central notice banner may go here', 70 ),
// article dependent
'html-bodycontent': placeholder( 'Article content goes here' ),
'html-printfooter': `Retrieved from <a dir="ltr" href="#">https://en.wikipedia.org/w/index.php?title=this&oldid=blah</a>`,
'html-catlinks': placeholder( 'Category links component from mediawiki core', 50 )
}, TEMPLATE_PARTIALS );

View File

@ -1,6 +1,10 @@
<?php
namespace MediaWiki\Skins\Vector\Tests\Integration;
use GlobalVarConfig;
use MediaWikiIntegrationTestCase;
use TemplateParser;
use VectorTemplate;
use Wikimedia\TestingAccessWrapper;
/**
@ -11,14 +15,17 @@ use Wikimedia\TestingAccessWrapper;
*
* @coversDefaultClass \VectorTemplate
*/
class VectorTemplateTest extends \MediaWikiTestCase {
class VectorTemplateTest extends MediaWikiIntegrationTestCase {
/**
* @return \VectorTemplate
*/
private function provideVectorTemplateObject() {
$template = new \VectorTemplate( \GlobalVarConfig::newInstance() );
$template->setTemplateParser( new \TemplateParser() );
$template = new VectorTemplate(
GlobalVarConfig::newInstance(),
new TemplateParser(),
true
);
return $template;
}
@ -128,7 +135,7 @@ class VectorTemplateTest extends \MediaWikiTestCase {
*/
public function testbuildViewsProps() {
$langAttrs = 'LANG_ATTRIBUTES';
$vectorTemplate = new \VectorTemplate( \GlobalVarConfig::newInstance() );
$vectorTemplate = $this->provideVectorTemplateObject();
$vectorTemplate->set( 'view_urls', [] );
$vectorTemplate->set( 'skin', new \SkinVector() );
$vectorTemplate->set( 'userlangattributes', $langAttrs );

View File

@ -74,7 +74,18 @@
@font-size-nav-main-heading: unit( 12 / @font-size-browser, em ); // Equals `0.75em`.
@font-size-nav-main-body: unit( 12 / @font-size-browser, em );
@margin-left-nav-main-body: 0.5em;
@margin-start-nav-main-body: 0.5em;
// Navigation: Portal
// Font size of the Portal links.
@font-size-portal-list-item: @font-size-nav-main-body;
// Margin space from the start of the Portal (left edge in LTR
// languages).
@margin-start-portal: 0.7em;
// Margin space from the start of the Portal body (left edge in LTR languages).
@margin-start-portal-body: @margin-start-nav-main-body;
// Navigation: Personal tools
@background-position-nav-personal-icon: left ( 4 / @font-size-browser / @font-size-nav-personal );