diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0c7654..d77ed5b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
## ChangeLog for MatomoAnalytics
+### 1.0.6 (29-06-2022)
+* Require MediaWiki 1.38.0
+* Modernise MatomoAnalyticsOOUIForm
+
### 1.0.5.14 (07-09-2021)
* Add CI for MediaWiki standards and security
diff --git a/extension.json b/extension.json
index d4eb759..1552663 100644
--- a/extension.json
+++ b/extension.json
@@ -6,12 +6,12 @@
"Universal Omega"
],
"url": "https://github.com/miraheze/MatomoAnalytics",
- "version": "1.0.5.14",
+ "version": "1.0.6",
"descriptionmsg": "matomoanalytics-desc",
"license-name": "GPL-3.0-or-later",
"type": "specialpage",
"requires": {
- "MediaWiki": ">= 1.35.3"
+ "MediaWiki": ">= 1.38.0"
},
"AvailableRights": [
"noanalytics"
@@ -54,16 +54,16 @@
},
"ResourceModules": {
"ext.matomoanalytics.oouiform": {
- "scripts": [
- "ext.matomoanalytics.oouiform.edit.ooui.js",
- "ext.matomoanalytics.oouiform.ooui.js"
- ],
- "styles": "ext.matomoanalytics.oouiform.ooui.less",
+ "scripts": "ext.matomoanalytics.oouiform.ooui.js",
+ "targets": [ "desktop", "mobile" ],
"dependencies": [
- "oojs-ui",
- "mediawiki.editfont.styles"
- ],
- "targets": [ "desktop", "mobile" ]
+ "mediawiki.storage",
+ "oojs-ui-widgets"
+ ]
+ },
+ "ext.matomoanalytics.oouiform.styles": {
+ "targets": [ "desktop", "mobile" ],
+ "styles": "ext.matomoanalytics.oouiform.ooui.less"
}
},
"ResourceFileModulePaths": {
diff --git a/includes/MatomoAnalyticsOOUIForm.php b/includes/MatomoAnalyticsOOUIForm.php
index b4ff600..f7f41bb 100644
--- a/includes/MatomoAnalyticsOOUIForm.php
+++ b/includes/MatomoAnalyticsOOUIForm.php
@@ -5,119 +5,76 @@ class MatomoAnalyticsOOUIForm extends OOUIHTMLForm {
protected $mSubSectionBeforeFields = false;
public function wrapForm( $html ) {
- $html = Xml::tags( 'div', [ 'id' => 'baseform' ], $html );
+ $html = Xml::tags( 'div', [ 'id' => 'matomoanalytics' ], $html );
return parent::wrapForm( $html );
}
protected function wrapFieldSetSection( $legend, $section, $attributes, $isRoot ) {
- if ( $isRoot ) {
- $wrapper = new OOUI\PanelLayout( [
- 'expanded' => false,
- 'scrollable' => true,
- 'framed' => true,
- 'infusable' => false,
- 'classes' => [ 'oo-ui-stackLayout oo-ui-indexLayout-stackLayout' ]
- ] );
+ $layout = parent::wrapFieldSetSection( $legend, $section, $attributes, $isRoot );
- $layout = new OOUI\PanelLayout( [
- 'expanded' => false,
- 'scrollable' => true,
- 'framed' => true,
- 'infusable' => false,
- 'classes' => [ 'oo-ui-tabPanelLayout' ]
- ] );
+ $layout->addClasses( [ 'matomoanalytics-fieldset-wrapper' ] );
+ $layout->removeClasses( [ 'oo-ui-panelLayout-framed' ] );
+
+ return $layout;
+ }
+
+ public function getBody() {
+ $tabPanels = [];
+ foreach ( $this->mFieldTree as $key => $val ) {
+ if ( !is_array( $val ) ) {
+ wfDebug( __METHOD__ . " encountered a field not attached to a section: '{$key}'" );
+
+ continue;
+ }
+
+ $label = $this->getLegend( $key );
- $wrapper->appendContent( $layout );
- } else {
- $wrapper = $layout = new OOUI\PanelLayout( [
+ $content =
+ $this->getHeaderHtml( $key ) .
+ $this->displaySection(
+ $val,
+ '',
+ "mw-section-{$key}-"
+ ) .
+ $this->getFooterHtml( $key );
+
+ $tabPanels[] = new \OOUI\TabPanelLayout( 'mw-section-' . $key, [
+ 'classes' => [ 'mw-htmlform-autoinfuse-lazy' ],
+ 'label' => $label,
+ 'content' => new \OOUI\FieldsetLayout( [
+ 'classes' => [ 'matomoanalytics-section-fieldset' ],
+ 'id' => "mw-section-{$key}",
+ 'label' => $label,
+ 'items' => [
+ new \OOUI\Widget( [
+ 'content' => new \OOUI\HtmlSnippet( $content )
+ ] ),
+ ],
+ ] ),
'expanded' => false,
- 'padded' => true,
'framed' => true,
- 'infusable' => false,
] );
}
- $layout->appendContent(
- new OOUI\FieldsetLayout( [
- 'label' => $legend,
- 'infusable' => false,
- 'items' => [
- new OOUI\Widget( [
- 'content' => new OOUI\HtmlSnippet( $section )
- ] ),
- ],
- ] + $attributes )
- );
-
- return $wrapper;
- }
+ $indexLayout = new \OOUI\IndexLayout( [
+ 'infusable' => true,
+ 'expanded' => false,
+ 'autoFocus' => false,
+ 'classes' => [ 'matomoanalytics-tabs' ],
+ ] );
- public function getBody() {
- $fakeTabs = [];
-
- foreach ( $this->getFormSections() as $i => $key ) {
- $fakeTabs[] = Html::rawElement(
- 'div',
- [
- 'class' =>
- 'oo-ui-widget oo-ui-widget-enabled oo-ui-optionWidget oo-ui-tabOptionsWidget oo-ui-labelElement' .
- ( $i === 0 ? 'oo-ui-optionWidget-selected' : '' )
- ],
- Html::element(
- 'a',
- [
- 'class' => 'oo-ui-labelElement-label',
- 'href' => '#mw-section-' . $key
- ],
- $this->getLegend( $key )
- )
- );
- }
+ $indexLayout->addTabPanels( $tabPanels );
- $fakeTabsHtml = Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-layout oo-ui-panelLayout oo-ui-indexLayout-tabPanel'
- ],
- Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-widget oo-ui-widget-enabled ooui-selectWidget oo-ui-selectWidget-depressed oo-ui-tabSelectWidget'
- ],
- implode( $fakeTabs )
- )
- );
-
- return Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-layout oo-ui-panelLayout oo-ui-paenlLayout-framed mw-baseform-faketabs'
- ],
- Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-layout oo-ui-menuLayout oo-ui-menuLayout-static oo-ui-menuLayout-top oo-ui-menuLayout-showMenu oo-ui-indexLayout'
- ],
- Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-menuLayout-menu'
- ],
- $fakeTabsHtml
- ) .
- Html::rawElement(
- 'div',
- [
- 'class' => 'oo-ui-menuLayout-content mw-htmlform-autoinfuse-lazy'
- ],
- $this->displaySection( $this->mFieldTree, '', 'mw-section-' )
- )
- )
- );
- }
+ $header = $this->formatFormHeader();
+
+ $form = new \OOUI\PanelLayout( [
+ 'framed' => true,
+ 'expanded' => false,
+ 'classes' => [ 'matomoanalytics-tabs-wrapper' ],
+ 'content' => $indexLayout
+ ] );
- public function getFormSections() {
- return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
+ return $header . $form;
}
}
diff --git a/includes/MatomoAnalyticsViewer.php b/includes/MatomoAnalyticsViewer.php
index 7a89f41..81f732a 100644
--- a/includes/MatomoAnalyticsViewer.php
+++ b/includes/MatomoAnalyticsViewer.php
@@ -26,7 +26,7 @@ public function getFormDescriptor(
'visithour' => $mA->getVisitsPerServerHour(),
'visitpages' => $mA->getVisitPages(),
'visitduration' => $mA->getVisitDurations(),
- 'visitpass' => $mA->getVisitDaysPassed()
+ 'visitpass' => $mA->getVisitDaysPassed(),
];
$formDescriptor = [];
@@ -36,7 +36,7 @@ public function getFormDescriptor(
'type' => 'info',
'label' => $label,
'default' => (string)$value,
- 'section' => $type
+ 'section' => $type,
];
}
}
@@ -51,7 +51,7 @@ public function getForm(
$htmlForm = new MatomoAnalyticsOOUIForm( $formDescriptor, $context, 'matomoanalytics-labels' );
- $htmlForm->setId( 'mw-baseform-analytics' );
+ $htmlForm->setId( 'matomoanalytics-form' );
$htmlForm->suppressDefaultSubmit();
return $htmlForm;
diff --git a/includes/SpecialAnalytics.php b/includes/SpecialAnalytics.php
index 40c87c4..f3e6291 100644
--- a/includes/SpecialAnalytics.php
+++ b/includes/SpecialAnalytics.php
@@ -14,21 +14,13 @@ public function execute( $par ) {
$out = $this->getOutput();
$out->addWikiMsg( 'matomoanalytics-header' );
+
$out->addModules( [ 'ext.matomoanalytics.oouiform' ] );
+ $out->addModuleStyles( [ 'ext.matomoanalytics.oouiform.styles' ] );
+ $out->addModuleStyles( [ 'oojs-ui-widgets.styles' ] );
$analyticsViewer = new MatomoAnalyticsViewer();
$htmlForm = $analyticsViewer->getForm( $this->getContext() );
- $sectionTitles = $htmlForm->getFormSections();
-
- $sectTabs = [];
- foreach ( $sectionTitles as $key ) {
- $sectTabs[] = [
- 'name' => $key,
- 'label' => $htmlForm->getLegend( $key )
- ];
- }
-
- $out->addJsConfigVars( 'wgMatomoAnalyticsOOUIFormTabs', $sectTabs );
$htmlForm->show();
}
diff --git a/modules/ext.matomoanalytics.oouiform.edit.ooui.js b/modules/ext.matomoanalytics.oouiform.edit.ooui.js
deleted file mode 100644
index 4f6844e..0000000
--- a/modules/ext.matomoanalytics.oouiform.edit.ooui.js
+++ /dev/null
@@ -1,35 +0,0 @@
-( function () {
- mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
- var widget, lastValue,
- $target = $root.find( '#mw-input-wpeditfont' );
-
- if (
- !$target.length ||
- $target.closest( '.mw-htmlform-autoinfuse-lazy' ).length
- ) {
- return;
- }
-
- try {
- widget = OO.ui.infuse( $target );
- } catch ( err ) {
- return;
- }
-
- // Style options
- widget.dropdownWidget.menu.items.forEach( function ( item ) {
- item.$label.addClass( 'mw-editfont-' + item.getData() );
- } );
-
- function updateLabel( value ) {
- // Style selected item label
- widget.dropdownWidget.$label
- .removeClass( 'mw-editfont-' + lastValue )
- .addClass( 'mw-editfont-' + value );
- lastValue = value;
- }
-
- widget.on( 'change', updateLabel );
- updateLabel( widget.getValue() );
- } );
-}() );
diff --git a/modules/ext.matomoanalytics.oouiform.ooui.js b/modules/ext.matomoanalytics.oouiform.ooui.js
index c66e777..b590afc 100644
--- a/modules/ext.matomoanalytics.oouiform.ooui.js
+++ b/modules/ext.matomoanalytics.oouiform.ooui.js
@@ -1,61 +1,23 @@
( function () {
$( function () {
- var $baseform, tabs, wrapper, previousTab, switchingNoHash;
+ var tabs, previousTab, switchingNoHash;
- $baseform = $( '#baseform' );
+ tabs = OO.ui.infuse( $( '.matomoanalytics-tabs' ) );
- // Make sure the accessibility tip is selectable so that screen reader users take notice,
- // but hide it by default to reduce visual clutter.
- // Make sure it becomes visible when focused.
- $( '
' ).addClass( 'mw-navigation-hint' )
- .text( mw.msg( 'baseform-tabs-navigation-hint' ) )
- .attr( 'tabIndex', 0 )
- .prependTo( '#mw-content-text' );
+ tabs.$element.addClass( 'matomoanalytics-tabs-infused' );
- tabs = new OO.ui.IndexLayout( {
- expanded: false,
- // Do not remove focus from the tabs menu after choosing a tab
- autoFocus: false
- } );
-
- mw.config.get( 'wgMatomoAnalyticsOOUIFormTabs' ).forEach( function ( tabConfig ) {
- var panel, $panelContents;
-
- panel = new OO.ui.TabPanelLayout( tabConfig.name, {
- expanded: false,
- label: tabConfig.label
+ function enhancePanel( panel ) {
+ var $infuse = $( panel.$element ).find( '.matomoanalytics-infuse' );
+ $infuse.each( function () {
+ try {
+ OO.ui.infuse( this );
+ } catch ( error ) {
+ return;
+ }
} );
- $panelContents = $( '#mw-section-' + tabConfig.name );
-
- // Hide the unnecessary PHP PanelLayouts
- // (Do not use .remove(), as that would remove event handlers for everything inside them)
- $panelContents.parent().detach();
-
- panel.$element.append( $panelContents );
- tabs.addTabPanels( [ panel ] );
-
- // Remove duplicate labels
- // (This must be after .addTabPanels(), otherwise the tab item doesn't exist yet)
- $panelContents.children( 'legend' ).remove();
- $panelContents.attr( 'aria-labelledby', panel.getTabItem().getElementId() );
- } );
-
- wrapper = new OO.ui.PanelLayout( {
- expanded: false,
- padded: false,
- framed: true
- } );
-
- wrapper.$element.append( tabs.$element );
-
- $baseform.prepend( wrapper.$element );
-
- $( '.mw-baseform-faketabs' ).remove();
-
- function enhancePanel( panel ) {
if ( !panel.$element.data( 'mw-section-infused' ) ) {
- // mw-htmlform-autoinfuse-lazy class has been removed by replacing faketabs
+ panel.$element.removeClass( 'mw-htmlform-autoinfuse-lazy' );
mw.hook( 'htmlform.enhance' ).fire( panel.$element );
panel.$element.data( 'mw-section-infused', true );
}
@@ -67,20 +29,16 @@
if ( switchingNoHash ) {
return;
}
-
// Handle hash manually to prevent jumping,
// therefore save and restore scrollTop to prevent jumping.
scrollTop = $( window ).scrollTop();
-
// Changing the hash apparently causes keyboard focus to be lost?
// Save and restore it. This makes no sense though.
active = document.activeElement;
- location.hash = '#mw-section-' + panel.getName();
-
+ location.hash = '#' + panel.getName();
if ( active ) {
active.focus();
}
-
$( window ).scrollTop( scrollTop );
}
@@ -88,18 +46,16 @@
/**
* @ignore
- * @param {string} name the name of a tab without the prefix ("mw-section-")
+ * @param {string} name The name of a tab
* @param {boolean} [noHash] A hash will be set according to the current
* open section. Use this flag to suppress this.
*/
- function switchBaseFormTab( name, noHash ) {
+ function switchMatomoAnalyticsTab( name, noHash ) {
if ( noHash ) {
switchingNoHash = true;
}
-
tabs.setTabPanel( name );
enhancePanel( tabs.getCurrentTabPanel() );
-
if ( noHash ) {
switchingNoHash = false;
}
@@ -110,17 +66,16 @@
function detectHash() {
var hash = location.hash,
matchedElement, $parentSection;
- if ( hash.match( /^#mw-section-[\w]+$/ ) ) {
- mw.storage.session.remove( 'mwbaseform-prevTab' );
- switchBaseFormTab( hash.replace( '#mw-section-', '' ) );
+ if ( hash.match( /^#mw-section-[\w-]+$/ ) ) {
+ mw.storage.session.remove( 'matomoanalytics-prevTab' );
+ switchMatomoAnalyticsTab( hash.slice( 1 ) );
} else if ( hash.match( /^#mw-[\w-]+$/ ) ) {
matchedElement = document.getElementById( hash.slice( 1 ) );
- $parentSection = $( matchedElement ).parent().closest( '[id^="mw-section-"]' );
-
+ $parentSection = $( matchedElement ).closest( '.matomoanalytics-section-fieldset' );
if ( $parentSection.length ) {
- mw.storage.session.remove( 'mwbaseform-prevTab' );
+ mw.storage.session.remove( 'matomoanalytics-prevTab' );
// Switch to proper tab and scroll to selected item.
- switchBaseFormTab( $parentSection.attr( 'id' ).replace( 'mw-section-', '' ), true );
+ switchMatomoAnalyticsTab( $parentSection.attr( 'id' ), true );
matchedElement.scrollIntoView();
}
}
@@ -131,24 +86,23 @@
if ( hash.match( /^#mw-[\w-]+/ ) ) {
detectHash();
} else if ( hash === '' ) {
- switchBaseFormTab( 'personal', true );
+ switchMatomoAnalyticsTab( $( '[id*=mw-section-]' ).attr( 'id' ), true );
}
} )
// Run the function immediately to select the proper tab on startup.
.trigger( 'hashchange' );
// Restore the active tab after saving
- previousTab = mw.storage.session.get( 'mwbaseform-prevTab' );
+ previousTab = mw.storage.session.get( 'matomoanalytics-prevTab' );
if ( previousTab ) {
- switchBaseFormTab( previousTab, true );
+ switchMatomoAnalyticsTab( previousTab, true );
// Deleting the key, the tab states should be reset until we press Save
- mw.storage.session.remove( 'mwbaseform-prevTab' );
+ mw.storage.session.remove( 'matomoanalytics-prevTab' );
}
- $( '#mw-baseform-form' ).on( 'submit', function () {
+ $( '#matomoanalytics-form' ).on( 'submit', function () {
var value = tabs.getCurrentTabPanelName();
- mw.storage.session.set( 'mwbaseform-prevTab', value );
+ mw.storage.session.set( 'matomoanalytics-prevTab', value );
} );
-
} );
}() );
diff --git a/modules/ext.matomoanalytics.oouiform.ooui.less b/modules/ext.matomoanalytics.oouiform.ooui.less
index cdb4216..60cf2b0 100644
--- a/modules/ext.matomoanalytics.oouiform.ooui.less
+++ b/modules/ext.matomoanalytics.oouiform.ooui.less
@@ -1,126 +1,83 @@
-@import 'mediawiki.mixins';
-
-/* Reuses colors from mediawiki.legacy/shared.css */
-.mw-email-not-authenticated .oo-ui-labelWidget,
-.mw-email-none .oo-ui-labelWidget {
- padding: 0.5em;
- border: 1px solid #fde29b;
- background-color: #fdf1d1;
- color: #000;
-}
-/* Authenticated email field has its own class too. Unstyled by default */
-/*
-.mw-email-authenticated .oo-ui-labelWidget { }
-*/
-
-/* This is needed because add extra buttons in a weird way */
-.mw-baseform-buttons .mw-htmlform-submit-buttons {
- display: inline;
- margin: 0;
+#matomoanalytics {
+ filter: brightness( 1 );
}
-.mw-baseform-buttons {
- margin-top: 1em;
-}
+.matomoanalytics-tabs {
+ .matomoanalytics-fieldset-wrapper {
+ padding-right: 0;
+ padding-left: 0;
-#baseformcontrol {
- margin-right: 0.5em;
-}
+ &:first-child {
+ padding-top: 0;
+ }
-/*
- * Hide, but keep accessible for screen-readers.
- */
-.client-js .mw-navigation-hint:not( :focus ) {
- .mixin-screen-reader-text;
+ &:last-child {
+ padding-bottom: 0;
+ }
+ }
}
-/* Most outer Panellayout:
- * Decrease contrast of `border` slightly as padding/border combination is sufficient
- * accessibility wise and focus of content is more important here. */
-#baseform .oo-ui-panelLayout-framed {
+.matomoanalytics-tabs-wrapper.oo-ui-panelLayout-framed,
+.matomoanalytics-tabs > .oo-ui-menuLayout-content > .oo-ui-indexLayout-stackLayout > .oo-ui-tabPanelLayout {
+ /* Decrease contrast of `border` slightly as padding/border combination is sufficient
+ * accessibility wise and focus of content is more important here. */
border-color: #c8ccd1;
}
-#baseform .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
- padding-right: 0;
- padding-left: 0;
- border-width: 0;
- border-radius: 0;
- box-shadow: none;
-}
-
-.mw-baseform-faketabs > .oo-ui-menuLayout > .oo-ui-menuLayout-menu a {
- color: inherit;
- text-decoration: none;
-}
-
-/* Disabled JavaScript */
+/* JavaScript disabled */
.client-nojs {
- /* Adjust the borders: frame each instead of the
- * whole tabLayout wrapper */
- #baseform .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed:first-child {
- border-width: 1px 0 0;
- border-color: #c8ccd1;
- }
-
- #baseform .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed:last-child {
- padding-bottom: 0;
- margin-bottom: 0;
- }
-
- /* Fake Tabs to address reflow */
- .mw-baseform-faketabs {
+ // Disable .oo-ui-panelLayout-framed on outer wrapper
+ .matomoanalytics-tabs-wrapper {
border-width: 0;
border-radius: 0;
- box-shadow: none;
+ }
- > .oo-ui-menuLayout > .oo-ui-menuLayout-content > .oo-ui-stackLayout {
- margin-bottom: 1em;
+ .matomoanalytics-tabs {
+ // Hide the tab menu when JS is disabled as we can't use this feature
+ > .oo-ui-menuLayout-menu {
+ display: none;
}
- /* Hide the tab menu when JS is disabled as we can't use this feature */
- > .oo-ui-menuLayout > .oo-ui-menuLayout-menu {
- display: none;
+ .matomoanalytics-section-fieldset {
+ //