(bug 42220) Added support for edit notices, which appear on the toolbar

ApiVisualEditor
* Including notices in response to parse actions

ve.init.mw.ViewPageTarget
* Added styles for editNoticeButton and editNotices

ve.init.mw.ViewPageTarget
* Added toolbarEditNoticeButton and toolbarEditNotices
* Combined toolbarEditNoticeButton and toolbarSaveButton setup
* Moved toolbar buttons setup to onLoad (it could vary per-parse now)
* Added tearDownToolbarButtons which fires on deactivate
* Renamed some instances of teardown to tearDown
* Added click handler for toolbarEditNoticeButton
* Added toolbarEditNotices setup method, called on load
* Made notices fade in and out, in by default on load if any
* Made notices hide when save dialog is opened

ve.init.mw.Target
* Added storing of notices on parse

icons, alert, ve.ui-Icons
* Added alert icon

VisualEditor.i18n, VisualEditor
* Added notices button message

Change-Id: I581bf5a005a9c18422f952d71064d17d0ba9b540
This commit is contained in:
Trevor Parscal 2012-11-30 15:09:34 -08:00
parent 26d06a98ed
commit a63f812d52
11 changed files with 718 additions and 7908 deletions

View file

@ -157,10 +157,13 @@ class ApiVisualEditor extends ApiBase {
if ( $params['paction'] === 'parse' ) {
$parsed = $this->getHTML( $page, $parserParams );
$notices = $page->getEditNotices();
if ( $parsed === false ) {
$this->dieUsage( 'Error contacting the Parsoid server', 'parsoidserver' );
} else {
$result = array_merge( array( 'result' => 'success' ), $parsed );
$result = array_merge(
array( 'result' => 'success', 'notices' => $notices ), $parsed
);
}
} else if ( $params['paction'] === 'serialize' ) {
if ( $params['html'] === null ) {
@ -211,7 +214,6 @@ class ApiVisualEditor extends ApiBase {
'diff' => $diff
);
}
}
$this->getResult()->addValue( null, $this->getModuleName(), $result );

View file

@ -13,6 +13,7 @@ $messages['en'] = array(
'visualeditor-ca-editsource' => 'Edit source',
'visualeditor-ca-ve-edit' => 'VisualEditor',
'visualeditor-ca-ve-create' => 'VisualEditor',
'visualeditor-editnotices-button' => '$1 {{PLURAL:$1|notice|notices}}',
'tooltip-ca-ve-edit' => 'Edit this page with VisualEditor',
'accesskey-ca-ve-edit' => '',
'visualeditor-inspector-title' => 'Inspect',
@ -71,6 +72,7 @@ Text for the edit source link in the tab dropdown
Link text of the dedicated VisualEditor Edit tab.
{{Identical|visualeditor}}',
'visualeditor-ca-ve-create' => 'Link text of the dedicated VisualEditor Create tab.',
'visualeditor-editnotices-button' => 'Text of button in the toolbar that shows edit notices (such as MediaWiki:editnotice-0) as a pop-up',
'tooltip-ca-ve-edit' => 'Tooltip of the dedicated VisualEditor Edit tab.',
'accesskey-ca-ve-edit' => '{{Ignore}}',
'visualeditor-inspector-title' => 'Title of an unnamed inspector',

View file

@ -137,6 +137,7 @@ $wgResourceModules += array(
'visualeditor-ca-editsource',
'visualeditor-loadwarning',
'visualeditor-editsummary',
'visualeditor-editnotices-button'
),
),
'ext.visualEditor.base' => $wgVisualEditorResourceTemplate + array(

View file

@ -31,6 +31,48 @@
float: right;
}
.ve-init-mw-viewPageTarget-toolbar-editNoticesButton {
position: relative;
display: inline-block;
vertical-align: top;
line-height: 2.125em;
margin-right: 1em;
padding-left: 30px;
cursor: pointer;
background-repeat: no-repeat;
background-position: left center;
}
.ve-init-mw-viewPageTarget-toolbar-editNotices {
display: none;
position: absolute;
right: -0.5em;
top: 30px;
width: 29em;
font-family: sans-serif;
border: solid 1px #ccc;
padding: 0 0.75em 0 0.75em;
border-radius: 0.25em;
background-color: #fff;
-webkit-box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
z-index: 3;
}
.ve-init-mw-viewPageTarget-toolbar-editNoticesButton-label {
font-size: 0.8em;
color: #555555;
}
.ve-init-mw-viewPageTarget-toolbar-editNotices-notice {
padding: 0.5em 0;
font-size: 0.8em;
line-height: 1.5em;
border-top: solid 1px #ccc;
margin-top: -1px;
}
.ve-init-mw-viewPageTarget-toolbar-saveButton,
.ve-init-mw-viewPageTarget-saveDialog-saveButton {
display: inline-block;

View file

@ -27,6 +27,10 @@ ve.init.mw.ViewPageTarget = function VeInitMwViewPageTarget() {
this.$spinner = $( '<div class="ve-init-mw-viewPageTarget-loadingSpinner"></div>' );
this.$toolbarSaveButton =
$( '<div class="ve-init-mw-viewPageTarget-toolbar-saveButton"></div>' );
this.$toolbarEditNotices =
$( '<div class="ve-init-mw-viewPageTarget-toolbar-editNotices"></div>' );
this.$toolbarEditNoticesButton =
$( '<div class="ve-init-mw-viewPageTarget-toolbar-editNoticesButton"></div>' );
this.$saveDialog =
$( '<div class="ve-init-mw-viewPageTarget-saveDialog"></div>' );
this.$saveDialogSaveButton = null;
@ -91,8 +95,6 @@ ve.init.mw.ViewPageTarget = function VeInitMwViewPageTarget() {
this.setupSkinTabs();
this.setupSectionEditLinks();
if ( this.isViewPage ) {
this.setupToolbarSaveButton();
this.setupSaveDialog();
if ( currentUri.query.veaction === 'edit' ) {
this.activate();
}
@ -209,7 +211,8 @@ ve.init.mw.ViewPageTarget.prototype.deactivate = function ( override ) {
this.restoreSkinTabs();
this.restoreSiteNotice();
this.hideSpinner();
this.detachToolbarSaveButton();
this.tearDownToolbarButtons();
this.detachToolbarButtons();
this.detachSaveDialog();
this.tearDownSurface();
this.showTableOfContents();
@ -227,7 +230,10 @@ ve.init.mw.ViewPageTarget.prototype.deactivate = function ( override ) {
ve.init.mw.ViewPageTarget.prototype.onLoad = function ( dom ) {
this.edited = false;
this.setUpSurface( dom );
this.attachToolbarSaveButton();
this.setupToolbarEditNotices();
this.setupToolbarButtons();
this.setupSaveDialog();
this.attachToolbarButtons();
this.attachSaveDialog();
this.restoreScrollPosition();
this.restoreEditSection();
@ -266,7 +272,7 @@ ve.init.mw.ViewPageTarget.prototype.onLoadError = function ( response, status )
ve.init.mw.ViewPageTarget.prototype.onSave = function ( html ) {
if ( Number( mw.config.get( 'wgArticleId', 0 ) ) === 0 || this.oldId ) {
// This is a page creation, refresh the page
this.teardownBeforeUnloadHandler();
this.tearDownBeforeUnloadHandler();
window.location.href = this.viewUri.extend( {
'venotify': this.oldId ? 'saved' : 'created'
} );
@ -287,7 +293,7 @@ ve.init.mw.ViewPageTarget.prototype.onSave = function ( html ) {
this.hideSaveDialog();
this.resetSaveDialog();
this.replacePageContent( html );
this.teardownBeforeUnloadHandler();
this.tearDownBeforeUnloadHandler();
this.deactivate( true );
mw.util.jsMessage( ve.msg( 'visualeditor-notification-saved', this.pageName ) );
}
@ -382,6 +388,16 @@ ve.init.mw.ViewPageTarget.prototype.onToolbarSaveButtonClick = function () {
}
};
/**
* Handles clicks on the edit notices button in the toolbar.
*
* @method
* @param {jQuery.Event} e
*/
ve.init.mw.ViewPageTarget.prototype.onToolbarEditNoticesClick = function () {
this.$toolbarEditNotices.fadeToggle( 'fast' );
};
/**
* Handles the first transaction in the surface model.
*
@ -436,6 +452,24 @@ ve.init.mw.ViewPageTarget.prototype.onSaveDialogCloseButtonClick = function () {
this.hideSaveDialog();
};
/**
* Gets a list of edit notices.
*
* @method
* @returns {String[]} HTML strings for each edit notice
*/
ve.init.mw.ViewPageTarget.prototype.setupToolbarEditNotices = function () {
var key;
this.$toolbarEditNotices.empty();
for ( key in this.editNotices ) {
this.$toolbarEditNotices.append(
$( '<div>' )
.addClass( 've-init-mw-viewPageTarget-toolbar-editNotices-notice' )
.attr( 'rel', key ).html( this.editNotices[key] )
);
}
};
/**
* Switches to editing mode.
*
@ -594,11 +628,13 @@ ve.init.mw.ViewPageTarget.prototype.setupSectionEditLinks = function () {
};
/**
* Adds content and event bindings to the save button.
* Adds content and event bindings to toolbar buttons.
*
* @method
*/
ve.init.mw.ViewPageTarget.prototype.setupToolbarSaveButton = function () {
ve.init.mw.ViewPageTarget.prototype.setupToolbarButtons = function () {
var editNoticeCount = this.$toolbarEditNotices
.find( '.ve-init-mw-viewPageTarget-toolbar-editNotices-notice' ).length;
this.$toolbarSaveButton
.append(
$( '<span class="ve-init-mw-viewPageTarget-toolbar-saveButton-label"></span>' )
@ -615,6 +651,28 @@ ve.init.mw.ViewPageTarget.prototype.setupToolbarSaveButton = function () {
},
'click': ve.bind( this.onToolbarSaveButtonClick, this )
} );
if ( editNoticeCount ) {
this.$toolbarEditNoticesButton
.addClass( 've-ui-icon-alert' )
.append(
$( '<span>' )
.addClass( 've-init-mw-viewPageTarget-toolbar-editNoticesButton-label' )
.text( ve.msg( 'visualeditor-editnotices-button', editNoticeCount ) )
)
.append( this.$toolbarEditNotices )
.click( ve.bind( this.onToolbarEditNoticesClick, this ) );
this.$toolbarEditNotices.fadeIn( 'fast' );
}
};
/**
* Removes content and event bindings from toolbar buttons.
*
* @method
*/
ve.init.mw.ViewPageTarget.prototype.tearDownToolbarButtons = function () {
this.$toolbarSaveButton.empty().off( 'click' );
this.$toolbarEditNoticesButton.empty().off( 'click' );
};
/**
@ -622,8 +680,10 @@ ve.init.mw.ViewPageTarget.prototype.setupToolbarSaveButton = function () {
*
* @method
*/
ve.init.mw.ViewPageTarget.prototype.attachToolbarSaveButton = function () {
$( '.ve-ui-toolbar .ve-ui-actions' ).append( this.$toolbarSaveButton );
ve.init.mw.ViewPageTarget.prototype.attachToolbarButtons = function () {
$( '.ve-ui-toolbar .ve-ui-actions' )
.append( this.$toolbarEditNoticesButton )
.append( this.$toolbarSaveButton );
};
/**
@ -631,8 +691,9 @@ ve.init.mw.ViewPageTarget.prototype.attachToolbarSaveButton = function () {
*
* @method
*/
ve.init.mw.ViewPageTarget.prototype.detachToolbarSaveButton = function () {
ve.init.mw.ViewPageTarget.prototype.detachToolbarButtons = function () {
this.$toolbarSaveButton.detach();
this.$toolbarEditNoticesButton.detach();
};
/**
@ -854,6 +915,7 @@ ve.init.mw.ViewPageTarget.prototype.hideTableOfContents = function () {
*/
ve.init.mw.ViewPageTarget.prototype.showSaveDialog = function () {
var viewPage = this;
this.$toolbarEditNotices.fadeOut( 'fast' );
this.unlockSaveDialogSaveButton();
this.$saveDialogLoadingIcon.hide();
this.$saveDialog.fadeIn( 'fast' ).find( 'textarea' ).eq( 0 ).focus();
@ -1115,7 +1177,7 @@ ve.init.mw.ViewPageTarget.prototype.setupBeforeUnloadHandler = function () {
*
* @method
*/
ve.init.mw.ViewPageTarget.prototype.teardownBeforeUnloadHandler = function () {
ve.init.mw.ViewPageTarget.prototype.tearDownBeforeUnloadHandler = function () {
// Restore whatever previous onbeforeload hook existed
window.onbeforeunload = this.onBeforeUnloadFallback;
};

View file

@ -39,6 +39,7 @@ ve.init.mw.Target = function VeInitMwTarget( pageName, oldId ) {
this.baseTimeStamp = null;
this.startTimeStamp = null;
this.dom = null;
this.editNotices = null;
this.isMobileDevice = (
'ontouchstart' in window ||
( window.DocumentTouch && document instanceof window.DocumentTouch )
@ -78,6 +79,7 @@ ve.init.mw.Target.onLoad = function ( response ) {
);
} else {
this.dom = $( '<div>' ).html( data.content )[0];
this.editNotices = data.notices;
this.baseTimeStamp = data.basetimestamp;
this.startTimeStamp = data.starttimestamp;
// Everything worked, the page was loaded, continue as soon as the module is ready

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" opacity="0.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<rect id="bottom_1_" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
<polygon style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15 "/>
<g>
<path d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402
C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 958 B

View file

@ -5,6 +5,11 @@
* @license The MIT License (MIT); see LICENSE.txt
*/
.ve-ui-icon-alert {
/* @embed */
background-image: url(images/icons/alert.png);
}
.ve-ui-icon-down {
/* @embed */
background-image: url(images/icons/down.png);

View file

@ -5,6 +5,11 @@
* @license The MIT License (MIT); see LICENSE.txt
*/
.ve-ui-icon-alert {
/* @embed */
background-image: url(images/icons/alert.svg);
}
.ve-ui-icon-down {
/* @embed */
background-image: url(images/icons/down.svg);