Skip to content

Commit aa11f43

Browse files
DanielRyanSmithDanielRyanSmith
andauthored
Add experimental interop mobile results view (#3959)
* add mobile results view for 2024 * lint * handle mobile view redirects * interop JSON data matches * Add text about mobile scores being WIP * Put mobile results view behind a flag * handle stable click properly * Add Safari iOS as a placeholder * lint * changes suggested by @KyleJu --------- Co-authored-by: DanielRyanSmith <[email protected]>
1 parent b1f1372 commit aa11f43

File tree

8 files changed

+380
-56
lines changed

8 files changed

+380
-56
lines changed

webapp/components/interop-dashboard.js

Lines changed: 124 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
import { InteropDataManager } from './interop-data-manager.js';
8+
import { WPTFlags } from './wpt-flags.js';
89
import '../node_modules/@polymer/paper-button/paper-button.js';
910
import '../node_modules/@polymer/polymer/lib/elements/dom-if.js';
1011
import '../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

Comments
 (0)