55 */
66
77import { InteropDataManager } from './interop-data-manager.js' ;
8+ import { WPTFlags } from './wpt-flags.js' ;
89import '../node_modules/@polymer/paper-button/paper-button.js' ;
910import '../node_modules/@polymer/polymer/lib/elements/dom-if.js' ;
1011import '../node_modules/@polymer/paper-icon-button/paper-icon-button.js' ;
@@ -14,7 +15,7 @@ import { afterNextRender } from '../node_modules/@polymer/polymer/lib/utils/rend
1415// InteropDashboard is a custom element that holds the overall interop dashboard.
1516// The dashboard breaks down into top-level summary scores, a small description,
1617// graphs per feature, and a table of currently tracked tests.
17- class InteropDashboard extends PolymerElement {
18+ class InteropDashboard extends WPTFlags ( PolymerElement ) {
1819 static get template ( ) {
1920 return html `
2021 < style >
@@ -81,6 +82,10 @@ class InteropDashboard extends PolymerElement {
8182 grid-area : bottom-desc;
8283 }
8384
85+ .text-center {
86+ text-align : center;
87+ }
88+
8489 .channel-area {
8590 display : flex;
8691 max-width : fit-content;
@@ -91,6 +96,14 @@ class InteropDashboard extends PolymerElement {
9196 box-shadow : var (--shadow-elevation-2dp_-_box-shadow );
9297 }
9398
99+ .channel-area [hidden ] {
100+ display : none;
101+ }
102+
103+ paper-button [hidden ] {
104+ display : none;
105+ }
106+
94107 .channel-area > paper-button {
95108 margin : 0 ;
96109 }
@@ -220,10 +233,6 @@ class InteropDashboard extends PolymerElement {
220233 background : hsl (0 0% 0% / 5% );
221234 }
222235
223- .interop-years {
224- text-align : center;
225- }
226-
227236 .interop-year-text {
228237 display : inline-block;
229238 padding : 0 5px ;
@@ -292,14 +301,24 @@ class InteropDashboard extends PolymerElement {
292301 </ div >
293302 < div class ="grid-container ">
294303 < div class ="grid-item grid-item-header ">
295- < h1 > Interop [[year]] Dashboard </ h1 >
304+ < h1 > [[dashboardTitle]] </ h1 >
296305 < div class ="channel-area ">
297- < paper-button id ="toggleStable " class \$="[[stableButtonClass(stable)]] " on-click ="clickStable "> Stable</ paper-button >
298- < paper-button id ="toggleExperimental " class \$="[[experimentalButtonClass(stable)]] " on-click ="clickExperimental "> Experimental</ paper-button >
306+ < paper-button id ="toggleStable " class \$="[[stableButtonClass(stable, isMobileScoresView)]] " on-click ="clickStable "> Stable</ paper-button >
307+ < paper-button id ="toggleExperimental " class \$="[[experimentalButtonClass(stable, isMobileScoresView)]] " on-click ="clickExperimental "> Experimental</ paper-button >
308+ < paper-button id ="toggleMobile " class \$="[[mobileButtonClass(isMobileScoresView)]] " on-click ="clickMobile " hidden$ ="[[!shouldShowMobileScoresView()]] "> Mobile</ paper-button >
309+ </ div >
310+ < div class ="text-center " hidden$ ="[[!isMobileScoresView]] ">
311+ < p > < i > Mobile browser results and how they are obtained are a work in progress. Scores may not reflect the real level of support for a given feature.</ i > </ p >
299312 </ div >
300313 </ div >
301314 < div class ="grid-item grid-item-summary ">
302- < interop-summary year ="[[year]] " data-manager ="[[dataManager]] " scores ="[[scores]] " stable ="[[stable]] "> </ interop-summary >
315+ < interop-summary
316+ year ="[[year]] "
317+ data-manager ="[[dataManager]] "
318+ scores ="[[scores]] "
319+ stable ="[[stable]] "
320+ is-mobile-scores-view ="[[isMobileScoresView]] ">
321+ </ interop-summary >
303322 </ div >
304323 < div class ="grid-item grid-item-description ">
305324 < p > Interop [[year]] is a cross-browser effort to improve the interoperability of the web —
@@ -373,6 +392,14 @@ class InteropDashboard extends PolymerElement {
373392 </ th >
374393 </ template >
375394 </ template >
395+ < template is ="dom-if " if ="{{isMobileScoresView}} ">
396+ < th class ="sortable-header ">
397+ < div class ="browser-icons single-browser-icon ">
398+ < img src ="/static/wktr_64x64.png " width ="32 " alt ="Safari iOS " title ="Safari iOS " />
399+ </ div >
400+ < img class ="sort-icon " src ="[[getSortIcon(2, sortColumn, isSortedAsc)]] " />
401+ </ th >
402+ </ template >
376403 < th class ="sortable-header ">
377404 < div class ="interop-header "> INTEROP</ div >
378405 < img class ="sort-icon " src ="[[getInteropSortIcon(sortColumn, isSortedAsc)]] " />
@@ -433,6 +460,9 @@ class InteropDashboard extends PolymerElement {
433460 < template is ="dom-repeat " items ="{{getYearProp('browserInfo')}} " as ="browserInfo ">
434461 < td > [[getBrowserScoreForFeature(itemsIndex, rowName, stable)]]</ td >
435462 </ template >
463+ < template is ="dom-if " if ="[[isMobileScoresView]] ">
464+ < td > --%</ td >
465+ </ template >
436466 < td > [[getInteropScoreForFeature(rowName, stable)]]</ td >
437467 </ tr >
438468 </ template >
@@ -443,6 +473,9 @@ class InteropDashboard extends PolymerElement {
443473 < template is ="dom-repeat " items ="{{getYearProp('browserInfo')}} " as ="browserInfo ">
444474 < td > [[getSubtotalScore(itemsIndex, section, stable)]]</ td >
445475 </ template >
476+ < template is ="dom-if " if ="[[isMobileScoresView]] ">
477+ < td > --%</ td >
478+ </ template >
446479 < td > [[getInteropSubtotalScore(section, stable)]]</ td >
447480 </ tr >
448481 </ tfoot >
@@ -510,7 +543,7 @@ class InteropDashboard extends PolymerElement {
510543 </ div >
511544 </ div >
512545 < footer class ="compat-footer ">
513- < div class ="interop-years ">
546+ < div class ="text-center ">
514547 < div class ="interop-year-text ">
515548 < p > View by year: </ p >
516549 </ div >
@@ -543,11 +576,16 @@ class InteropDashboard extends PolymerElement {
543576 type : Number ,
544577 value : 0
545578 } ,
579+ dashboardTitle : String ,
546580 currentInteropYear : Number ,
547581 isCurrentYear : {
548582 type : Boolean ,
549583 value : true ,
550584 } ,
585+ isMobileScoresView : {
586+ type : Boolean ,
587+ value : false ,
588+ } ,
551589 isSortedAsc : {
552590 type : Boolean ,
553591 value : true
@@ -569,7 +607,7 @@ class InteropDashboard extends PolymerElement {
569607
570608 static get observers ( ) {
571609 return [
572- 'updateUrlParams(embedded, stable, feature)' ,
610+ 'updateUrlParams(embedded, stable, feature, isMobileScoresView )' ,
573611 'updateTotals(features, stable)'
574612 ] ;
575613 }
@@ -578,7 +616,16 @@ class InteropDashboard extends PolymerElement {
578616 const params = ( new URL ( document . location ) ) . searchParams ;
579617
580618 this . stable = params . get ( 'stable' ) !== null ;
581- this . dataManager = new InteropDataManager ( this . year ) ;
619+ this . isMobileScoresView = params . get ( 'mobile-view' ) !== null && this . showMobileScoresView ;
620+ this . dataManager = new InteropDataManager ( this . year , this . isMobileScoresView ) ;
621+
622+ if ( this . isMobileScoresView ) {
623+ this . dashboardTitle = `Interop ${ this . year } Mobile Dashboard` ;
624+ // No stable view for mobile results.
625+ this . stable = false ;
626+ } else {
627+ this . dashboardTitle = `Interop ${ this . year } Dashboard` ;
628+ }
582629
583630 this . scores = { } ;
584631 this . scores . experimental = await this . dataManager . getMostRecentScores ( false ) ;
@@ -610,7 +657,7 @@ class InteropDashboard extends PolymerElement {
610657 this . $ . toggleStable . setAttribute ( 'aria-pressed' , this . stable ) ;
611658 this . $ . toggleExperimental . setAttribute ( 'aria-pressed' , ! this . stable ) ;
612659 // Keep the block-level design for interop 2021-2022
613- if ( this . year === '2021' || this . year === '2022' ) {
660+ if ( this . year === '2021' || this . year === '2022' || this . isMobileScoresView ) {
614661 const gridContainerDiv = this . shadowRoot . querySelector ( '.grid-container' ) ;
615662 gridContainerDiv . style . display = 'block' ;
616663 gridContainerDiv . style . width = '700px' ;
@@ -663,7 +710,6 @@ class InteropDashboard extends PolymerElement {
663710 // - https://github.com/whatwg/url/issues/762
664711 // - https://github.com/whatwg/url/issues/461
665712 // - https://github.com/whatwg/url/issues/335
666-
667713 // Test results are defined as absolute paths from this origin.
668714 const url = new URL ( testsURL , window . location . origin ) ;
669715 // Test results URLs can have multiple 'label' params. Grab them all.
@@ -804,7 +850,7 @@ class InteropDashboard extends PolymerElement {
804850 this . totalSafari = this . getBrowserScoreForFeature ( 2 , summaryFeatureName ) ;
805851 }
806852
807- updateUrlParams ( embedded , stable , feature ) {
853+ updateUrlParams ( embedded , stable , feature , isMobileScoresView ) {
808854 // Our observer may be called before the feature is set, so debounce that.
809855 if ( feature === undefined ) {
810856 return ;
@@ -820,6 +866,9 @@ class InteropDashboard extends PolymerElement {
820866 if ( embedded ) {
821867 params . push ( 'embedded' ) ;
822868 }
869+ if ( isMobileScoresView ) {
870+ params . push ( 'mobile-view' ) ;
871+ }
823872
824873 let url = location . pathname ;
825874 if ( params . length ) {
@@ -828,30 +877,71 @@ class InteropDashboard extends PolymerElement {
828877 history . pushState ( '' , '' , url ) ;
829878 }
830879
831- experimentalButtonClass ( stable ) {
832- return stable ? 'unselected' : 'selected' ;
880+ experimentalButtonClass ( stable , isMobileScoresView ) {
881+ return ( isMobileScoresView || stable ) ? 'unselected' : 'selected' ;
833882 }
834883
835- stableButtonClass ( stable ) {
836- return stable ? 'selected' : 'unselected' ;
884+ stableButtonClass ( stable , isMobileScoresView ) {
885+ return ( stable && ! isMobileScoresView ) ? 'selected' : 'unselected' ;
886+ }
887+
888+ mobileButtonClass ( isMobileScoresView ) {
889+ return isMobileScoresView ? 'selected' : 'unselected' ;
837890 }
838891
839892 clickExperimental ( ) {
840- if ( ! this . stable ) {
893+ if ( ! this . stable && ! this . isMobileScoresView ) {
841894 return ;
842895 }
843- this . stable = false ;
844- this . $ . toggleStable . setAttribute ( 'aria-pressed' , false ) ;
845- this . $ . toggleExperimental . setAttribute ( 'aria-pressed' , true ) ;
896+ if ( this . isMobileScoresView ) {
897+ this . toggleMobileView ( false , false ) ;
898+ } else {
899+ this . stable = false ;
900+ this . isMobileScoresView = false ;
901+ this . $ . toggleStable . setAttribute ( 'aria-pressed' , false ) ;
902+ this . $ . toggleExperimental . setAttribute ( 'aria-pressed' , true ) ;
903+ }
846904 }
847905
848906 clickStable ( ) {
849- if ( this . stable ) {
907+ if ( this . stable && ! this . isMobileScoresView ) {
850908 return ;
851909 }
852- this . stable = true ;
853- this . $ . toggleStable . setAttribute ( 'aria-pressed' , true ) ;
854- this . $ . toggleExperimental . setAttribute ( 'aria-pressed' , false ) ;
910+ if ( this . isMobileScoresView ) {
911+ this . toggleMobileView ( false , true ) ;
912+ } else {
913+ this . stable = true ;
914+ this . isMobileScoresView = false ;
915+ this . $ . toggleStable . setAttribute ( 'aria-pressed' , true ) ;
916+ this . $ . toggleExperimental . setAttribute ( 'aria-pressed' , false ) ;
917+ }
918+ }
919+
920+ clickMobile ( ) {
921+ if ( this . isMobileScoresView ) {
922+ return ;
923+ }
924+ this . toggleMobileView ( true , false ) ;
925+ }
926+
927+ toggleMobileView ( showMobileScores , stable ) {
928+ let queryString = '' ;
929+ if ( showMobileScores ) {
930+ queryString += 'mobile-view' ;
931+ }
932+ if ( stable ) {
933+ queryString += ( queryString . length ) ? '&stable' : 'stable' ;
934+ }
935+ if ( queryString . length ) {
936+ queryString = `?${ queryString } ` ;
937+ }
938+
939+ const url = `${ location . pathname } ${ queryString } ` ;
940+ window . location = url ;
941+ }
942+
943+ shouldShowMobileScoresView ( ) {
944+ return this . showMobileScoresView && parseInt ( this . year ) >= 2024 ;
855945 }
856946
857947 // Check if the table being rendered is the first table.
@@ -880,7 +970,8 @@ class InteropDashboard extends PolymerElement {
880970
881971 // Determine the icon that should be displayed on the interop column.
882972 getInteropSortIcon ( sortColumn , isSortedAsc ) {
883- const interopIndex = this . dataManager . getYearProp ( 'numBrowsers' ) + 1 ;
973+ const indexOffset = ( this . isMobileScoresView ) ? 2 : 1 ;
974+ const interopIndex = this . dataManager . getYearProp ( 'numBrowsers' ) + indexOffset ;
884975 if ( interopIndex !== sortColumn ) {
885976 return '/static/expand_inactive.svg' ;
886977 }
@@ -916,7 +1007,7 @@ class InteropDashboard extends PolymerElement {
9161007 } ;
9171008
9181009 numericalSort = ( rows , featureOrder , sortColumn ) => {
919- const browserIndex = sortColumn - 1 ;
1010+ const browserIndex = ( this . isMobileScoresView && sortColumn === 4 ) ? 2 : sortColumn - 1 ;
9201011 const individualScores = [ ] ;
9211012 for ( let i = 0 ; i < rows . length ; i ++ ) {
9221013 const feature = rows [ i ] ;
@@ -932,6 +1023,10 @@ class InteropDashboard extends PolymerElement {
9321023 if ( index !== 0 ) {
9331024 return rows ;
9341025 }
1026+ // Safari column will not have data for mobile and cannot be sorted.
1027+ if ( this . isMobileScoresView && sortColumn === 3 ) {
1028+ return rows ;
1029+ }
9351030 const sortedFeatureOrder = [ ] ;
9361031 // For the first column, sort alphabetically by name
9371032 if ( sortColumn === 0 ) {
0 commit comments