Yurik has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/327445 )

Change subject: Cleanup tabular data HTML/CSS
......................................................................

Cleanup tabular data HTML/CSS

Bug: T153290
Change-Id: I3ceb45a9feb1ec1daeb798f8bba1ce83276431ac
---
M includes/JCTabularContentView.php
M includes/JCUtils.php
M modules/JsonConfig.css
3 files changed, 177 insertions(+), 72 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/JsonConfig 
refs/changes/45/327445/1

diff --git a/includes/JCTabularContentView.php 
b/includes/JCTabularContentView.php
index 490a38f..cca860f 100644
--- a/includes/JCTabularContentView.php
+++ b/includes/JCTabularContentView.php
@@ -18,91 +18,114 @@
         * Called from an override of AbstractContent::fillParserOutput()
         *
         * @param JCContent|JCTabularContent $content
-        * @param Title $title Context title for parsing
+        * @param Title $pageTitle Context title for parsing
         * @param int|null $revId Revision ID (for {{REVISIONID}})
         * @param ParserOptions $options Parser options
         * @param bool $generateHtml Whether or not to generate HTML
         * @param ParserOutput &$output The output object to fill (reference).
         * @return string
         */
-       public function valueToHtml( JCContent $content, Title $title, $revId, 
ParserOptions $options,
-                                                                $generateHtml, 
ParserOutput &$output ) {
+       public function valueToHtml( JCContent $content, Title $pageTitle, 
$revId,
+                                                                ParserOptions 
$options, $generateHtml, ParserOutput &$output ) {
 
                // Use user's language, and split parser cache.  This should 
not have a big
                // impact because data namespace is rarely viewed, but viewing 
it localized
                // will be valuable
                $lang = $options->getUserLangObj();
 
-               $okClass = [ ];
-               $infoClass = [ 'class' => 'mw-jsonconfig-value-info' ];
-               $errorClass = [ 'class' => 'mw-jsonconfig-error' ];
-               $result = [ ];
+               $infoClass = [ 'class' => 'mw-tabular-value-info' ];
+               $titleHeaders = [];
+               $nameHeaders = [];
+               $typeHeaders = [];
+               $rows = [];
+               $headerAttributes = [];
 
-               $dataAttrs = [ 'class' => 'mw-jsonconfig sortable' ];
+               // Helper to add a class value to an array of attributes
+               $addErr = function ( array $attrs, $isValid ) {
+                       if ( !$isValid ) {
+                               $attrs['class'] = 'mw-tabular-error';
+                       }
+                       return $attrs;
+               };
+
+               // Helper to create a <tr> element out of an array of raw HTML 
values
+               $makeRow = function ( array $values, array $attrs = [] ) {
+                       return Html::rawElement( 'tr', $attrs, implode( '', 
$values ) );
+               };
+
+               $dataAttrs = [ 'class' => 'mw-tabular sortable' ];
                if ( !$content->getValidationData() || 
$content->getValidationData()->error() ) {
-                       $dataAttrs['class'] .= ' mw-jsonconfig-error';
+                       $dataAttrs['class'] .= ' mw-tabular-error';
                }
+
                $flds = $content->getField( [ 'schema', 'fields' ] );
                if ( $flds && !$flds->error() ) {
-                       $vals = [ ];
                        foreach ( $flds->getValue() as $fld ) {
                                $name = $content->getField( 'name', $fld );
+                               $nameIsValid = $name && !$name->error();
+                               $name = $nameIsValid ? $name->getValue() : '';
+
+                               $title = $content->getField( 'title', $fld );
+                               $titleIsValid = $title && !$title->error();
+                               $title =
+                                       $titleIsValid ? 
JCUtils::pickLocalizedString( $title->getValue(), $lang, $name )
+                                               : '';
+
                                $type = $content->getField( 'type', $fld );
-                               $label = $content->getField( 'title', $fld );
+                               $typeIsValid = $type && !$type->error();
+                               $type = $typeIsValid ? $type->getValue() : '';
 
-                               if ( $name && !$name->error() && $type && 
!$type->error() &&
-                                        ( !$label || !$label->error() )
-                               ) {
-                                       $labelAttrs = $okClass;
-                               } else {
-                                       $labelAttrs = $errorClass;
+                               $thAttr = [];
+                               if ( $nameIsValid ) {
+                                       $thAttr['data-name'] = $name;
+                               }
+                               if ( $typeIsValid ) {
+                                       $thAttr['data-type'] = $type;
+                                       $headerAttributes['data-type'] = $type;
                                }
 
-                               if ( $label && !$label->error() ) {
-                                       $label = JCUtils::pickLocalizedString( 
$label->getValue(), $lang );
-                               } elseif ( $name && !$name->error() ) {
-                                       $label = $name->getValue();
-                               } else {
-                                       $label = '';
-                               }
+                               $nameHeaders[] = Html::element( 'th', $addErr( 
$thAttr, $nameIsValid ), $name );
 
-                               $type = !$type || $type->error() ? 'invalid' : 
$type->getValue();
-                               $typeAttrs = $infoClass;
-                               $typeAttrs['title'] = wfMessage( 
'jsonconfig-type-name-' . $type )->plain();
-                               $typeAbbr = wfMessage( 'jsonconfig-type-abbr-' 
. $type )->plain();
+                               $typeHeaders[] =
+                                       Html::element( 'th', $addErr( $thAttr, 
$typeIsValid ),
+                                               $typeIsValid ? wfMessage( 
'jsonconfig-type-name-' . $type )->plain() : '' );
 
-                               $label = htmlspecialchars( $label ) .
-                                                 Html::element( 'span', 
$typeAttrs, $typeAbbr );
-                               $vals[] = Html::rawElement( 'th', $labelAttrs, 
$label );
+                               $titleHeaders[] = Html::element( 'th', $addErr( 
$thAttr, $titleIsValid ), $title );
                        }
-                       $result[] = Html::rawElement( 'tr', $okClass, implode( 
'', $vals ) );
                }
 
                $data = $content->getField( 'data' );
                if ( $data && !$data->error() ) {
                        foreach ( $data->getValue() as $row ) {
-                               list( $row, $rowAttrs ) = self::split( $row );
-                               $vals = [ ];
+                               $rowIsValid = $row && $row instanceof JCValue 
&& !$row->error();
+                               $row = ( $row && $row instanceof JCValue ) ? 
$row->getValue() : $row;
+                               if ( !is_array( $row ) ) {
+                                       continue;
+                               }
+                               $vals = [];
                                foreach ( $row as $column ) {
-                                       list( $column, $columnAttrs ) = 
self::split( $column, 'mw-jsonconfig-value' );
+                                       $colIsValid = $column && $column 
instanceof JCValue && !$column->error();
+                                       $column =
+                                               ( $column && $column instanceof 
JCValue ) ? $column->getValue() : $column;
+                                       $header = $headerAttributes;
+                                       if ( !$colIsValid ) {
+                                               $header['class'] = 
'mw-tabular-error';
+                                       }
+
                                        if ( is_object( $column ) ) {
                                                $valueSize = count( 
(array)$column );
-                                               $column = htmlspecialchars( 
JCUtils::pickLocalizedString( $column, $lang ) ) .
-                                                                 
Html::element( 'span', $infoClass, "($valueSize)" );
-                                               $vals[] = Html::rawElement( 
'td', $columnAttrs, $column );
-                                       } else {
-                                               if ( is_bool( $column ) ) {
-                                                       $column = $column ? '☑' 
: '☐';
-                                               } elseif ( $column === null ) {
-                                                       // TODO: Should we 
append the CSS class instead?
-                                                       $columnAttrs['class'] = 
'mw-jsonconfig-value-null';
-                                                       $column = '';
-                                               }
-                                               // TODO: We should probably 
introduce one CSS class per type
-                                               $vals[] = Html::element( 'td', 
$columnAttrs, $column );
+                                               $column =
+                                                       htmlspecialchars( 
JCUtils::pickLocalizedString( $column, $lang ) ) .
+                                                       Html::element( 'span', 
$infoClass, "($valueSize)" );
+                                       } elseif ( is_bool( $column ) ) {
+                                               $column = $column ? '☑' : '☐';
+                                       } elseif ( $column === null ) {
+                                               $header['class'] = 
'mw-tabular-value-null';
+                                               $column = '';
                                        }
+                                       $vals[] = Html::rawElement( 'td', 
$header, $column );
                                }
-                               $result[] = Html::rawElement( 'tr', $rowAttrs, 
implode( '', $vals ) );
+                               $rows[] = $makeRow( $vals, $rowIsValid ? [] : [ 
'class' => 'mw-tabular-error' ] );
                        }
                }
 
@@ -110,31 +133,15 @@
 
                $html =
                        $content->renderDescription( $lang ) .
-                       Html::rawElement( 'table', $dataAttrs,
-                               Html::rawElement( 'tbody', null, implode( "\n", 
$result ) ) ) .
-                       $content->renderSources( $wgParser->getFreshParser(), 
$title, $revId, $options ) .
+                       Html::rawElement( 'table', $dataAttrs, 
Html::rawElement( 'thead', null, implode( "\n", [
+                                       $makeRow( $titleHeaders, [ 'class' => 
'mw-tabular-row-name' ] ),
+                                       $makeRow( $nameHeaders, [ 'class' => 
'mw-tabular-row-key' ] ),
+                                       $makeRow( $typeHeaders, [ 'class' => 
'mw-tabular-row-type' ] ),
+                               ] ) ) . Html::rawElement( 'tbody', null, 
implode( "\n", $rows ) ) ) .
+                       $content->renderSources( $wgParser->getFreshParser(), 
$pageTitle, $revId, $options ) .
                        $content->renderLicense();
 
                return $html;
-       }
-
-       /**
-        * Converts JCValue into a raw data + class string. In case of an 
error, adds error class
-        * @param JCValue|mixed $data
-        * @param string $class
-        * @return array
-        */
-       private static function split( $data, $class = '' ) {
-               if ( $data instanceof JCValue ) {
-                       if ( $data->error() ) {
-                               if ( $class ) {
-                                       $class .= ' ';
-                               }
-                               $class .= 'mw-jsonconfig-error';
-                       }
-                       $data = $data->getValue();
-               }
-               return [ $data, $class ? [ 'class' => $class ] : null ];
        }
 
        /**
diff --git a/includes/JCUtils.php b/includes/JCUtils.php
index 2ad3f86..83328a1 100644
--- a/includes/JCUtils.php
+++ b/includes/JCUtils.php
@@ -270,9 +270,10 @@
         * or use language fallbacks if message is not defined.
         * @param stdClass $map Dictionary of languageCode => string
         * @param Language|StubUserLang $lang language object
+        * @param bool|string $defaultValue if non-false, use this value in 
case no fallback and no 'en'
         * @return string message from the dictionary or "" if nothing found
         */
-       public static function pickLocalizedString( stdClass $map, $lang ) {
+       public static function pickLocalizedString( stdClass $map, $lang, 
$defaultValue = false ) {
                $langCode = $lang->getCode();
                if ( property_exists( $map, $langCode ) ) {
                        return $map->$langCode;
@@ -286,6 +287,12 @@
                if ( property_exists( $map, 'en' ) ) {
                        return $map->en;
                }
+
+               // We have a custom default, return that
+               if ( $defaultValue !== false ) {
+                       return $defaultValue;
+               }
+
                // Return first available value, or an empty string
                // There might be a better way to get the first value from an 
object
                $map = (array)$map;
diff --git a/modules/JsonConfig.css b/modules/JsonConfig.css
index 59b5815..f0c2418 100644
--- a/modules/JsonConfig.css
+++ b/modules/JsonConfig.css
@@ -101,3 +101,94 @@
        padding: 1em;
        width: 30px;
 }
+
+.mw-tabular {
+       border-collapse: collapse;
+       border-spacing: 0;
+       font-family: 'Bitstream Vera Sans', 'DejaVu Sans', 'Lucida Sans', 
'Lucida Grande', sans-serif;
+       font-style: normal;
+}
+
+.mw-tabular th,
+.mw-tabular td {
+       border: 1px solid gray;
+       padding: 0.5em 1em;
+}
+
+.mw-tabular td {
+       background-color: #eee;
+       font-style: italic;
+}
+
+.mw-tabular .mw-tabular-value {
+       font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, 
Courier, monospace;
+       background-color: #dcfae3;
+}
+
+.mw-tabular .mw-tabular-value-null {
+       background-color: #eaecf0;
+}
+
+.mw-tabular-value-info {
+       float: right;
+       font-weight: bold;
+       font-size: 80%;
+       color: #800080;
+}
+
+.mw-tabular tr {
+       margin-bottom: 0.5em;
+}
+
+.mw-tabular th {
+       background-color: #fff;
+       font-weight: normal;
+}
+
+.mw-tabular-default {
+       opacity: 0.3;
+}
+
+.mw-tabular-same {
+       color: purple;
+       font-weight: bold;
+}
+
+.mw-tabular-error {
+       color: red;
+       font-weight: bold;
+}
+
+.mw-tabular-unknown {
+       color: #ffa100;
+       font-weight: bold;
+}
+
+.mw-tabular caption {
+       /* For stylistic reasons, suppress the caption of the outermost table */
+       display: none;
+}
+
+.mw-tabular table caption {
+       color: gray;
+       display: inline-block;
+       font-size: 10px;
+       font-style: italic;
+       margin-bottom: 0.5em;
+       text-align: left;
+}
+
+.mw-tabular-editnotice {
+       color: #000;
+       border: solid 1px #A8A8A8;
+       padding: 0.5em;
+       margin: 0.5em 0;
+       background-color: #FFF;
+       font-size: 95%;
+       vertical-align: middle;
+}
+
+.mw-tabular-editnotice-icon {
+       padding: 1em;
+       width: 30px;
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/327445
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3ceb45a9feb1ec1daeb798f8bba1ce83276431ac
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/JsonConfig
Gerrit-Branch: master
Gerrit-Owner: Yurik <yu...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to