INP
- {{latest.pct_good_inp}}%
+ {{ latest.pct_good_inp }}%
{% for entry in tech_data %}
- {% if entry.client == "mobile" %}
+ {% if entry.client == "desktop" %}
{{ entry.pct_good_inp }}
diff --git a/templates/techreport/components/timeseries_container.html b/templates/techreport/components/timeseries_container.html
index ff1d57e9..2c4ad194 100644
--- a/templates/techreport/components/timeseries_container.html
+++ b/templates/techreport/components/timeseries_container.html
@@ -8,7 +8,9 @@ {{ timeseries_title }}
Date
Client
- % Good scores
+ {% for metric in timeseries_metrics %}
+ {{ metric.title }}
+ {% endfor %}
@@ -16,7 +18,9 @@ {{ timeseries_title }}
{{ entry.date }}
{{ entry.client }}
- {{ entry[timeseries_metric] }}
+ {% for metric in timeseries_metrics %}
+ {{ entry[metric.key] }}{% if metric.suffix %}{{ metric.suffix }}{% endif %}
+ {% endfor %}
{% endfor %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index eddc3614..81ffcfff 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -40,7 +40,19 @@ {{ tech_report_labels.cwv.title }}
{% set timeseries_title = tech_report_labels.cwv.good.timeseries_title %}
{% set timeseries_description = tech_report_labels.cwv.good.section_description %}
- {% set timeseries_metric = "pct_good_cwv" %}
+ {% set timeseries_metrics = [
+ {
+ "key": "pct_good_cwv",
+ "title": "% Good CWVs",
+ "suffic": "%"
+ }, {
+ "key": "origins_with_good_cwv",
+ "title": "# Good CWVs"
+ }, {
+ "key": "origins_eligible_for_cwv",
+ "title": "Eligible"
+ }
+ ] %}
{% set client = "mobile" %}
{% include "techreport/components/cwv_overview.html" %}
@@ -56,11 +68,15 @@ {{ tech_report_labels.adoption.title }}
{% set timeseries_title = tech_report_labels.adoption.timeseries_title %}
{% set timeseries_description = tech_report_labels.adoption.timeseries_description %}
- {% set timeseries_metric = "origins" %}
+ {% set timeseries_metrics = [
+ {
+ "key": "origins",
+ "title": "Origins"
+ }
+ ] %}
{% set client = "mobile" %}
{% include "techreport/components/timeseries_container.html" %}
-
{% else %}
From 43e464b204c7ccb624d7f93a490507cc815884dd Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 29 Jun 2023 15:11:35 +0200
Subject: [PATCH 036/155] add table on overview
---
templates/techreport/components/table_overview.html | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/templates/techreport/components/table_overview.html b/templates/techreport/components/table_overview.html
index 0f99b5e5..f486e2b4 100644
--- a/templates/techreport/components/table_overview.html
+++ b/templates/techreport/components/table_overview.html
@@ -12,10 +12,11 @@ {{ table.title }}
Technology
Origins
- Good CWVs
+ % Good CWVs
LCP
CLS
FID
+ INP
@@ -25,10 +26,11 @@ {{ table.title }}
{{ data[technology][0].app }}
{{ latest.origins }}
- {{ latest.origins_with_good_cwv }}
- {{ latest.origins_with_good_lcp }} s
- {{ latest.origins_with_good_cls }}
- {{ latest.origins_with_good_fid }} ms
+ {{ latest.pct_good_cwv }}
+ {{ latest.pct_good_lcp }} %
+ {{ latest.pct_good_cls }} %
+ {{ latest.pct_good_fid }} %
+ {{ latest.pct_good_inp }} %
{% endfor %}
From d29dbcaaa81191e6cb91dedeed0c4c1b7c79ff13 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 8 Jul 2023 04:20:04 +0200
Subject: [PATCH 037/155] render data with js
---
server/routes.py | 32 +----
src/js/components/drilldownHeader.js | 50 +++++++
src/js/components/summaryLinked.js | 53 ++++++++
src/js/components/tableOverview.js | 75 ++++++++++
src/js/techreport.js | 49 +++++++
src/js/utils.js | 5 +
static/components/header.css | 50 +++++++
static/components/summary.css | 21 +++
static/css/techreport/general.css | 65 +++++++++
static/css/techreport/techreport.css | 128 ------------------
templates/techreport/comparison.html | 31 -----
templates/techreport/drilldown.html | 116 ++++++----------
templates/techreport/landing.html | 24 ----
templates/techreport/techreport.html | 25 +++-
.../templates/drilldown_header.html | 24 ++++
.../techreport/templates/summary_linked.html | 16 +++
.../techreport/templates/table_overview.html | 33 +++++
webpack.config.js | 4 +
18 files changed, 514 insertions(+), 287 deletions(-)
create mode 100644 src/js/components/drilldownHeader.js
create mode 100644 src/js/components/summaryLinked.js
create mode 100644 src/js/components/tableOverview.js
create mode 100644 src/js/techreport.js
create mode 100644 static/components/header.css
create mode 100644 static/components/summary.css
create mode 100644 static/css/techreport/general.css
create mode 100644 templates/techreport/templates/drilldown_header.html
create mode 100644 templates/techreport/templates/summary_linked.html
create mode 100644 templates/techreport/templates/table_overview.html
diff --git a/server/routes.py b/server/routes.py
index ce8c311f..0b69ab2b 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -75,49 +75,31 @@ def techreport(page_id):
# Get the configuration for the tech report
tech_report = tech_report_util.get_report()
- # Get the technologies, geos, ranks on which we have data
- available_technologies = tech_report_util.get_technologies()
- available_geos = tech_report_util.get_geos()
- available_ranks = tech_report_util.get_ranks()
-
# Get the settings for the current page
active_tech_report = tech_report.get("pages").get(page_id)
# Combine technologies from the URL with the pre-defined ones from the config
# Because sometimes we want 'ALL' in addition to chosen tech
- requested_technologies = tech_report_util.get_requested_technologies(
- request, available_technologies
- )
- defined_technologies = active_tech_report.get("filters").get("technologies")
- technologies_all = [*defined_technologies, *requested_technologies]
+ requested_technologies = "ALL"
+ if request.args.get("tech"):
+ requested_technologies = request.args.get("tech").split(",")
+ if isinstance(requested_technologies, str):
+ requested_technologies = [requested_technologies]
# Get the filters
- requested_geo = tech_report_util.get_request_values(request, "geo", available_geos)
- requested_rank = tech_report_util.get_request_values(
- request, "rank", available_ranks
- )
+ requested_geo = request.args.get("geo") or "ALL"
+ requested_rank = request.args.get("rank") or "ALL"
filters = {
"geo": requested_geo,
"rank": requested_rank,
"app": requested_technologies,
}
- for technology in technologies_all:
- # For each of the technologies, get the data
- results = tech_report_util.get_metrics(technology, filters)
- active_tech_report["data"][technology] = results
-
- active_tech_report["tech"] = requested_technologies
- active_tech_report["tech_all"] = technologies_all
-
active_tech_report["set_filters"] = filters
return render_template(
"techreport/%s.html" % page_id,
active_page=page_id,
- available_technologies=available_technologies,
- available_geos=available_geos,
- available_ranks=available_ranks,
tech_report_labels=tech_report.get("labels"),
tech_report_page=active_tech_report,
reports=all_reports,
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
new file mode 100644
index 00000000..bc936cb4
--- /dev/null
+++ b/src/js/components/drilldownHeader.js
@@ -0,0 +1,50 @@
+class drilldownHeader extends HTMLElement {
+ constructor() {
+ super();
+ this.filters = {};
+ this.categories = [];
+
+ this.attachShadow({ mode: 'open' });
+ const template = document.getElementById('drilldown-header').content.cloneNode(true);
+ this.shadowRoot.appendChild(template);
+ }
+
+ connectedCallback() {
+ this.renderComponent();
+ }
+
+ static get observedAttributes() {
+ return ['loaded'];
+ }
+
+ attributeChangedCallback(property, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ this[ property ] = newValue;
+ console.log('will re-render', oldValue, newValue, 'for prop', property);
+ this.renderComponent();
+ }
+
+ setTitle() {
+ const title = this.filters.appString;
+ this.shadowRoot.querySelectorAll('h1 span.main-title')
+ .forEach( node => node.textContent = title );
+ }
+
+ setTags() {
+ const list = this.shadowRoot.querySelector('.category-list');
+
+ list.innerHTML = '';
+ this.categories.forEach((category) => {
+ const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
+ cellTemplate.querySelector('li.cell').textContent = category;
+ list.appendChild(cellTemplate);
+ });
+ }
+
+ renderComponent() {
+ this.setTitle();
+ this.setTags();
+ }
+}
+
+customElements.define('drilldown-header', drilldownHeader);
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
new file mode 100644
index 00000000..98829341
--- /dev/null
+++ b/src/js/components/summaryLinked.js
@@ -0,0 +1,53 @@
+class SummaryLinked extends HTMLElement {
+ constructor() {
+ super();
+
+ this.latest = {};
+
+ this.attachShadow({ mode: 'open' });
+ const template = document.getElementById('summary-linked').content.cloneNode(true);
+ this.shadowRoot.appendChild(template);
+ }
+
+ connectedCallback() {
+ this.renderComponent();
+ }
+
+ static get observedAttributes() {
+ return ['key', 'title', 'loaded'];
+ }
+
+ attributeChangedCallback(property, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ this[ property ] = newValue;
+ console.log('attributeChangedCallback of the summary', property, 'from', oldValue, 'to', newValue);
+ this.renderComponent();
+ }
+
+ setTitle() {
+ this.shadowRoot.querySelectorAll('.summary-linked-label a')
+ .forEach( (node) => {
+ node.textContent = this.title;
+ node.setAttribute('href', this.link);
+ } );
+ }
+
+ setData() {
+ this.shadowRoot.querySelectorAll('.summary-linked-value')
+ .forEach( (node) => {
+ node.textContent = this.latest[this.key];
+ } );
+
+ this.shadowRoot.querySelectorAll('.summary-linked-description')
+ .forEach( (node) => {
+ node.textContent = `For ${this.latest.client}.`;
+ } );
+ }
+
+ renderComponent() {
+ this.setTitle();
+ this.setData();
+ }
+}
+
+customElements.define('summary-linked', SummaryLinked);
diff --git a/src/js/components/tableOverview.js b/src/js/components/tableOverview.js
new file mode 100644
index 00000000..a8c1ebb8
--- /dev/null
+++ b/src/js/components/tableOverview.js
@@ -0,0 +1,75 @@
+import { getLatestEntry } from "../utils";
+
+class TableOverview extends HTMLElement {
+ constructor() {
+ super();
+
+ this.latest = {};
+ this.allData = [];
+ this.focus = 'mobile';
+
+ this.attachShadow({ mode: 'open' });
+ const template = document.getElementById('table-overview').content.cloneNode(true);
+ this.shadowRoot.appendChild(template);
+ }
+
+ connectedCallback() {
+ this.renderComponent();
+ }
+
+ static get observedAttributes() {
+ return ['loaded', 'focus'];
+ }
+
+ attributeChangedCallback(property, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ this[ property ] = newValue;
+ this.renderComponent();
+ }
+
+ setTitle() {
+
+ }
+
+ setData() {
+ const focusedData = this.allData.filter(entry => entry.client === this.focus);
+ const latestFocus = getLatestEntry(focusedData);
+
+ const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
+
+ const coreWebVitals = [
+ {
+ origins_with_good: "origins_with_good_cwv",
+ origins_eligible: "origins_eligible_for_cwv",
+ title: "Overall"
+ },
+ {
+ origins_with_good: "origins_with_good_fid",
+ origins_eligible: "origins_with_any_fid",
+ title: "FID"
+ }
+ ];
+
+ coreWebVitals.forEach((cwv) => {
+ const rowTemplate = document.getElementById('table-overview-row').content.cloneNode(true);
+
+ console.log(latestFocus, latestFocus[cwv.origins_with_good]);
+
+ rowTemplate.querySelector('tr th').textContent = cwv.title;
+ rowTemplate.querySelectorAll('tr td')[0].textContent = `${parseInt(latestFocus[cwv.origins_with_good] / latestFocus[cwv.origins_eligible] * 1000) / 100}%`;
+
+ focusedData.reverse().forEach((entry) => {
+ const barTemplate = document.getElementById('table-overview-bar').content.cloneNode(true);
+ rowTemplate.querySelectorAll('tr td')[1].append(barTemplate);
+ })
+ tableBody.append(rowTemplate);
+ });
+ }
+
+ renderComponent() {
+ this.setTitle();
+ this.setData();
+ }
+}
+
+customElements.define('table-overview', TableOverview);
diff --git a/src/js/techreport.js b/src/js/techreport.js
new file mode 100644
index 00000000..4b8920dc
--- /dev/null
+++ b/src/js/techreport.js
@@ -0,0 +1,49 @@
+class TechReport {
+ constructor(report) {
+ console.log('TechReport', report);
+ this.filters = report.set_filters;
+ this.allData = [];
+ this.getAllData();
+ }
+
+ getAllData() {
+ const data = [];
+ this.filters.app.forEach(async (technology) => {
+ const url = `https://cdn.httparchive.org/reports/cwvtech/${this.filters.rank}/${this.filters.geo}/${technology}.json`;
+ await fetch(url)
+ .then(result => result.json())
+ .then((result) => {
+ data.push(result);
+ this.updateComponents(data);
+ });
+ });;
+ }
+
+ updateComponents(data) {
+ const generalComponents = document.querySelectorAll('[data-scope="general-info"]');
+ generalComponents.forEach((component) => {
+ const app = this.filters.app.join(',');
+
+ component.categories = data[0][0]?.category?.split(",");
+ component.app = app;
+ component.filters = this.filters;
+ component.filters.appString = this.filters.app.join(',');
+
+ component.setAttribute('loaded', true);
+ });
+
+ const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
+ latestComponents.forEach((component) => {
+ component.latest = data[0][0];
+ component.setAttribute('loaded', true);
+ });
+
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = data[0];
+ component.setAttribute('loaded', true);
+ })
+ }
+}
+
+window.TechReport = TechReport;
diff --git a/src/js/utils.js b/src/js/utils.js
index cc7a2217..e4f81d5b 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -95,3 +95,8 @@ const getChangeSentiment = (change, options) => {
}
return 'neutral';
};
+
+export const getLatestEntry = (data) => {
+ const sorted = data.sort((a, b) => new Date(b.date) - new Date(a.date));
+ return sorted[0];
+};
diff --git a/static/components/header.css b/static/components/header.css
new file mode 100644
index 00000000..d91ca2c4
--- /dev/null
+++ b/static/components/header.css
@@ -0,0 +1,50 @@
+/* Page heading */
+.intro {
+ border: none;
+ margin-top: 0;
+ background-color: transparent;
+ padding: 4rem 0;
+ display: grid;
+ grid-template-columns: 1fr 20rem;
+ column-gap: 2rem;
+ row-gap: 2rem;
+}
+
+.intro h1 {
+ font-size: var(--font-size-xlarge);
+ margin-bottom: 2.5rem;
+ margin-top: 0;
+}
+
+.intro h1 span.subtitle {
+ font-size: 1.15rem;
+ display: block;
+ margin-bottom: 0.5rem;
+}
+
+.intro p {
+ font-size: 1.15rem;
+ max-width: 45rem;
+}
+
+.intro h1 + p {
+ padding: 0;
+}
+
+.intro ul {
+ padding-left: 0;
+ margin-left: 0;
+}
+
+/* Categories */
+.categories {
+ margin: 1rem 0;
+}
+
+.categories .cell {
+ display: inline-block;
+ padding: 0.25rem 0.75rem;
+ border-radius: 1rem;
+ border: 1px solid var(--color-text);
+ font-size: 0.875rem;
+}
diff --git a/static/components/summary.css b/static/components/summary.css
new file mode 100644
index 00000000..659e0b57
--- /dev/null
+++ b/static/components/summary.css
@@ -0,0 +1,21 @@
+
+.summary-linked-label {
+ font-weight: 600;
+}
+
+.summary-linked-label a {
+ color: var(--color-link);
+}
+
+.summary-linked-label a:is(:hover, :focus) {
+ color: var(--color-link);
+ text-decoration: none;
+}
+
+.summary-linked-value {
+ font-size: var(--font-size-medium);
+}
+
+.summary-linked-description {
+ margin-bottom: 0;
+}
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
new file mode 100644
index 00000000..a17be5c2
--- /dev/null
+++ b/static/css/techreport/general.css
@@ -0,0 +1,65 @@
+/* General */
+* {
+ padding: 0;
+ margin: 0;
+}
+main {
+ color: var(--color-text);
+}
+
+h1 {
+ font-size: var(--font-size-xlarge);
+ font-weight: 500;
+}
+
+h2 {
+ font-size: var(--font-size-large);
+}
+
+:is(a, button, select):focus {
+ outline: 1.5px solid var(--color-teal-dark);
+ outline-offset: 1.5px;
+}
+
+.sr-only {
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+
+.card {
+ padding: 1.5rem;
+ background: var(--color-card-background);
+ border-radius: var(--card-radius);
+ border: 1px solid var(--color-card-border);
+ box-shadow: var(--card-shadow);
+}
+
+.card > :is(h2, h3, h4) {
+ margin-top: 0;
+}
+
+.block-s {
+ width: 50rem;
+ max-width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.block-m {
+ width: 70rem;
+ max-width: 95%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.block-l {
+ width: 85rem;
+ max-width: 98%;
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 7d3471cf..8698b388 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -1,64 +1,3 @@
-/* General */
-main {
- color: var(--color-text);
-}
-
-h1 {
- font-size: var(--font-size-xlarge);
-}
-
-h2 {
- font-size: var(--font-size-large);
-}
-
-:is(a, button, select):focus {
- outline: 1.5px solid var(--color-teal-dark);
- outline-offset: 1.5px;
-}
-
-.sr-only {
- clip: rect(0 0 0 0);
- clip-path: inset(50%);
- height: 1px;
- overflow: hidden;
- position: absolute;
- white-space: nowrap;
- width: 1px;
-}
-
-.card {
- padding: 1.5rem;
- background: var(--color-card-background);
- border-radius: var(--card-radius);
- border: 1px solid var(--color-card-border);
- box-shadow: var(--card-shadow);
-}
-
-.card > :is(h2, h3, h4) {
- margin-top: 0;
-}
-
-.block-s {
- width: 50rem;
- max-width: 90%;
- margin-left: auto;
- margin-right: auto;
-}
-
-.block-m {
- width: 70rem;
- max-width: 95%;
- margin-left: auto;
- margin-right: auto;
-}
-
-.block-l {
- width: 85rem;
- max-width: 98%;
- margin-left: auto;
- margin-right: auto;
-}
-
/* Building blocks */
.cta-link {
background-color: var(--color-teal-dark);
@@ -178,38 +117,6 @@ h2 {
padding: 0.25rem 0.5rem;
}
-/* Page heading */
-.intro {
- border: none;
- margin-top: 0;
- background-color: transparent;
- padding: 4rem 0;
- display: grid;
- grid-template-columns: 1fr 20rem;
- column-gap: 2rem;
- row-gap: 2rem;
-}
-
-.intro h1 {
- font-size: var(--font-size-xlarge);
- margin-bottom: 2.5rem;
- margin-top: 0;
-}
-
-.intro h1 span {
- font-size: 1.15rem;
- display: block;
- margin-bottom: 0.5rem;
-}
-
-.intro p {
- font-size: 1.15rem;
- max-width: 45rem;
-}
-
-.intro h1 + p {
- padding: 0;
-}
/* Table */
.table-ui-wrapper {
@@ -313,28 +220,6 @@ h2 {
row-gap: 1rem;
}
-.summary-linked-label {
- font-weight: 600;
-}
-
-.summary-linked-label a {
- color: var(--color-link);
-}
-
-.summary-linked-label a:is(:hover, :focus) {
- color: var(--color-link);
- text-decoration: none;
-}
-
-.summary-linked-value {
- font-size: var(--font-size-medium);
- margin-top: -0.25rem;
-}
-
-.summary-linked-description {
- margin-top: -0.5rem;
- margin-bottom: 0;
-}
/* Timeseries cards */
.timeseries-container {
@@ -356,19 +241,6 @@ h2 {
margin: 0.75rem 0;
}
-/* Categories */
-.categories {
- margin: 1rem 0;
-}
-
-.categories .cell {
- display: inline-block;
- padding: 0.25rem 0.75rem;
- border-radius: 1rem;
- border: 1px solid var(--color-text);
- font-size: 0.875rem;
-}
-
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
@media screen and (max-height: 25rem) {
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index cf2216e1..1300ee82 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -3,35 +3,4 @@
{% block section %}
{{ super() }}
- {% set filtered_technology = tech_report_page.tech[0] or tech_report_page.tech_all[0] %}
-
- {% if filtered_technology and tech_report_page.data[filtered_technology] %}
- {% include "techreport/components/heading.html" %}
-
-
- {% set explore = tech_report_page.sections[0] %}
-
Summary
-
- {% set table = explore.labels.summary %}
- {% set technologies = tech_report_page.tech or tech_report_page.tech_all %}
- {% set data = tech_report_page.data %}
- {% include "techreport/components/table_overview.html" %}
-
-
-
-
-
{{ tech_report_labels.cwv.title }}
-
- {{ tech_report_labels.cwv.section_description }}
-
-
-
-
-
{{ tech_report_labels.adoption.title }}
-
- {{ tech_report_labels.adoption.section_description }}
-
-
-
- {% endif %}
{% endblock %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 81ffcfff..cc33e260 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -3,83 +3,45 @@
{% block section %}
{{ super() }}
- {% set filtered_technology = tech_report_page.tech[0] or tech_report_page.tech_all[0] %}
- {% set tech_report_section = tech_report_page.sections[0] %}
-
- {% if filtered_technology and tech_report_page.data[filtered_technology] %}
- {% include "techreport/components/heading.html" %}
-
-
-
Summary
-
-
- {% set summary = {
- "url": "#adoption",
- "label": tech_report_labels.adoption.title,
- "value": tech_report_page.data[filtered_technology][0].origins,
- "description": tech_report_labels.adoption.summary_description
- } %}
- {% include "techreport/components/summary_linked.html" %}
-
- {% set summary = {
- "url": "#cwv",
- "label": tech_report_labels.cwv.good.summary_title,
- "value": tech_report_page.data[filtered_technology][0].origins_with_good_cwv,
- "description": tech_report_labels.cwv.good.summary_description
- } %}
- {% include "techreport/components/summary_linked.html" %}
-
+
+
+
+
+
Summary
+
+
+
+
+
+
+
-
-
-
-
{{ tech_report_labels.cwv.title }}
-
- {{ tech_report_labels.cwv.section_description }}
-
-
- {% set timeseries_title = tech_report_labels.cwv.good.timeseries_title %}
- {% set timeseries_description = tech_report_labels.cwv.good.section_description %}
- {% set timeseries_metrics = [
- {
- "key": "pct_good_cwv",
- "title": "% Good CWVs",
- "suffic": "%"
- }, {
- "key": "origins_with_good_cwv",
- "title": "# Good CWVs"
- }, {
- "key": "origins_eligible_for_cwv",
- "title": "Eligible"
- }
- ] %}
- {% set client = "mobile" %}
-
- {% include "techreport/components/cwv_overview.html" %}
- {% include "techreport/components/timeseries_container.html" %}
-
-
-
-
-
{{ tech_report_labels.adoption.title }}
-
- {{ tech_report_labels.adoption.section_description }}
-
-
- {% set timeseries_title = tech_report_labels.adoption.timeseries_title %}
- {% set timeseries_description = tech_report_labels.adoption.timeseries_description %}
- {% set timeseries_metrics = [
- {
- "key": "origins",
- "title": "Origins"
- }
- ] %}
- {% set client = "mobile" %}
-
- {% include "techreport/components/timeseries_container.html" %}
-
+
+
+
+
Core Web Vitals
+
Description
+
- {% else %}
-
No data found
- {% endif %}
+
+
{% endblock %}
diff --git a/templates/techreport/landing.html b/templates/techreport/landing.html
index 7fc76e2b..b812170c 100644
--- a/templates/techreport/landing.html
+++ b/templates/techreport/landing.html
@@ -6,29 +6,5 @@
{% endblock %}
{% block section %}
- {% include "techreport/components/heading.html" %}
-
-
-
-
Get detailed information about one technology.
-
-
-
-
Get detailed information about two to ten technologies.
-
-
-
-
-
- {% set explore = tech_report_page.sections[0] %}
-
{{ explore.title }}
-
- {% set table = explore.blocks.popular_tech %}
- {% set data = tech_report_page.data %}
- {% set technologies = table["technologies"] %}
- {% include "techreport/components/table_overview.html" %}
-
-
-
{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 1b335e2e..b03880a7 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -5,8 +5,9 @@
{% block head %}
{{ super() }}
+
-{% endblock %}
+ {% endblock %}
{% block report_navigation %}
@@ -46,7 +47,27 @@
{% endblock %}
{% block main %}
-
{% block section %}{% endblock %}
+
+ {% include "techreport/templates/drilldown_header.html" %}
+ {% include "techreport/templates/summary_linked.html" %}
+ {% include "techreport/templates/table_overview.html" %}
+
+{% endblock %}
+
+
+{% block scripts %}
+ {{ super() }}
+
+
+
+
+
+
+
+
{% endblock %}
diff --git a/templates/techreport/templates/drilldown_header.html b/templates/techreport/templates/drilldown_header.html
new file mode 100644
index 00000000..c932fb8f
--- /dev/null
+++ b/templates/techreport/templates/drilldown_header.html
@@ -0,0 +1,24 @@
+
+
+
+ Category
+
diff --git a/templates/techreport/templates/summary_linked.html b/templates/techreport/templates/summary_linked.html
new file mode 100644
index 00000000..cb9f0e18
--- /dev/null
+++ b/templates/techreport/templates/summary_linked.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Label
+
+
+ Value
+
+
+ Description
+
+
+
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
new file mode 100644
index 00000000..3b9a79e1
--- /dev/null
+++ b/templates/techreport/templates/table_overview.html
@@ -0,0 +1,33 @@
+
+
+
Latest data
+
+
+ Latest % of websites with good core web vitals.
+
+
+
+ Core Web Vital
+ % Good scores
+ Trend
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webpack.config.js b/webpack.config.js
index f38a7907..4fe8b73d 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -7,9 +7,13 @@ module.exports = {
'index': './src/js/index.js',
'main': './src/js/main.js',
'report': './src/js/report.js',
+ 'techreport': './src/js/techreport.js',
'histogram': './src/js/histogram.js',
'timeseries': './src/js/timeseries.js',
'send-web-vitals': './src/js/send-web-vitals.js',
+ 'drilldownHeader': './src/js/components/drilldownHeader.js',
+ 'summaryLinked': './src/js/components/summaryLinked.js',
+ 'tableOverview': './src/js/components/tableOverview.js',
},
output: {
path: path.resolve(__dirname, 'static/js'),
From 6e9e847be7d649c2854f89f2db36e3043743a4b4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 8 Jul 2023 23:02:00 +0200
Subject: [PATCH 038/155] readd table styling
---
src/js/components/tableOverview.js | 38 ++++++--
static/components/table.css | 92 +++++++++++++++++++
static/css/techreport/techreport.css | 83 -----------------
.../techreport/templates/table_overview.html | 38 ++++----
4 files changed, 141 insertions(+), 110 deletions(-)
create mode 100644 static/components/table.css
diff --git a/src/js/components/tableOverview.js b/src/js/components/tableOverview.js
index a8c1ebb8..c9ec435e 100644
--- a/src/js/components/tableOverview.js
+++ b/src/js/components/tableOverview.js
@@ -33,6 +33,9 @@ class TableOverview extends HTMLElement {
setData() {
const focusedData = this.allData.filter(entry => entry.client === this.focus);
+ const focusedDataSorted = [...focusedData].sort((a, b) => {
+ return new Date(a.date) - new Date(b.date);
+ });
const latestFocus = getLatestEntry(focusedData);
const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
@@ -41,26 +44,43 @@ class TableOverview extends HTMLElement {
{
origins_with_good: "origins_with_good_cwv",
origins_eligible: "origins_eligible_for_cwv",
- title: "Overall"
+ title: "Overall",
+ },
+ {
+ origins_with_good: "origins_with_good_lcp",
+ origins_eligible: "origins_with_any_lcp",
+ title: "Largest Contentful Paint",
},
{
origins_with_good: "origins_with_good_fid",
origins_eligible: "origins_with_any_fid",
- title: "FID"
- }
+ title: "First Input Delay",
+ },
+ {
+ origins_with_good: "origins_with_good_cls",
+ origins_eligible: "origins_with_any_cls",
+ title: "Cumulative Layout Shift",
+ },
+ {
+ origins_with_good: "origins_with_good_inp",
+ origins_eligible: "origins_with_any_inp",
+ title: "Interaction to Next Paint",
+ },
];
coreWebVitals.forEach((cwv) => {
const rowTemplate = document.getElementById('table-overview-row').content.cloneNode(true);
-
- console.log(latestFocus, latestFocus[cwv.origins_with_good]);
-
+ const latestPercentageGood = parseInt(latestFocus[cwv.origins_with_good] / latestFocus[cwv.origins_eligible] * 10000) / 100;
rowTemplate.querySelector('tr th').textContent = cwv.title;
- rowTemplate.querySelectorAll('tr td')[0].textContent = `${parseInt(latestFocus[cwv.origins_with_good] / latestFocus[cwv.origins_eligible] * 1000) / 100}%`;
+ rowTemplate.querySelectorAll('tr td')[0].textContent = `${latestPercentageGood}%`;
- focusedData.reverse().forEach((entry) => {
+ focusedDataSorted.forEach((entry) => {
const barTemplate = document.getElementById('table-overview-bar').content.cloneNode(true);
- rowTemplate.querySelectorAll('tr td')[1].append(barTemplate);
+ const percentageGood = parseInt(entry[cwv.origins_with_good] / latestFocus[cwv.origins_eligible] * 10000) / 100;
+ const date = entry.date;
+ barTemplate.querySelector('li.bar').style.setProperty('--height', `${percentageGood}%`);
+ barTemplate.querySelector('li.bar .sr-only').textContent = `${date}: ${percentageGood}%`;
+ rowTemplate.querySelector('tr td ul.table-bar-preview').append(barTemplate);
})
tableBody.append(rowTemplate);
});
diff --git a/static/components/table.css b/static/components/table.css
new file mode 100644
index 00000000..89ce81b2
--- /dev/null
+++ b/static/components/table.css
@@ -0,0 +1,92 @@
+
+.table-ui {
+ width: 100%;
+ margin: 1rem 0;
+ border-collapse: collapse;
+}
+
+.table-ui tr {
+ border-bottom: 1px solid var(--color-card-border);
+ width: 100%;
+}
+
+.table-ui tr:last-child {
+ border-bottom: none;
+}
+
+.table-ui thead {
+ font-size: 0.875rem;
+ border-bottom: 1px solid var(--color-text);
+}
+
+.table-ui thead th {
+ padding: 1rem 0;
+}
+
+.table-ui tbody :is(td, th) {
+ padding: 1rem 0;
+}
+
+.table-ui tbody tr {
+ border-bottom: 1px solid var(--color-card-border);
+}
+
+.table-ui tbody th {
+ font-weight: normal;
+}
+
+.table-ui :is(td, th) {
+ text-align: left;
+}
+
+.table-ui :is(td, th) strong {
+ margin-right: 0.1rem;
+ font-weight: 600;
+}
+
+.table-ui tr a {
+ color: var(--color-link);
+ text-decoration: underline;
+}
+
+.table-ui tr .row-link:is(:hover, :focus) {
+ text-decoration-thickness: 3px;
+}
+
+.table-ui tr:has(.row-link:hover) {
+ background-color: var(--table-row-hover);
+}
+
+.table-ui tr:has(.row-link:focus) {
+ background-color: var(--table-row-hover);
+ border: 1.5px solid var(--color-teal-dark);
+}
+
+.table-ui tr:has(.row-link:focus) :is(th, td) {
+ border-bottom: 1.5px solid var(--color-teal-dark);
+ border-top: 1.5px solid var(--color-teal-dark);
+}
+
+.table-ui tr:has(.row-link:focus) .row-link:focus {
+ /* So the outline only gets removed in browsers that support :has */
+ outline-style: dotted;
+}
+
+.table-ui td ul {
+ height: 30px;
+ display: flex;
+ align-items: flex-end;
+ column-gap: 1px;
+}
+
+.table-ui td ul li {
+ border: 1px solid var(--graph-color-primary-darker);
+ height: 100%;
+ background-image: linear-gradient(
+ transparent calc(100% - var(--height)),
+ var(--graph-color-primary) calc(100% - var(--height)) 100%
+ );
+ border-radius: 1px 1px 0 0;
+ flex: 1;
+ list-style-type: none;
+}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 8698b388..10b5d702 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -123,89 +123,6 @@
overflow-x: scroll;
}
-.table-ui {
- width: 100%;
- margin: 1rem 0;
-}
-
-.table-ui tr {
- border-bottom: 1px solid var(--color-card-border);
- width: 100%;
-}
-
-.table-ui tr:last-child {
- border-bottom: none;
-}
-
-.table-ui thead {
- font-size: 0.875rem;
- border-bottom: 1px solid var(--color-text);
-}
-
-.table-ui thead th {
- padding: 1rem 0;
-}
-
-.table-ui tbody :is(td, th) {
- padding: 1rem 0;
- border-bottom: 1px solid var(--color-card-border);
-}
-
-.table-ui tbody th {
- font-weight: normal;
-}
-
-.table-ui :is(td, th) strong {
- margin-right: 0.1rem;
- font-weight: 600;
-}
-
-.table-ui tr a {
- color: var(--color-link);
- text-decoration: underline;
-}
-
-.table-ui tr .row-link:is(:hover, :focus) {
- text-decoration-thickness: 3px;
-}
-
-.table-ui tr:has(.row-link:hover) {
- background-color: var(--table-row-hover);
-}
-
-.table-ui tr:has(.row-link:focus) {
- background-color: var(--table-row-hover);
- border: 1.5px solid var(--color-teal-dark);
-}
-
-.table-ui tr:has(.row-link:focus) :is(th, td) {
- border-bottom: 1.5px solid var(--color-teal-dark);
- border-top: 1.5px solid var(--color-teal-dark);
-}
-
-.table-ui tr:has(.row-link:focus) .row-link:focus {
- /* So the outline only gets removed in browsers that support :has */
- outline-style: dotted;
-}
-
-.table-ui td ul {
- height: 30px;
- display: flex;
- align-items: flex-end;
- column-gap: 1px;
-}
-
-.table-ui td ul li {
- border: 1px solid var(--graph-color-primary-darker);
- height: 100%;
- background-image: linear-gradient(
- transparent calc(100% - var(--height)),
- var(--graph-color-primary) calc(100% - var(--height)) 100%
- );
- border-radius: 1px 1px 0 0;
- flex: 1;
-}
-
.footnote {
margin-bottom: 2rem;
font-style: italic;
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
index 3b9a79e1..d1412122 100644
--- a/templates/techreport/templates/table_overview.html
+++ b/templates/techreport/templates/table_overview.html
@@ -1,28 +1,30 @@
-
-
Latest data
-
-
- Latest % of websites with good core web vitals.
-
-
-
- Core Web Vital
- % Good scores
- Trend
-
-
-
-
-
-
+
+
+
+
+
+ Latest % of websites with good core web vitals.
+
+
+
+ Core Web Vital
+ % Good scores
+ Trend
+
+
+
+
+
-
+
+
+
From 3370006c30866a677889c7bd5a67194da7ac2f95 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 9 Jul 2023 03:34:08 +0200
Subject: [PATCH 039/155] clean up code
---
src/js/components/drilldownHeader.js | 102 +++++++++-----
src/js/components/summaryLinked.js | 5 +-
src/js/techreport.js | 15 +-
static/components/header.css | 50 -------
static/css/techreport/report.css | 41 ------
static/css/techreport/techreport.css | 128 ++++++++++++++++++
static/css/techreport/variables.css | 31 -----
templates/techreport/drilldown.html | 21 ++-
templates/techreport/report.html | 1 -
templates/techreport/techreport.html | 8 +-
.../templates/drilldown_header.html | 21 ---
webpack.config.js | 1 -
12 files changed, 221 insertions(+), 203 deletions(-)
delete mode 100644 static/css/techreport/report.css
delete mode 100644 static/css/techreport/variables.css
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index bc936cb4..7c250a4e 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -1,50 +1,82 @@
-class drilldownHeader extends HTMLElement {
- constructor() {
- super();
- this.filters = {};
- this.categories = [];
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('drilldown-header').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
+// class drilldownHeader extends HTMLElement {
+// constructor() {
+// super();
+// this.filters = {};
+// this.categories = [];
- connectedCallback() {
- this.renderComponent();
- }
+// this.attachShadow({ mode: 'open' });
+// const template = document.getElementById('drilldown-header').content.cloneNode(true);
+// this.shadowRoot.appendChild(template);
+// }
- static get observedAttributes() {
- return ['loaded'];
- }
+// connectedCallback() {
+// this.renderComponent();
+// }
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- console.log('will re-render', oldValue, newValue, 'for prop', property);
- this.renderComponent();
- }
+// static get observedAttributes() {
+// return ['loaded', 'title'];
+// }
- setTitle() {
- const title = this.filters.appString;
- this.shadowRoot.querySelectorAll('h1 span.main-title')
- .forEach( node => node.textContent = title );
- }
+// attributeChangedCallback(property, oldValue, newValue) {
+// if (oldValue === newValue) return;
+// this[ property ] = newValue;
+// console.log('will re-render', oldValue, newValue, 'for prop', property);
+// this.renderComponent();
+// }
+
+// setTitle() {
+// const title = this.title;
+// console.log(title);
+// this.shadowRoot.querySelectorAll('h1 span.main-title')
+// .forEach( node => node.textContent = title );
+// }
+
+// setTags() {
+// if(this.categories.length > 0) {
+// const list = this.shadowRoot.querySelector('.category-list');
+// list.innerHTML = '';
+// this.categories.forEach((category) => {
+// const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
+// cellTemplate.querySelector('li.cell').textContent = category;
+// list.appendChild(cellTemplate);
+// });
+// }
+// }
- setTags() {
- const list = this.shadowRoot.querySelector('.category-list');
+// renderComponent() {
+// this.setTitle();
+// this.setTags();
+// }
+// }
+// customElements.define('drilldown-header', drilldownHeader);
+
+function setTitle(title) {
+ const mainTitle = document.querySelector('h1 span.main-title');
+ mainTitle.textContent = title;
+}
+
+function setCategories(categories) {
+ console.log('set categories', categories);
+ if(categories.length > 0) {
+ const list = document.querySelector('.intro .category-list');
+ console.log('list', list);
list.innerHTML = '';
- this.categories.forEach((category) => {
+ categories.forEach((category) => {
const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
cellTemplate.querySelector('li.cell').textContent = category;
list.appendChild(cellTemplate);
});
}
+}
- renderComponent() {
- this.setTitle();
- this.setTags();
- }
+function update(data, filters) {
+ const app = filters.app.join(',');
+ setTitle(app);
+ console.log('update w data', data);
+ setCategories(data[0][0]?.category?.split(","));
}
-customElements.define('drilldown-header', drilldownHeader);
+export const DrilldownHeader = {
+ update,
+}
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
index 98829341..9bf95c77 100644
--- a/src/js/components/summaryLinked.js
+++ b/src/js/components/summaryLinked.js
@@ -3,6 +3,7 @@ class SummaryLinked extends HTMLElement {
super();
this.latest = {};
+ this.placeholder = '000';
this.attachShadow({ mode: 'open' });
const template = document.getElementById('summary-linked').content.cloneNode(true);
@@ -35,12 +36,12 @@ class SummaryLinked extends HTMLElement {
setData() {
this.shadowRoot.querySelectorAll('.summary-linked-value')
.forEach( (node) => {
- node.textContent = this.latest[this.key];
+ node.textContent = this.latest[this.key] || this.placeholder;
} );
this.shadowRoot.querySelectorAll('.summary-linked-description')
.forEach( (node) => {
- node.textContent = `For ${this.latest.client}.`;
+ node.textContent = this.latest.client ? `For ${this.latest.client}.` : this.placeholder;
} );
}
diff --git a/src/js/techreport.js b/src/js/techreport.js
index 4b8920dc..e6ef5c05 100644
--- a/src/js/techreport.js
+++ b/src/js/techreport.js
@@ -1,6 +1,7 @@
+const { DrilldownHeader } = require("./components/drilldownHeader");
+
class TechReport {
constructor(report) {
- console.log('TechReport', report);
this.filters = report.set_filters;
this.allData = [];
this.getAllData();
@@ -20,17 +21,7 @@ class TechReport {
}
updateComponents(data) {
- const generalComponents = document.querySelectorAll('[data-scope="general-info"]');
- generalComponents.forEach((component) => {
- const app = this.filters.app.join(',');
-
- component.categories = data[0][0]?.category?.split(",");
- component.app = app;
- component.filters = this.filters;
- component.filters.appString = this.filters.app.join(',');
-
- component.setAttribute('loaded', true);
- });
+ DrilldownHeader.update(data, this.filters)
const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
latestComponents.forEach((component) => {
diff --git a/static/components/header.css b/static/components/header.css
index d91ca2c4..e69de29b 100644
--- a/static/components/header.css
+++ b/static/components/header.css
@@ -1,50 +0,0 @@
-/* Page heading */
-.intro {
- border: none;
- margin-top: 0;
- background-color: transparent;
- padding: 4rem 0;
- display: grid;
- grid-template-columns: 1fr 20rem;
- column-gap: 2rem;
- row-gap: 2rem;
-}
-
-.intro h1 {
- font-size: var(--font-size-xlarge);
- margin-bottom: 2.5rem;
- margin-top: 0;
-}
-
-.intro h1 span.subtitle {
- font-size: 1.15rem;
- display: block;
- margin-bottom: 0.5rem;
-}
-
-.intro p {
- font-size: 1.15rem;
- max-width: 45rem;
-}
-
-.intro h1 + p {
- padding: 0;
-}
-
-.intro ul {
- padding-left: 0;
- margin-left: 0;
-}
-
-/* Categories */
-.categories {
- margin: 1rem 0;
-}
-
-.categories .cell {
- display: inline-block;
- padding: 0.25rem 0.75rem;
- border-radius: 1rem;
- border: 1px solid var(--color-text);
- font-size: 0.875rem;
-}
diff --git a/static/css/techreport/report.css b/static/css/techreport/report.css
deleted file mode 100644
index fdcb9ba2..00000000
--- a/static/css/techreport/report.css
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -------------------- */
-/* ----- Sections ----- */
-/* -------------------- */
-
-/* Summary */
-.summary {
- position: relative;
- z-index: 1;
-}
-
-.summary h2 {
- font-size: 1rem;
- font-weight: 600;
- margin-bottom: 1rem;
-}
-
-/* Main data */
-.page-data {
- margin-top: -4rem;
- padding: 8rem 0;
- border-top: 1px solid var(--color-teal-medium);
- background-image:
- linear-gradient(
- var(--color-teal-faded) 60%,
- var(--color-page-background)
- );
- background-size: 100% 25rem;
- background-repeat: no-repeat;
-}
-
-.page-data h2 {
- margin-bottom: 1rem;
-}
-
-.metric-block + .metric-block {
- margin-top: 6rem;
-}
-
-.block-description {
- max-width: 50rem;
-}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 10b5d702..3e6be4ea 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -1,3 +1,88 @@
+/* Variables */
+:root {
+ /* Main colors to use */
+ --color-teal-faded: #c0ced0;
+ --color-teal-medium: #6a797c;
+ --color-teal-dark: #3a5c63;
+ --color-teal-darker: #1c4750;
+ --color-blue-dark: #3a7098;
+ --color-blue-100: #eff7ff;
+
+ /* Colors based on function */
+ --color-link: var(--color-blue-dark);
+ --color-text: #444;
+ --color-text-inverted: #fff;
+ --color-card-background: #fff;
+ --color-card-border: #cdd4d6;
+ --color-page-background: #f4f4f4;
+
+ /* Font sizes */
+ --font-size-medium: 1.75rem;
+ --font-size-large: 2.15rem;
+ --font-size-xlarge: 2.35rem;
+
+ /* Components */
+ --card-shadow: 0 2px 7px 0px rgba(143, 149, 150, 0.05);
+ --card-radius: 0.25rem;
+ --table-row-hover: var(--color-blue-100);
+
+ /* Graph colors */
+ --graph-color-primary: var(--color-teal-dark);
+ --graph-color-primary-darker: var(--color-teal-darker);
+}
+
+/* Page heading */
+.intro {
+ border: none;
+ margin-top: 0;
+ background-color: transparent;
+ padding: 4rem 0;
+ display: grid;
+ grid-template-columns: 1fr 20rem;
+ column-gap: 2rem;
+ row-gap: 2rem;
+}
+
+.intro h1 {
+ font-size: var(--font-size-xlarge);
+ margin-bottom: 2.5rem;
+ margin-top: 0;
+}
+
+.intro h1 span.subtitle {
+ font-size: 1.15rem;
+ display: block;
+ margin-bottom: 0.5rem;
+}
+
+.intro p {
+ font-size: 1.15rem;
+ max-width: 45rem;
+}
+
+.intro h1 + p {
+ padding: 0;
+}
+
+.intro ul {
+ padding-left: 0;
+ margin-left: 0;
+}
+
+/* Categories */
+.categories {
+ margin: 1rem 0;
+}
+
+.categories .cell {
+ display: inline-block;
+ padding: 0.25rem 0.75rem;
+ border-radius: 1rem;
+ border: 1px solid var(--color-text);
+ font-size: 0.875rem;
+}
+
+
/* Building blocks */
.cta-link {
background-color: var(--color-teal-dark);
@@ -158,6 +243,49 @@
margin: 0.75rem 0;
}
+/* -------------------- */
+/* ----- Sections ----- */
+/* -------------------- */
+
+/* Summary */
+.summary {
+ position: relative;
+ z-index: 1;
+}
+
+.summary h2 {
+ font-size: 1rem;
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+/* Main data */
+.page-data {
+ margin-top: -4rem;
+ padding: 8rem 0;
+ border-top: 1px solid var(--color-teal-medium);
+ background-image:
+ linear-gradient(
+ var(--color-teal-faded) 60%,
+ var(--color-page-background)
+ );
+ background-size: 100% 25rem;
+ background-repeat: no-repeat;
+}
+
+.page-data h2 {
+ margin-bottom: 1rem;
+}
+
+.metric-block + .metric-block {
+ margin-top: 6rem;
+}
+
+.block-description {
+ max-width: 50rem;
+}
+
+
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
@media screen and (max-height: 25rem) {
diff --git a/static/css/techreport/variables.css b/static/css/techreport/variables.css
deleted file mode 100644
index 130efab8..00000000
--- a/static/css/techreport/variables.css
+++ /dev/null
@@ -1,31 +0,0 @@
-:root {
- /* Main colors to use */
- --color-teal-faded: #c0ced0;
- --color-teal-medium: #6a797c;
- --color-teal-dark: #3a5c63;
- --color-teal-darker: #1c4750;
- --color-blue-dark: #3a7098;
- --color-blue-100: #eff7ff;
-
- /* Colors based on function */
- --color-link: var(--color-blue-dark);
- --color-text: #444;
- --color-text-inverted: #fff;
- --color-card-background: #fff;
- --color-card-border: #cdd4d6;
- --color-page-background: #f4f4f4;
-
- /* Font sizes */
- --font-size-medium: 1.75rem;
- --font-size-large: 2.15rem;
- --font-size-xlarge: 2.35rem;
-
- /* Components */
- --card-shadow: 0 2px 7px 0px rgba(143, 149, 150, 0.05);
- --card-radius: 0.25rem;
- --table-row-hover: var(--color-blue-100);
-
- /* Graph colors */
- --graph-color-primary: var(--color-teal-dark);
- --graph-color-primary-darker: var(--color-teal-darker);
-}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index cc33e260..8846f71d 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -3,11 +3,22 @@
{% block section %}
{{ super() }}
-
-
+
+
+
+ Tech Report
+ Drilldown
+
+
+
+ Description not yet supported.
+
+
+
+
+
Summary
diff --git a/templates/techreport/report.html b/templates/techreport/report.html
index b1a838fe..d2f24c61 100644
--- a/templates/techreport/report.html
+++ b/templates/techreport/report.html
@@ -2,7 +2,6 @@
{% block head %}
{{ super() }}
-
{% endblock %}
{% block section %}{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index b03880a7..02d082b7 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -4,10 +4,11 @@
{% block head %}
{{ super() }}
-
+
+
- {% endblock %}
+{% endblock %}
{% block report_navigation %}
@@ -53,17 +54,16 @@
{% include "techreport/templates/drilldown_header.html" %}
{% include "techreport/templates/summary_linked.html" %}
{% include "techreport/templates/table_overview.html" %}
-
{% endblock %}
{% block scripts %}
{{ super() }}
-
+
-
+
{% endblock %}
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
new file mode 100644
index 00000000..baddfdd4
--- /dev/null
+++ b/templates/techreport/templates/table_general.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+ % of websites with good overall Core Web Vitals over time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webpack.config.js b/webpack.config.js
index fb8127a7..71c80937 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -12,6 +12,7 @@ module.exports = {
'timeseries': './src/js/timeseries.js',
'send-web-vitals': './src/js/send-web-vitals.js',
'summaryLinked': './src/js/components/summaryLinked.js',
+ 'tableGeneral': './src/js/components/tableGeneral.js',
'tableOverview': './src/js/components/tableOverview.js',
},
output: {
From fe29342bc65195a910627983635dc6c4d477c09e Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 23 Jul 2023 02:23:53 +0200
Subject: [PATCH 042/155] re-add tables and filters on landing and comparison
pages
---
config/techreport.json | 54 ++++------
server/routes.py | 7 +-
src/js/components/drilldownHeader.js | 4 +-
src/js/components/summaryLinked.js | 13 ++-
src/js/components/tableOverview.js | 37 +++----
src/js/components/tableOverviewMulti.js | 98 +++++++++++++++++++
src/js/techreport.js | 88 ++++++++++++++---
templates/techreport/comparison.html | 37 +++++++
templates/techreport/drilldown.html | 15 ++-
templates/techreport/landing.html | 27 +++++
templates/techreport/techreport.html | 9 +-
.../templates/table_overview_multitech.html | 24 +++++
webpack.config.js | 1 +
13 files changed, 341 insertions(+), 73 deletions(-)
create mode 100644 src/js/components/tableOverviewMulti.js
create mode 100644 templates/techreport/templates/table_overview_multitech.html
diff --git a/config/techreport.json b/config/techreport.json
index 47ce685f..0e992d6b 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -105,23 +105,22 @@
"filters": {
"technologies": ["WordPress", "Squarespace", "Drupal"]
},
- "sections": [
- {
- "id": "explore",
- "title": "Explore our data",
- "blocks": {
- "popular_tech": {
- "id": "popular_tech",
- "title": "Popular technologies",
- "description": "To write",
- "caption": "popular technologies table caption todo",
- "technologies": ["WordPress", "Squarespace", "Drupal"],
- "ctaLabel": "Compare technologies",
- "ctaUrl": "/reports/techreport/comparison?app=WordPress,Squarespace,Drupal"
- }
- }
+ "config": {
+ "default": {
+ "app": ["WordPress", "Squarespace", "Drupal"]
+ },
+ "popular_tech": {
+ "id": "popular_tech",
+ "title": "Popular technologies",
+ "description": "To write",
+ "caption": "popular technologies table caption todo",
+ "filters": {
+ "app": ["WordPress", "Squarespace", "Drupal"]
+ },
+ "ctaLabel": "Compare technologies",
+ "ctaUrl": "/reports/techreport/comparison?app=WordPress,Squarespace,Drupal"
}
- ]
+ }
},
"drilldown": {
"id": "drilldown",
@@ -162,25 +161,12 @@
"id": "comparison",
"title": "Comparison",
"subtitle": "Technology Report",
- "data": {},
- "description": "Comparison placeholder",
- "filters": {
- "technologies": ["ALL"]
- },
- "sections": [
- {
- "id": "all",
- "title": "All",
- "labels": {
- "summary": {
- "id": "comparing_summary",
- "title": "Comparing technologies",
- "description": "Placeholder: Comparing the following techs",
- "caption": "Placeholder: comparing technologies table caption todo"
- }
- }
+ "config": {
+ "default": {
+ "app": ["ALL", "WordPress", "Drupal"]
}
- ]
+ },
+ "description": "Comparison placeholder"
}
},
"graphic": {
diff --git a/server/routes.py b/server/routes.py
index d884a954..a1a99bae 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -81,6 +81,8 @@ def techreport(page_id):
# Combine technologies from the URL with the pre-defined ones from the config
# Because sometimes we want 'ALL' in addition to chosen tech
requested_technologies = "ALL"
+ default_technologies = active_tech_report.get("config").get("default").get("app")
+
if request.args.get("tech"):
requested_technologies = request.args.get("tech").split(",")
if isinstance(requested_technologies, str):
@@ -93,9 +95,12 @@ def techreport(page_id):
"geo": requested_geo,
"rank": requested_rank,
"app": requested_technologies,
+ "app_defaults": default_technologies,
}
- active_tech_report["set_filters"] = filters
+ active_tech_report["filters"] = filters
+
+ print('active_tech_report', active_tech_report)
return render_template(
"techreport/%s.html" % page_id,
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index 0a9e2239..c86141c9 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -16,9 +16,9 @@ function setCategories(categories) {
}
function update(data, filters) {
- const app = filters.app.join(',');
+ const app = filters.app[0];
setTitle(app);
- setCategories(data[0][0]?.category?.split(","));
+ setCategories(data[app][0]?.category?.split(","));
}
export const DrilldownHeader = {
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
index 3be147a2..1e0db27d 100644
--- a/src/js/components/summaryLinked.js
+++ b/src/js/components/summaryLinked.js
@@ -1,9 +1,13 @@
+import { getLatestEntry } from "../utils";
+
class SummaryLinked extends HTMLElement {
constructor() {
super();
this.latest = {};
+ this.allData = [];
this.placeholder = '000';
+ this.client = 'mobile';
this.attachShadow({ mode: 'open' });
const template = document.getElementById('summary-linked').content.cloneNode(true);
@@ -15,7 +19,7 @@ class SummaryLinked extends HTMLElement {
}
static get observedAttributes() {
- return ['key', 'title', 'loaded'];
+ return ['key', 'title', 'client', 'loaded'];
}
attributeChangedCallback(property, oldValue, newValue) {
@@ -35,16 +39,19 @@ class SummaryLinked extends HTMLElement {
setData() {
this.shadowRoot.querySelectorAll('.summary-linked-value')
.forEach( (node) => {
- node.textContent = this.latest[this.key] || this.placeholder;
+ node.textContent = this.latest?.[this.key] || this.placeholder;
} );
this.shadowRoot.querySelectorAll('.summary-linked-description')
.forEach( (node) => {
- node.textContent = this.latest.client ? `For ${this.latest.client}.` : this.placeholder;
+ node.textContent = this.latest?.client ? `For ${this.latest.client}.` : this.placeholder;
} );
}
renderComponent() {
+ const _filtered = this.allData?.filter(row => row.client === this.client);
+ const _latest = getLatestEntry(_filtered);
+ this.latest = _latest;
this.setTitle();
this.setData();
}
diff --git a/src/js/components/tableOverview.js b/src/js/components/tableOverview.js
index 76e63d59..b38ed23a 100644
--- a/src/js/components/tableOverview.js
+++ b/src/js/components/tableOverview.js
@@ -6,7 +6,6 @@ class TableOverview extends HTMLElement {
this.latest = {};
this.allData = [];
- this.focus = 'mobile';
this.attachShadow({ mode: 'open' });
const template = document.getElementById('table-overview').content.cloneNode(true);
@@ -18,7 +17,7 @@ class TableOverview extends HTMLElement {
}
static get observedAttributes() {
- return ['loaded', 'focus'];
+ return ['loaded', 'client'];
}
attributeChangedCallback(property, oldValue, newValue) {
@@ -32,13 +31,15 @@ class TableOverview extends HTMLElement {
}
setData() {
- const focusedData = this.allData.filter(entry => entry.client === this.focus);
+ const focusedData = this.allData.filter(entry => entry.client === this.client);
const focusedDataSorted = [...focusedData].sort((a, b) => {
return new Date(a.date) - new Date(b.date);
});
+
const latestFocus = getLatestEntry(focusedData);
const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
+ tableBody.innerHTML = '';
const coreWebVitals = [
{
@@ -69,20 +70,22 @@ class TableOverview extends HTMLElement {
];
coreWebVitals.forEach((cwv) => {
- const rowTemplate = document.getElementById('table-overview-row').content.cloneNode(true);
- const latestPercentageGood = parseInt(latestFocus[cwv?.origins_with_good] / latestFocus[cwv?.origins_eligible] * 10000) / 100;
- rowTemplate.querySelector('tr th').textContent = cwv.title;
- rowTemplate.querySelectorAll('tr td')[0].textContent = `${latestPercentageGood}%`;
-
- focusedDataSorted.forEach((entry) => {
- const barTemplate = document.getElementById('table-overview-bar').content.cloneNode(true);
- const percentageGood = parseInt(entry[cwv?.origins_with_good] / latestFocus[cwv?.origins_eligible] * 10000) / 100;
- const date = entry.date;
- barTemplate.querySelector('li.bar').style.setProperty('--height', `${percentageGood}%`);
- barTemplate.querySelector('li.bar .sr-only').textContent = `${date}: ${percentageGood}%`;
- rowTemplate.querySelector('tr td ul.table-bar-preview').append(barTemplate);
- })
- tableBody.append(rowTemplate);
+ if(cwv && latestFocus?.[cwv?.origins_with_good] && latestFocus[cwv?.origins_eligible]) {
+ const rowTemplate = document.getElementById('table-overview-row').content.cloneNode(true);
+ const latestPercentageGood = parseInt(latestFocus[cwv?.origins_with_good] / latestFocus[cwv?.origins_eligible] * 10000) / 100;
+ rowTemplate.querySelector('tr th').textContent = cwv.title;
+ rowTemplate.querySelectorAll('tr td')[0].textContent = `${latestPercentageGood}%`;
+
+ focusedDataSorted.forEach((entry) => {
+ const barTemplate = document.getElementById('table-overview-bar').content.cloneNode(true);
+ const percentageGood = parseInt(entry[cwv?.origins_with_good] / entry[cwv?.origins_eligible] * 10000) / 100;
+ const date = entry.date;
+ barTemplate.querySelector('li.bar').style.setProperty('--height', `${percentageGood}%`);
+ barTemplate.querySelector('li.bar .sr-only').textContent = `${date}: ${percentageGood}%`;
+ rowTemplate.querySelector('tr td ul.table-bar-preview').append(barTemplate);
+ })
+ tableBody.append(rowTemplate);
+ }
});
}
diff --git a/src/js/components/tableOverviewMulti.js b/src/js/components/tableOverviewMulti.js
new file mode 100644
index 00000000..28ce4474
--- /dev/null
+++ b/src/js/components/tableOverviewMulti.js
@@ -0,0 +1,98 @@
+import { getLatestEntry } from "../utils";
+
+class TableOverviewMulti extends HTMLElement {
+ constructor() {
+ super();
+
+ this.allData = [];
+ this.latest = [];
+ this.technologies = '';
+
+ this.attachShadow({ mode: 'open' });
+ const template = document.getElementById('table-overview-multitech').content.cloneNode(true);
+ this.shadowRoot.appendChild(template);
+ }
+
+ connectedCallback() {
+ this.renderComponent();
+ }
+
+ static get observedAttributes() {
+ return ['loaded', 'client', 'all_data', 'technologies'];
+ }
+
+ attributeChangedCallback(property, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ this[ property ] = newValue;
+ this.renderComponent();
+ }
+
+ setData() {
+ const technologies = this.technologies?.split(",");
+ const latestData = [];
+ const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
+ tableBody.innerHTML = '';
+
+ const coreWebVitals = [
+ {
+ origins_with_good: "origins_with_good_cwv",
+ origins_eligible: "origins_eligible_for_cwv",
+ },
+ {
+ origins_with_good: "origins_with_good_lcp",
+ origins_eligible: "origins_with_any_lcp",
+ },
+ {
+ origins_with_good: "origins_with_good_cls",
+ origins_eligible: "origins_with_any_cls",
+ },
+ {
+ origins_with_good: "origins_with_good_fid",
+ origins_eligible: "origins_with_any_fid",
+ },
+ {
+ origins_with_good: "origins_with_good_inp",
+ origins_eligible: "origins_with_any_inp",
+ },
+ ];
+
+ technologies.forEach(technology => {
+ const _data = this.allData?.[technology];
+
+ if(_data) {
+ const _clientData = _data?.filter(entry => entry.client === this.client);
+ const _clientDataSorted = [..._clientData]?.sort((a, b) => {
+ return new Date(a.date) - new Date(b.date);
+ });
+
+ const _latest = getLatestEntry(_clientDataSorted);
+
+ const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true);
+ const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
+
+ headingCellTemplate.querySelector('th').textContent = technology;
+ rowTemplate.querySelector('tr').append(headingCellTemplate);
+
+ const origins = document.getElementById('table-general-cell').content.cloneNode(true);
+ origins.querySelector('td').textContent = _latest.origins;
+ rowTemplate.querySelector('tr').append(origins);
+
+ coreWebVitals.forEach(cwv => {
+ const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
+ const percentageGood = parseInt(_latest[cwv?.origins_with_good] / _latest[cwv?.origins_eligible] * 10000) / 100;
+ dataCellTemplate.querySelector('td').textContent = `${percentageGood}%`;
+ rowTemplate.querySelector('tr').append(dataCellTemplate);
+ })
+
+ tableBody.append(rowTemplate);
+ }
+ });
+
+ }
+
+ renderComponent() {
+ this.setData();
+ }
+}
+
+customElements.define('table-overview-multitech', TableOverviewMulti);
diff --git a/src/js/techreport.js b/src/js/techreport.js
index d891b18f..4206c737 100644
--- a/src/js/techreport.js
+++ b/src/js/techreport.js
@@ -3,14 +3,31 @@ const { Filters } = require("./components/filters");
const { getPercentage } = require("./utils");
class TechReport {
- constructor(report, config, labels) {
- this.filters = report.set_filters;
+ constructor(pageId, page, config, labels) {
+ this.filters = page.filters;
this.allData = [];
+ this.page = page;
this.config = config;
this.labels = labels;
+ this.pageId = pageId;
+
+ this.bindClientListener();
this.getAllData();
}
+ bindClientListener() {
+ const select = document.getElementById('client-breakdown');
+ if(select) {
+ select.onchange = (event) => {
+ const client = event.target.value;
+ const allDataComponents = document.querySelectorAll('[data-scope]');
+ allDataComponents.forEach(component => {
+ component.setAttribute('client', client);
+ });
+ }
+ }
+ }
+
processData(result) {
return result.map(entry => {
entry.pct_good_cwv = getPercentage(entry.origins_with_good_cwv, entry.origins_eligible_for_cwv);
@@ -27,18 +44,22 @@ class TechReport {
}
getAllData() {
- const data = [];
- this.filters.app.forEach(technology => {
+ const data = {};
+ const fetch_app = this.filters.app.concat(this.filters.app_defaults);
+ Promise.all(fetch_app.map(technology => {
const url = `https://cdn.httparchive.org/reports/cwvtech/${this.filters.rank}/${this.filters.geo}/${technology}.json`;
- fetch(url)
+ return fetch(url)
.then(result => result.json())
.then(result => this.processData(result))
.then(result => {
- data.push(result);
- this.updateComponents(data);
+ data[technology] = result;
});
+ })).then(() => {
+ this.updateComponents(data);
});
+ }
+ getFilterInfo() {
fetch('https://cdn.httparchive.org/reports/cwvtech/technologies.json')
.then(result => result.json())
.then(result => Filters.updateTechnologies(result, this.filters));
@@ -50,25 +71,68 @@ class TechReport {
fetch('https://cdn.httparchive.org/reports/cwvtech/ranks.json')
.then(result => result.json())
.then(result => Filters.updateRank(result, this.filters));
-
}
updateComponents(data) {
- DrilldownHeader.update(data, this.filters)
+ switch(this.pageId) {
+ case 'landing':
+ this.updateLandingComponents(data);
+ break;
+
+ case 'drilldown':
+ this.updateDrilldownComponents(data);
+ this.getFilterInfo();
+ break;
+
+ case 'comparison':
+ this.updateComparisonComponents(data);
+ this.getFilterInfo();
+ break;
+ }
+ }
+
+ updateLandingComponents(data) {
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = data;
+ component.page = this.page;
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ component.setAttribute('all_data', JSON.stringify(data));
+ });
+ }
+
+ updateDrilldownComponents(data) {
+ DrilldownHeader.update(data, this.filters);
+
+ const app = this.filters.app[0];
const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
latestComponents.forEach((component) => {
- component.latest = data[0][0];
+ component.latest = data[app][0];
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ });
+
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = data[app];
component.labels = this.labels;
component.setAttribute('loaded', true);
});
+ }
+
+ updateComparisonComponents(data) {
const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+
allDataComponents.forEach((component) => {
- component.allData = data[0];
+ component.allData = data;
+ component.page = this.page;
component.labels = this.labels;
component.setAttribute('loaded', true);
- })
+ component.setAttribute('all_data', JSON.stringify(data));
+ });
}
}
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 1300ee82..5ad39a36 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -3,4 +3,41 @@
{% block section %}
{{ super() }}
+
+
+
+ Tech Report
+ Comparison
+
+
+
+ Description not yet supported.
+
+
+
+ {% include "techreport/templates/filters.html" %}
+
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
+
+
+
Popular CMSes
+
Description
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% set technologies_str = ','.join(technologies) %}
+
+
+
+
+
{% endblock %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index c9a0a037..36b06dbb 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -23,6 +23,13 @@
+
Client
+
+
+ Mobile
+ Desktop
+
+
Summary
@@ -31,7 +38,8 @@ Summary
title="Adoption"
link="#adoption"
key="origins"
- data-scope="all-latest"
+ data-scope="all-data"
+ client="mobile"
>
@@ -39,7 +47,8 @@ Summary
title="Good CWVs"
link="#good-cwvs"
key="origins_with_good_cwv"
- data-scope="all-latest"
+ data-scope="all-data"
+ client="mobile"
>
@@ -53,7 +62,7 @@
Latest data
Explanation
diff --git a/templates/techreport/landing.html b/templates/techreport/landing.html
index b812170c..b56a5ec7 100644
--- a/templates/techreport/landing.html
+++ b/templates/techreport/landing.html
@@ -6,5 +6,32 @@
{% endblock %}
{% block section %}
+
+
+
+
Get detailed information about one technology.
+
+
+
+
Get detailed information about two to ten technologies.
+
+
+
+
Explore
+
Placeholder
+
+
+
Popular CMSes
+
Description
+
+
+
+
+
+
{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 3e6f9e73..2bd7cf2a 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -48,6 +48,10 @@
{% endblock %}
{% block main %}
+
+
Beta
+
Changes are still being made to this page.
+
{% block section %}{% endblock %}
@@ -55,6 +59,8 @@
{% include "techreport/templates/summary_linked.html" %}
{% include "techreport/templates/table_general.html" %}
{% include "techreport/templates/table_overview.html" %}
+ {% include "techreport/templates/table_overview_multitech.html" %}
+
{% endblock %}
@@ -63,6 +69,7 @@
+
@@ -72,6 +79,6 @@
const config = {{ tech_report_config|tojson }};
const labels = {{ tech_report_labels|tojson }};
- const techReport = new TechReport(reportPage, config, labels);
+ const techReport = new TechReport('{{ active_page }}', reportPage, config, labels);
{% endblock %}
diff --git a/templates/techreport/templates/table_overview_multitech.html b/templates/techreport/templates/table_overview_multitech.html
new file mode 100644
index 00000000..fe806fab
--- /dev/null
+++ b/templates/techreport/templates/table_overview_multitech.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ Core web vitals
+
+
+
+ Technology
+ Origins
+ % Overall Good CWVs
+ Good LCP
+ Good CLS
+ Good FID
+ Good INP
+
+
+
+
+
+
+
diff --git a/webpack.config.js b/webpack.config.js
index 71c80937..8335b48c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -14,6 +14,7 @@ module.exports = {
'summaryLinked': './src/js/components/summaryLinked.js',
'tableGeneral': './src/js/components/tableGeneral.js',
'tableOverview': './src/js/components/tableOverview.js',
+ 'tableOverviewMulti': './src/js/components/tableOverviewMulti.js',
},
output: {
path: path.resolve(__dirname, 'static/js'),
From 70c76beea89325968035f82be7643f6fc572b4b7 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 27 Jul 2023 01:08:52 +0200
Subject: [PATCH 043/155] add technology options for each tech set in the
filters from the url (prototype, cleanup needed)
---
src/js/components/filters.js | 30 ++++++++++++---------
templates/techreport/templates/filters.html | 17 +++++++-----
2 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 49b0b197..fdd869bc 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -1,17 +1,21 @@
function updateTechnologies(technologies, filters) {
- const select = document.querySelector('select#tech');
- select.innerHTML = '';
- technologies.forEach((technology) => {
- const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
- const option = optionTmpl.querySelector('option');
- const formattedTech = technology.app.replaceAll(" ", "-");
- option.textContent = technology.app;
- option.value = formattedTech;
- if(formattedTech === filters.app[0]) {
- option.selected = true;
- }
- select.append(optionTmpl);
- });
+ const selectAll = document.querySelectorAll('select.tech');
+
+ selectAll.forEach(select => {
+ select.innerHTML = '';
+
+ technologies.forEach((technology) => {
+ const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
+ const option = optionTmpl.querySelector('option');
+ const formattedTech = technology.app.replaceAll(" ", "-");
+ option.textContent = technology.app;
+ option.value = formattedTech;
+ if(formattedTech === select.getAttribute('data-selected')) {
+ option.selected = true;
+ }
+ select.append(optionTmpl);
+ });
+ })
}
function updateGeo(geos, filters) {
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 8b304da3..3e822aef 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,11 +1,16 @@
@@ -36,3 +34,9 @@
Option
+
+
+ {% set option = "ALL" %}
+ {% set name = "tech-new" %}
+ {% include "techreport/templates/selector_tech.html" %}
+
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
new file mode 100644
index 00000000..56af13fc
--- /dev/null
+++ b/templates/techreport/templates/selector_tech.html
@@ -0,0 +1,6 @@
+Technology
+
+
+ {{ option }}
+
+
From 8a2fb08181b8ecf1812885e1b1dc125906929ffc Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 12 Aug 2023 01:29:19 +0200
Subject: [PATCH 045/155] improve styling, limit tags, limit tech selection for
drilldown page
---
server/routes.py | 2 -
src/js/components/drilldownHeader.js | 16 +-
static/css/techreport/general.css | 2 +
static/css/techreport/techreport.css | 51 +++++-
templates/techreport/comparison.html | 42 ++---
templates/techreport/drilldown.html | 172 +++++++++++---------
templates/techreport/techreport.html | 11 +-
templates/techreport/templates/filters.html | 9 +-
8 files changed, 196 insertions(+), 109 deletions(-)
diff --git a/server/routes.py b/server/routes.py
index a1a99bae..5ce224f5 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -100,8 +100,6 @@ def techreport(page_id):
active_tech_report["filters"] = filters
- print('active_tech_report', active_tech_report)
-
return render_template(
"techreport/%s.html" % page_id,
active_page=page_id,
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index c86141c9..5803fd2a 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -5,20 +5,32 @@ function setTitle(title) {
function setCategories(categories) {
if(categories.length > 0) {
+ /* Fetch the category list element and empty it. */
const list = document.querySelector('.intro .category-list');
list.innerHTML = '';
- categories.forEach((category) => {
+
+ /* Get the first 5 elements of the array */
+ const _categories = categories.slice(0,5);
+ _categories.forEach((category) => {
const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
cellTemplate.querySelector('li.cell').textContent = category;
list.appendChild(cellTemplate);
});
+
+ /* If there are more than 5 categories, show a message */
+ if(categories.length > 5) {
+ const more = categories.length - 5;
+ const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
+ cellTemplate.querySelector('li.cell').textContent = `+ ${more} more`;
+ list.appendChild(cellTemplate);
+ }
}
}
function update(data, filters) {
const app = filters.app[0];
setTitle(app);
- setCategories(data[app][0]?.category?.split(","));
+ setCategories(data[app][0]?.category?.split(", "));
}
export const DrilldownHeader = {
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index a17be5c2..a984c4b8 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -3,6 +3,7 @@
padding: 0;
margin: 0;
}
+
main {
color: var(--color-text);
}
@@ -63,3 +64,4 @@ h2 {
margin-left: auto;
margin-right: auto;
}
+
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 3e6be4ea..68429053 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -80,6 +80,7 @@
border-radius: 1rem;
border: 1px solid var(--color-text);
font-size: 0.875rem;
+ margin-bottom: 0.5rem;
}
@@ -193,7 +194,7 @@
color: var(--color-text);
}
-#filter-bar button[type="submit"] {
+#filter-bar button {
background-color: var(--color-teal-darker);
border-radius: 3px;
color: var(--color-blue-100);
@@ -202,12 +203,19 @@
padding: 0.25rem 0.5rem;
}
+button#add-tech {
+ margin-bottom: 3rem;
+}
/* Table */
.table-ui-wrapper {
overflow-x: scroll;
}
+.card.table-ui-wrapper {
+ margin-bottom: 2rem;
+}
+
.footnote {
margin-bottom: 2rem;
font-style: italic;
@@ -243,14 +251,54 @@
margin: 0.75rem 0;
}
+/* Info message */
+.info-panel {
+ background: #bfe1e7;
+ color: #203b40;
+ font-weight: 400;
+ padding: 0.5rem;
+}
+
+.info-panel > div {
+ display: flex;
+ align-items: center;
+}
+
+.info-panel p {
+ margin-bottom: 0;
+}
+
+.info-panel .info-label {
+ margin-right: 1rem;
+ padding: 0.3rem 0.5rem;
+ border-radius: 3px;
+ background-color: white;
+ border: 1px solid black;
+}
+
+
+
/* -------------------- */
/* ----- Sections ----- */
/* -------------------- */
+.report-content {
+ background-image: linear-gradient(#C0CED0, rgba(238,238,238,0));
+ border-top: 1px solid #6A797C;
+ background-size: 100% 50rem;
+ background-repeat: no-repeat;
+ padding-top: 3rem;
+}
+
+.report-section {
+ margin-bottom: 4rem;
+}
+
/* Summary */
.summary {
position: relative;
z-index: 1;
+ margin-bottom: 4rem;
}
.summary h2 {
@@ -293,3 +341,4 @@
position: static;
}
}
+
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 5ad39a36..9dda1ab5 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -9,34 +9,34 @@
Tech Report
Comparison
-
-
- Description not yet supported.
-
{% include "techreport/templates/filters.html" %}
- Client
-
- Mobile
- Desktop
-
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
-
-
-
Popular CMSes
-
Description
- {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
- {% set technologies_str = ','.join(technologies) %}
-
-
+
+
+
Popular CMSes
+
Description
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% set technologies_str = ','.join(technologies) %}
+
+
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 36b06dbb..7996bfa6 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -9,11 +9,6 @@
Tech Report
Drilldown
-
-
- Description not yet supported.
-
-
@@ -23,92 +18,113 @@
- Client
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
-
- Mobile
- Desktop
-
+
+
Summary
-
-
Summary
+
+
+
-
-
Core Web Vitals
-
Description
-
-
Latest data
-
Explanation
-
-
+
+
+
-
-
All data
-
Explanation
-
-
+
+
Core Web Vitals
+
Description
+
+
Latest data
+
Explanation
+
+
+
+
+
+
All data
+
Explanation
+
+
+
-
-
-
Lighthouse
-
Description
+
+
Lighthouse
+
Description
-
-
All data
-
Explanation
-
-
+
+
All data
+
Explanation
+
+
+
-
-
-
Page weight
-
Description
+
+
Page weight
+
Description
-
-
All data
-
Explanation
-
-
+
+
All data
+
Explanation
+
+
+
{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 2bd7cf2a..20daeaeb 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -11,6 +11,13 @@
{% endblock %}
{% block report_navigation %}
+
+
+
Beta
+
Changes are still being made to this page.
+
+
+
@@ -48,10 +55,6 @@
{% endblock %}
{% block main %}
-
-
Beta
-
Changes are still being made to this page.
-
{% block section %}{% endblock %}
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 7a29fe18..85f614a2 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,13 +1,20 @@
{% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% if active_page == "drilldown" %}
+ {% set technologies = [technologies[0]] %}
+ {% endif %}
+
{% for technology in technologies %}
{% set key = loop.index %}
{% set option = technology %}
{% set name = "tech-" + key|string %}
{% include "techreport/templates/selector_tech.html" %}
{% endfor %}
- Add technology
+
+ {% if active_page == "comparison" %}
+ Add technology
+ {% endif %}
From 4996410f38bb9763eb3907678ee814b0bd51e904 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 14 Aug 2023 15:42:30 +0200
Subject: [PATCH 046/155] add multi tech comparison tables
---
config/techreport.json | 2 +
src/js/components/summaryLinked.js | 3 +-
...rviewMulti.js => tableCWVOverviewMulti.js} | 26 ++++-
src/js/components/tableGeneralMulti.js | 102 ++++++++++++++++++
templates/techreport/comparison.html | 81 +++++++++++++-
templates/techreport/drilldown.html | 30 ++++--
templates/techreport/landing.html | 4 +-
templates/techreport/techreport.html | 6 +-
...html => table_cwv_overview_multitech.html} | 6 +-
.../techreport/templates/table_general.html | 4 +-
.../templates/table_general_multi.html | 16 +++
.../techreport/templates/table_overview.html | 4 +-
webpack.config.js | 3 +-
13 files changed, 258 insertions(+), 29 deletions(-)
rename src/js/components/{tableOverviewMulti.js => tableCWVOverviewMulti.js} (73%)
create mode 100644 src/js/components/tableGeneralMulti.js
rename templates/techreport/templates/{table_overview_multitech.html => table_cwv_overview_multitech.html} (80%)
create mode 100644 templates/techreport/templates/table_general_multi.html
diff --git a/config/techreport.json b/config/techreport.json
index 0e992d6b..c18c1ae2 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -23,6 +23,8 @@
"values": {
"date": "Date",
"client": "Client",
+ "origins": "Origins",
+
"origins_eligible_for_cwv": "Eligible",
"origins_eligible_for_fid": "Eligible",
"origins_eligible_for_cls": "Eligible",
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
index 1e0db27d..84bf3088 100644
--- a/src/js/components/summaryLinked.js
+++ b/src/js/components/summaryLinked.js
@@ -8,6 +8,7 @@ class SummaryLinked extends HTMLElement {
this.allData = [];
this.placeholder = '000';
this.client = 'mobile';
+ this.link = "#";
this.attachShadow({ mode: 'open' });
const template = document.getElementById('summary-linked').content.cloneNode(true);
@@ -19,7 +20,7 @@ class SummaryLinked extends HTMLElement {
}
static get observedAttributes() {
- return ['key', 'title', 'client', 'loaded'];
+ return ['key', 'title', 'client', 'loaded', 'link'];
}
attributeChangedCallback(property, oldValue, newValue) {
diff --git a/src/js/components/tableOverviewMulti.js b/src/js/components/tableCWVOverviewMulti.js
similarity index 73%
rename from src/js/components/tableOverviewMulti.js
rename to src/js/components/tableCWVOverviewMulti.js
index 28ce4474..9fce41fc 100644
--- a/src/js/components/tableOverviewMulti.js
+++ b/src/js/components/tableCWVOverviewMulti.js
@@ -1,6 +1,12 @@
import { getLatestEntry } from "../utils";
-class TableOverviewMulti extends HTMLElement {
+/*
+ * Core Web Vitals overview table for multiple technologies.
+ * Uses the latest data for each of the technologies.
+ * Columns: Core Web Vitals breakdown
+ * Rows: Selected technologies
+ */
+class tableCWVOverviewMulti extends HTMLElement {
constructor() {
super();
@@ -9,7 +15,7 @@ class TableOverviewMulti extends HTMLElement {
this.technologies = '';
this.attachShadow({ mode: 'open' });
- const template = document.getElementById('table-overview-multitech').content.cloneNode(true);
+ const template = document.getElementById('table-cwv-overview-multitech').content.cloneNode(true);
this.shadowRoot.appendChild(template);
}
@@ -29,10 +35,10 @@ class TableOverviewMulti extends HTMLElement {
setData() {
const technologies = this.technologies?.split(",");
- const latestData = [];
const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
tableBody.innerHTML = '';
+ /* Define keys for the different core web vitals */
const coreWebVitals = [
{
origins_with_good: "origins_with_good_cwv",
@@ -57,26 +63,32 @@ class TableOverviewMulti extends HTMLElement {
];
technologies.forEach(technology => {
+ /* Select the data for each of the technologies */
const _data = this.allData?.[technology];
+ /* If the data exits, fill in the table */
if(_data) {
+ /* Get the data for the selected client, and get the latest entry */
const _clientData = _data?.filter(entry => entry.client === this.client);
const _clientDataSorted = [..._clientData]?.sort((a, b) => {
return new Date(a.date) - new Date(b.date);
});
-
const _latest = getLatestEntry(_clientDataSorted);
+ /* Fetch the templates for the rows and cells */
const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true);
const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
+ /* Fill in the tech names as row headings */
headingCellTemplate.querySelector('th').textContent = technology;
rowTemplate.querySelector('tr').append(headingCellTemplate);
+ /* Fill in amount of origins tech has */
const origins = document.getElementById('table-general-cell').content.cloneNode(true);
origins.querySelector('td').textContent = _latest.origins;
rowTemplate.querySelector('tr').append(origins);
+ /* Fill in the data for each of the core web vitals */
coreWebVitals.forEach(cwv => {
const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
const percentageGood = parseInt(_latest[cwv?.origins_with_good] / _latest[cwv?.origins_eligible] * 10000) / 100;
@@ -84,7 +96,11 @@ class TableOverviewMulti extends HTMLElement {
rowTemplate.querySelector('tr').append(dataCellTemplate);
})
+ /* Add the row to the table body */
tableBody.append(rowTemplate);
+
+ /* Show the latest timestamp */
+ this.shadowRoot.querySelector('.timestamp').innerHTML = _latest.date;
}
});
@@ -95,4 +111,4 @@ class TableOverviewMulti extends HTMLElement {
}
}
-customElements.define('table-overview-multitech', TableOverviewMulti);
+customElements.define('table-cwv-overview-multitech', tableCWVOverviewMulti);
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
new file mode 100644
index 00000000..441696a8
--- /dev/null
+++ b/src/js/components/tableGeneralMulti.js
@@ -0,0 +1,102 @@
+import { getLatestEntry } from "../utils";
+
+/*
+ * Table comparing data between different technologies.
+ * Dataset: Based on selected metric (CWV, lighthouse, etc.)
+ * Columns: Selected technologies.
+ * Rows: Time entries.
+ */
+class tableGenralMulti extends HTMLElement {
+ constructor() {
+ super();
+
+ this.allData = [];
+ this.technologies = '';
+ this.client = 'mobile';
+ this.metric = 'origins';
+
+ this.attachShadow({ mode: 'open' });
+ const template = document.getElementById('table-general-multitech').content.cloneNode(true);
+ this.shadowRoot.appendChild(template);
+ }
+
+ connectedCallback() {
+ this.renderComponent();
+ }
+
+ static get observedAttributes() {
+ return ['loaded', 'client', 'all_data', 'technologies', 'metric'];
+ }
+
+ attributeChangedCallback(property, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ this[ property ] = newValue;
+ this.renderComponent();
+ }
+
+ setData() {
+ /* Turn the techs into an array */
+ const technologies = this.technologies?.split(",");
+
+ /* Select the elements within the component */
+ const tableHead = this.shadowRoot.querySelector('table.table-ui thead tr');
+ const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
+
+ /* Reset the component */
+ tableBody.innerHTML = '';
+ tableHead.innerHTML = '';
+
+ /* Set the date heading */
+ const dateHeading = document.createElement('th');
+ dateHeading.innerHTML = 'Date';
+ tableHead.append(dateHeading);
+
+ const _dates = [];
+
+ technologies.forEach(technology => {
+ /* Fill in the tech names as column headings. */
+ const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
+ headingCellTemplate.querySelector('th').textContent = technology;
+ tableHead.append(headingCellTemplate);
+
+ /* TODO: This could be done in a central place after fetching the data */
+ /* Add the dates to the dates array */
+ const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client);
+
+ _data?.forEach(entry => {
+ if(!_dates.includes(entry.date)) {
+ _dates.push(entry.date);
+ }
+ });
+ });
+
+ /* Add a row to the table body for each of the time entries */
+ _dates.forEach(date => {
+ /* Select the needed templates */
+ const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true);
+ const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
+
+ /* Fill in the dates */
+ headingCellTemplate.querySelector('th').textContent = date;
+ rowTemplate.append(headingCellTemplate);
+
+ /* For each of the technologies, select the chosen metric for the given date */
+ technologies.forEach(technology => {
+ const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
+ const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client)?.find(row => row.date = date);
+
+ dataCellTemplate.querySelector('td').textContent = _data?.[this.metric];
+ rowTemplate.append(dataCellTemplate);
+ });
+
+ /* Append the row to the table */
+ tableBody.append(rowTemplate);
+ });
+ }
+
+ renderComponent() {
+ this.setData();
+ }
+}
+
+customElements.define('table-general-multitech', tableGenralMulti);
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 9dda1ab5..90345d4d 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -3,6 +3,10 @@
{% block section %}
{{ super() }}
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% set technologies_str = ','.join(technologies) %}
+
+
@@ -26,16 +30,83 @@
-
Popular CMSes
+
Comparing {{ technologies | length }} technologies
Description
- {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
- {% set technologies_str = ','.join(technologies) %}
-
+
+
+
+
+
+
Adoption
+
Description
+
+
+
Origins
+
Explanation
+
+
+
+
+
+
+
Core Web Vitals
+
Description
+
+
+
Good Core Web Vitals
+
Explanation
+
+
+
+
+
+
+
Lighthouse
+
Description
+
+
+
Median Lighthouse Performance
+
Explanation
+
+
+
+
+
+
+
Page weight
+
Description
+
+
+
Median bytes total
+
Explanation
+
-
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 7996bfa6..541c616f 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -69,10 +69,26 @@
Summary
-
+
+
Adoption
+
Description
+
+
+
All data
+
Explanation
+
+
+
+
+
+
Core Web Vitals
Description
-
+
Latest data
Explanation
Latest data
-
+
All data
Explanation
All data
-
+
Lighthouse
Description
-
+
All data
Explanation
All data
-
+
Page weight
Description
-
+
All data
Explanation
Explore
Popular CMSes
Description
-
-
+
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 20daeaeb..c2b01648 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -61,8 +61,9 @@
{% include "techreport/templates/drilldown_header.html" %}
{% include "techreport/templates/summary_linked.html" %}
{% include "techreport/templates/table_general.html" %}
+ {% include "techreport/templates/table_general_multi.html" %}
{% include "techreport/templates/table_overview.html" %}
- {% include "techreport/templates/table_overview_multitech.html" %}
+ {% include "techreport/templates/table_cwv_overview_multitech.html" %}
{% endblock %}
@@ -72,8 +73,9 @@
-
+
+
diff --git a/templates/techreport/templates/table_overview_multitech.html b/templates/techreport/templates/table_cwv_overview_multitech.html
similarity index 80%
rename from templates/techreport/templates/table_overview_multitech.html
rename to templates/techreport/templates/table_cwv_overview_multitech.html
index fe806fab..525f28f2 100644
--- a/templates/techreport/templates/table_overview_multitech.html
+++ b/templates/techreport/templates/table_cwv_overview_multitech.html
@@ -1,10 +1,11 @@
-
+
+
- Core web vitals
+ TODO: ADD CAPTION
@@ -20,5 +21,6 @@
+ Data from
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
index baddfdd4..e2dae567 100644
--- a/templates/techreport/templates/table_general.html
+++ b/templates/techreport/templates/table_general.html
@@ -3,8 +3,8 @@
-
- % of websites with good overall Core Web Vitals over time.
+
+ TODO: ADD CAPTION
diff --git a/templates/techreport/templates/table_general_multi.html b/templates/techreport/templates/table_general_multi.html
new file mode 100644
index 00000000..5f3d43cd
--- /dev/null
+++ b/templates/techreport/templates/table_general_multi.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ TODO: ADD CAPTION
+
+
+
+
+
+
+
+
+
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
index d1412122..9b413864 100644
--- a/templates/techreport/templates/table_overview.html
+++ b/templates/techreport/templates/table_overview.html
@@ -3,8 +3,8 @@
-
- Latest % of websites with good core web vitals.
+
+ TODO: ADD CAPTION
diff --git a/webpack.config.js b/webpack.config.js
index 8335b48c..1f47b145 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -13,8 +13,9 @@ module.exports = {
'send-web-vitals': './src/js/send-web-vitals.js',
'summaryLinked': './src/js/components/summaryLinked.js',
'tableGeneral': './src/js/components/tableGeneral.js',
+ 'tableGeneralMulti': './src/js/components/tableGeneralMulti.js',
'tableOverview': './src/js/components/tableOverview.js',
- 'tableOverviewMulti': './src/js/components/tableOverviewMulti.js',
+ 'tableCWVOverviewMulti': './src/js/components/tableCWVOverviewMulti.js',
},
output: {
path: path.resolve(__dirname, 'static/js'),
From 0a05bb8053f08be7779668d47848ce94f4d454de Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 15 Aug 2023 23:45:00 +0200
Subject: [PATCH 047/155] update styling and responsiveness, remember geo/rank
filters
---
src/js/components/tableCWVOverviewMulti.js | 28 ++++----
static/components/table.css | 18 +++--
static/css/techreport/landing.css | 25 +++----
static/css/techreport/techreport.css | 16 ++---
templates/techreport/comparison.html | 2 +-
templates/techreport/drilldown.html | 4 +-
templates/techreport/landing.html | 62 +++++++++++------
templates/techreport/techreport.html | 68 ++++++++++---------
templates/techreport/templates/filters.html | 60 ++++++++--------
.../techreport/templates/table_general.html | 24 ++++---
.../templates/table_general_multi.html | 24 ++++---
.../techreport/templates/table_overview.html | 31 +++++----
12 files changed, 205 insertions(+), 157 deletions(-)
diff --git a/src/js/components/tableCWVOverviewMulti.js b/src/js/components/tableCWVOverviewMulti.js
index 9fce41fc..178014c1 100644
--- a/src/js/components/tableCWVOverviewMulti.js
+++ b/src/js/components/tableCWVOverviewMulti.js
@@ -75,29 +75,31 @@ class tableCWVOverviewMulti extends HTMLElement {
});
const _latest = getLatestEntry(_clientDataSorted);
- /* Fetch the templates for the rows and cells */
- const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true);
- const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
-
/* Fill in the tech names as row headings */
- headingCellTemplate.querySelector('th').textContent = technology;
- rowTemplate.querySelector('tr').append(headingCellTemplate);
+ const row = document.createElement('tr');
+ const headingCell = document.createElement('th');
+ const technologyLinkEl = document.createElement('a');
+ technologyLinkEl.className = 'row-link';
+ technologyLinkEl.href = `/reports/techreport/drilldown/?tech=${technology}`;
+ technologyLinkEl.innerHTML = technology;
+ headingCell.append(technologyLinkEl);
+ row.append(headingCell);
/* Fill in amount of origins tech has */
- const origins = document.getElementById('table-general-cell').content.cloneNode(true);
- origins.querySelector('td').textContent = _latest.origins;
- rowTemplate.querySelector('tr').append(origins);
+ const origins = document.createElement('td');
+ origins.innerHTML = _latest.origins;
+ row.append(origins);
/* Fill in the data for each of the core web vitals */
coreWebVitals.forEach(cwv => {
- const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
+ const dataCell = document.createElement('td');
const percentageGood = parseInt(_latest[cwv?.origins_with_good] / _latest[cwv?.origins_eligible] * 10000) / 100;
- dataCellTemplate.querySelector('td').textContent = `${percentageGood}%`;
- rowTemplate.querySelector('tr').append(dataCellTemplate);
+ dataCell.innerHTML = `${percentageGood}%`;
+ row.append(dataCell);
})
/* Add the row to the table body */
- tableBody.append(rowTemplate);
+ tableBody.append(row);
/* Show the latest timestamp */
this.shadowRoot.querySelector('.timestamp').innerHTML = _latest.date;
diff --git a/static/components/table.css b/static/components/table.css
index 89ce81b2..f3a15630 100644
--- a/static/components/table.css
+++ b/static/components/table.css
@@ -1,3 +1,11 @@
+.table-ui-wrapper {
+ overflow: auto;
+}
+
+.table-ui-wrapper:focus-visible {
+ outline: 1.5px solid var(--color-teal-dark);
+ outline-offset: 1.5px;
+}
.table-ui {
width: 100%;
@@ -19,12 +27,12 @@
border-bottom: 1px solid var(--color-text);
}
-.table-ui thead th {
- padding: 1rem 0;
+.table-ui :is(td, th) {
+ min-width: 5rem;
}
-.table-ui tbody :is(td, th) {
- padding: 1rem 0;
+.table-ui :is(td, th):not(:last-child) {
+ padding: 1rem 2rem 1rem 0;
}
.table-ui tbody tr {
@@ -47,6 +55,8 @@
.table-ui tr a {
color: var(--color-link);
text-decoration: underline;
+ width: 100%;
+ display: block;
}
.table-ui tr .row-link:is(:hover, :focus) {
diff --git a/static/css/techreport/landing.css b/static/css/techreport/landing.css
index abdc041a..fd9a4786 100644
--- a/static/css/techreport/landing.css
+++ b/static/css/techreport/landing.css
@@ -1,9 +1,14 @@
+.landing-content {
+ margin-top: 10rem;
+}
+
.choices {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
column-gap: 2rem;
row-gap: 1rem;
margin-bottom: 4rem;
+ margin-top: -15rem;
}
.choices .card {
@@ -21,6 +26,14 @@
padding: 0;
}
+.choices .card .img-placeholder {
+ display: block;
+ width: 100%;
+ height: 17rem;
+ background-color: #EEEEEE;
+ margin-top: 1rem;
+}
+
.latest-info h2 {
font-size: 1rem;
font-weight: 600;
@@ -42,18 +55,6 @@
font-weight: 600;
}
-.report-summary-wrapper {
- background-image:
- linear-gradient(
- var(--color-teal-faded) 60%,
- var(--color-page-background)
- );
- background-size: 100% 25rem;
- background-repeat: no-repeat;
- border-top: 1px solid var(--color-teal-medium);
- padding-bottom: 5rem;
-}
-
.report-summary-tables {
padding: 4rem 0;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 68429053..27d77bae 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -37,10 +37,6 @@
margin-top: 0;
background-color: transparent;
padding: 4rem 0;
- display: grid;
- grid-template-columns: 1fr 20rem;
- column-gap: 2rem;
- row-gap: 2rem;
}
.intro h1 {
@@ -176,16 +172,21 @@
}
/* Filters */
-#filter-bar {
- padding: 1rem;
+#filter-bar > div {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+#filter-bar > div > *:not(:last-child) {
+ margin-right: 1.5rem;
}
#filter-bar label {
margin-bottom: 0.25rem;
+ display: block;
}
#filter-bar select {
- display: block;
width: 20rem;
max-width: 100%;
margin-bottom: 1rem;
@@ -341,4 +342,3 @@ button#add-tech {
position: static;
}
}
-
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 90345d4d..e4a4a614 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -8,7 +8,7 @@
-
+
Tech Report
Comparison
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 541c616f..20904151 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -4,7 +4,7 @@
{{ super() }}
-
+
Tech Report
Drilldown
@@ -121,7 +121,7 @@ All data
diff --git a/templates/techreport/landing.html b/templates/techreport/landing.html
index 673c3174..424a8074 100644
--- a/templates/techreport/landing.html
+++ b/templates/techreport/landing.html
@@ -6,32 +6,54 @@
{% endblock %}
{% block section %}
-
-
-
-
Get detailed information about one technology.
-
-
-
-
Get detailed information about two to ten technologies.
+
+
+
+ Reports
+ Tech Report
+
+
+ Placeholder text: A short description about what it is that we display in the Core Web Vitals report, and how it can be used. There should probably be links here to the individual technology pages and a few interesting comparison pages, as well as to the methodology page and the discussions etc like the reports have today.
+
-
-
Explore
-
Placeholder
+
+
+
+
+
Get detailed information about one technology.
+
+
+
+
+
Get detailed information about two to ten technologies.
+
+
+
+
+
+
Explore
+
Placeholder
+
+
+
Popular CMSes
+
Description
-
{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index c2b01648..608c5a84 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -19,38 +19,42 @@
-
-
- {% set ariaCurrent = "false" %}
- {% if active_page == "landing" %}{% set ariaCurrent = "page" %}{% endif %}
-
- Home
-
-
-
- {% set ariaCurrent = "false" %}
- {% if active_page == "drilldown" %}{% set ariaCurrent = "page" %}{% endif %}
-
- Drilldown
-
-
-
- {% set ariaCurrent = "false" %}
- {% if active_page == "comparison" %}{% set ariaCurrent = "page" %}{% endif %}
-
- Comparison
-
-
-
+ {% set filters = "" %}
+ {% if tech_report_page.filters %}
+ {% set filters = "?geo=" + tech_report_page.filters.geo + "&rank=" + tech_report_page.filters.rank %}
+ {% endif %}
+
+
+ {% set ariaCurrent = "false" %}
+ {% if active_page == "landing" %}{% set ariaCurrent = "page" %}{% endif %}
+
+ Home
+
+
+
+ {% set ariaCurrent = "false" %}
+ {% if active_page == "drilldown" %}{% set ariaCurrent = "page" %}{% endif %}
+
+ Drilldown
+
+
+
+ {% set ariaCurrent = "false" %}
+ {% if active_page == "comparison" %}{% set ariaCurrent = "page" %}{% endif %}
+
+ Comparison
+
+
+
{% endblock %}
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 85f614a2..2dbb8a31 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,37 +1,39 @@
- {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
- {% if active_page == "drilldown" %}
- {% set technologies = [technologies[0]] %}
- {% endif %}
+
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% if active_page == "drilldown" %}
+ {% set technologies = [technologies[0]] %}
+ {% endif %}
- {% for technology in technologies %}
- {% set key = loop.index %}
- {% set option = technology %}
- {% set name = "tech-" + key|string %}
- {% include "techreport/templates/selector_tech.html" %}
- {% endfor %}
+ {% for technology in technologies %}
+ {% set key = loop.index %}
+ {% set option = technology %}
+ {% set name = "tech-" + key|string %}
+ {% include "techreport/templates/selector_tech.html" %}
+ {% endfor %}
- {% if active_page == "comparison" %}
- Add technology
- {% endif %}
+ {% if active_page == "comparison" %}
+ Add
+ {% endif %}
-
-
- Geo
-
-
- ALL
-
-
-
-
- Rank
-
-
- ALL
-
-
+
+
+ Geo
+
+
+ ALL
+
+
+
+
+ Rank
+
+
+ ALL
+
+
+
Update
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
index e2dae567..728bd958 100644
--- a/templates/techreport/templates/table_general.html
+++ b/templates/techreport/templates/table_general.html
@@ -2,17 +2,19 @@
-
-
- TODO: ADD CAPTION
-
-
-
-
-
-
-
-
+
+
+
diff --git a/templates/techreport/templates/table_general_multi.html b/templates/techreport/templates/table_general_multi.html
index 5f3d43cd..d3c038de 100644
--- a/templates/techreport/templates/table_general_multi.html
+++ b/templates/techreport/templates/table_general_multi.html
@@ -2,15 +2,17 @@
-
-
- TODO: ADD CAPTION
-
-
-
-
-
-
-
-
+
+
+
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
index 9b413864..288cbf52 100644
--- a/templates/techreport/templates/table_overview.html
+++ b/templates/techreport/templates/table_overview.html
@@ -2,20 +2,23 @@
-
-
- TODO: ADD CAPTION
-
-
-
- Core Web Vital
- % Good scores
- Trend
-
-
-
-
-
+
+
+
+
+ % Of tested origins that had good Core Web Vitals
+
+
+
+ Core Web Vital
+ % Good scores
+ Trend
+
+
+
+
+
+
From 8c36231792aa7c44e25c914f4fa2baab41a49dbc Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 17 Aug 2023 13:44:03 +0200
Subject: [PATCH 048/155] bug fixes, show warning when data doesnt exist
---
src/js/components/drilldownHeader.js | 10 ++-
src/js/components/filters.js | 10 +++
src/js/components/summaryLinked.js | 12 ++--
src/js/components/tableCWVOverviewMulti.js | 9 +++
src/js/components/tableGeneralMulti.js | 2 +-
src/js/techreport.js | 61 ++++++++++++-------
static/css/techreport/techreport.css | 13 ++++
templates/techreport/comparison.html | 1 -
.../table_cwv_overview_multitech.html | 4 +-
9 files changed, 91 insertions(+), 31 deletions(-)
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index 5803fd2a..7086637a 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -29,8 +29,14 @@ function setCategories(categories) {
function update(data, filters) {
const app = filters.app[0];
- setTitle(app);
- setCategories(data[app][0]?.category?.split(", "));
+
+ if(app) {
+ setTitle(app);
+ }
+
+ if(data[app]) {
+ setCategories(data[app][0]?.category?.split(", "));
+ }
}
export const DrilldownHeader = {
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index ae7c2a38..08530ee7 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -1,11 +1,21 @@
function updateTechnologies(technologies, filters) {
/* Get existing tech selectors on the page */
const allTechSelectors = document.querySelectorAll('select.tech');
+ const techNames = technologies.map(element => element.app);
/* Update the options inside all of the selectors */
allTechSelectors.forEach(techSelector => {
techSelector.innerHTML = '';
+ const selectedTechFormatted = techSelector.getAttribute('data-selected').replaceAll('-', ' ');
+
+ /* If the technology doesn't exist, throw a warning */
+ if(!techNames.includes(selectedTechFormatted)) {
+ const errorMsg = document.createElement('p');
+ errorMsg.textContent = 'Technology not found, please select a different one';
+ techSelector.before(errorMsg);
+ }
+
/* Add one option per technology */
technologies.forEach((technology) => {
const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
index 84bf3088..e8fbc674 100644
--- a/src/js/components/summaryLinked.js
+++ b/src/js/components/summaryLinked.js
@@ -50,11 +50,13 @@ class SummaryLinked extends HTMLElement {
}
renderComponent() {
- const _filtered = this.allData?.filter(row => row.client === this.client);
- const _latest = getLatestEntry(_filtered);
- this.latest = _latest;
- this.setTitle();
- this.setData();
+ if(this.allData) {
+ const _filtered = this.allData?.filter(row => row.client === this.client);
+ const _latest = getLatestEntry(_filtered);
+ this.latest = _latest;
+ this.setTitle();
+ this.setData();
+ }
}
}
diff --git a/src/js/components/tableCWVOverviewMulti.js b/src/js/components/tableCWVOverviewMulti.js
index 178014c1..36166965 100644
--- a/src/js/components/tableCWVOverviewMulti.js
+++ b/src/js/components/tableCWVOverviewMulti.js
@@ -62,6 +62,8 @@ class tableCWVOverviewMulti extends HTMLElement {
},
];
+ this.shadowRoot.querySelector('.errorMsg').innerHTML = '';
+
technologies.forEach(technology => {
/* Select the data for each of the technologies */
const _data = this.allData?.[technology];
@@ -104,6 +106,13 @@ class tableCWVOverviewMulti extends HTMLElement {
/* Show the latest timestamp */
this.shadowRoot.querySelector('.timestamp').innerHTML = _latest.date;
}
+
+ /* Else show a mesage that this tech doesn't have data */
+ else {
+ const errorMsg = document.createElement('p');
+ errorMsg.textContent = `No data found for ${technology}.`;
+ this.shadowRoot.querySelector('.errorMsg').append(errorMsg);
+ }
});
}
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index 441696a8..aec75b1a 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -85,7 +85,7 @@ class tableGenralMulti extends HTMLElement {
const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client)?.find(row => row.date = date);
- dataCellTemplate.querySelector('td').textContent = _data?.[this.metric];
+ dataCellTemplate.querySelector('td').textContent = _data ? _data[this.metric] : '-';
rowTemplate.append(dataCellTemplate);
});
diff --git a/src/js/techreport.js b/src/js/techreport.js
index bdb75cc2..a9cecad9 100644
--- a/src/js/techreport.js
+++ b/src/js/techreport.js
@@ -55,7 +55,8 @@ class TechReport {
.then(result => this.processData(result))
.then(result => {
data[technology] = result;
- });
+ })
+ .catch(error => console.log('Something went wrong', error));
})).then(() => {
this.updateComponents(data);
});
@@ -109,31 +110,49 @@ class TechReport {
const app = this.filters.app[0];
- const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
- latestComponents.forEach((component) => {
- component.latest = data[app][0];
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- });
+ if(data && data[app]) {
+ const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
+ latestComponents.forEach((component) => {
+ component.latest = data[app][0];
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ });
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
- allDataComponents.forEach((component) => {
- component.allData = data[app];
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- });
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = data[app];
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ });
+ } else {
+ this.updateWithEmptyData();
+ }
}
updateComparisonComponents(data) {
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ if(data && Object.keys(data).length > 0) {
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+
+ allDataComponents.forEach((component) => {
+ component.allData = data;
+ component.page = this.page;
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ component.setAttribute('all_data', JSON.stringify(data));
+ });
+ } else {
+ this.updateWithEmptyData();
+ }
+ }
- allDataComponents.forEach((component) => {
- component.allData = data;
- component.page = this.page;
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- component.setAttribute('all_data', JSON.stringify(data));
- });
+ updateWithEmptyData() {
+ const text = document.createElement('p');
+ text.textContent = 'No data found for this query';
+ text.className = 'error';
+
+ const report = document.querySelector('.report-content');
+ report.innerHTML = '';
+ report.append(text);
}
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 27d77bae..c758b970 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -295,6 +295,19 @@ button#add-tech {
margin-bottom: 4rem;
}
+.report-content:has(> .error) {
+ background-image: none;
+ padding-top: 0;
+ background-color: #fff;
+ border-bottom: 1px solid #6A797C;
+}
+
+.report-content > .error {
+ margin-bottom: 0;
+ text-align: center;
+ padding: 5rem 0;
+}
+
/* Summary */
.summary {
position: relative;
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index e4a4a614..f706d92f 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -6,7 +6,6 @@
{% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
{% set technologies_str = ','.join(technologies) %}
-
diff --git a/templates/techreport/templates/table_cwv_overview_multitech.html b/templates/techreport/templates/table_cwv_overview_multitech.html
index 525f28f2..5f7949ea 100644
--- a/templates/techreport/templates/table_cwv_overview_multitech.html
+++ b/templates/techreport/templates/table_cwv_overview_multitech.html
@@ -2,6 +2,7 @@
+ Data from
@@ -21,6 +22,7 @@
- Data from
+
+
From 1a7822112c1c6bbd94f1da453562747699a6fc22 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 19 Aug 2023 23:37:07 +0200
Subject: [PATCH 049/155] allow removing techs in comparison mode
---
src/js/components/filters.js | 56 ++++++++++++++++---
static/css/techreport/general.css | 6 ++
templates/techreport/templates/filters.html | 1 +
.../techreport/templates/selector_tech.html | 17 ++++--
4 files changed, 65 insertions(+), 15 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 08530ee7..fb2410db 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -1,4 +1,4 @@
-function updateTechnologies(technologies, filters) {
+function updateTechnologies(technologies) {
/* Get existing tech selectors on the page */
const allTechSelectors = document.querySelectorAll('select.tech');
const techNames = technologies.map(element => element.app);
@@ -28,7 +28,9 @@ function updateTechnologies(technologies, filters) {
}
techSelector.append(optionTmpl);
});
- })
+ });
+
+ hideRemoveButton();
}
function updateGeo(geos, filters) {
@@ -69,30 +71,66 @@ function bindFilterListener() {
submit.addEventListener('click', setFilter);
}
- const add = document.getElementById('add-tech');
- if(add) {
- add.addEventListener('click', addTechnologySelector);
+ const addButton = document.getElementById('add-tech');
+ if(addButton) {
+ addButton.addEventListener('click', addTechnologySelector);
}
+
+ const removeButtons = Object.values(document.getElementsByClassName('remove-tech'));
+ removeButtons?.forEach(removeButton => removeButton.addEventListener('click', removeTechnology));
}
+
function addTechnologySelector(event) {
event.preventDefault();
const selectorTemplate = document.getElementById('tech-selector').content.cloneNode(true);
+
const selectElement = selectorTemplate.querySelector('select');
const labelElement = selectorTemplate.querySelector('label');
+ const removeButton = selectorTemplate.querySelector('.remove-tech');
+
+ /* Set a unique name on the new element (based on the amount of techs) */
const techId = `tech-${document.querySelectorAll('select.tech[name="tech"]').length + 1}`;
selectElement.setAttribute('id', techId);
labelElement.setAttribute('for', techId);
+ removeButton.dataset.tech = techId;
+
+ removeButton.classList.remove('hidden');
+
+ /* Bind functionality to the button */
+ removeButton.addEventListener('click', removeTechnology);
+ /* Fill in all techs and select the first one */
selectElement.innerHTML = document.querySelector('select.tech').innerHTML;
- const firstOption = selectElement.querySelector('option');
- firstOption.selected = true;
+ selectElement.getElementsByTagName('option')[0].selected = true;
- const techs = document.getElementsByName('tech');
+ /* Add the new tech to the end of the list */
+ const techs = document.getElementsByClassName('tech-selector-group');
const last = techs[techs.length - 1];
-
last.after(selectorTemplate);
+
+ /* If this is there are 2 or more technologies, the first one can be removed too */
+ if(techs.length === 2) {
+ techs[0].getElementsByClassName('remove-tech')[0].classList.remove('hidden');
+ }
+}
+
+function removeTechnology(event) {
+ event.preventDefault();
+
+ /* Remove the tech selector group from the DOM */
+ event.target.parentElement.remove();
+
+ /* Don't show any remove buttons if there is only one element left */
+ hideRemoveButton();
+}
+
+function hideRemoveButton() {
+ const techs = document.getElementsByClassName('tech-selector-group');
+ if(techs.length === 1) {
+ techs[0].getElementsByClassName('remove-tech')[0].classList.add('hidden');
+ }
}
function setFilter(event) {
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index a984c4b8..afefd49d 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -22,6 +22,7 @@ h2 {
outline-offset: 1.5px;
}
+/* Hidden visually, but still accessible through screen readers/other AT */
.sr-only {
clip: rect(0 0 0 0);
clip-path: inset(50%);
@@ -32,6 +33,11 @@ h2 {
width: 1px;
}
+/* Hidden for everyone */
+.hidden {
+ display: none;
+}
+
.card {
padding: 1.5rem;
background: var(--color-card-background);
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 2dbb8a31..3d8cb704 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -47,5 +47,6 @@
{% set option = "ALL" %}
{% set name = "tech-new" %}
+ {% set key = 2 %}
{% include "techreport/templates/selector_tech.html" %}
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index 56af13fc..620cc405 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -1,6 +1,11 @@
-Technology
-
-
- {{ option }}
-
-
+
+ Technology
+
+
+ {{ option }}
+
+
+ {% if active_page == "comparison" %}
+ Remove
+ {% endif %}
+
From 4745cde030f1dbb70eb1f4f77049d3f4cae0b4fe Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 20 Aug 2023 00:12:02 +0200
Subject: [PATCH 050/155] bugfix
---
src/js/components/filters.js | 2 +-
src/js/components/tableGeneralMulti.js | 8 +++++++-
templates/techreport/comparison.html | 16 ++++++++++++++++
.../templates/table_cwv_overview_multitech.html | 2 +-
.../templates/table_general_multi.html | 4 +++-
5 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index fb2410db..401b823b 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -30,7 +30,7 @@ function updateTechnologies(technologies) {
});
});
- hideRemoveButton();
+ // hideRemoveButton();
}
function updateGeo(geos, filters) {
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index aec75b1a..9bfafce1 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -25,7 +25,7 @@ class tableGenralMulti extends HTMLElement {
}
static get observedAttributes() {
- return ['loaded', 'client', 'all_data', 'technologies', 'metric'];
+ return ['loaded', 'client', 'all_data', 'technologies', 'metric', 'id'];
}
attributeChangedCallback(property, oldValue, newValue) {
@@ -41,6 +41,12 @@ class tableGenralMulti extends HTMLElement {
/* Select the elements within the component */
const tableHead = this.shadowRoot.querySelector('table.table-ui thead tr');
const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
+ const tableCaption = this.shadowRoot.querySelector('table.table-ui caption');
+ const tableWrapper = this.shadowRoot.querySelector('table-ui-wrapper[role="region"]');
+
+ /* Set the caption id and connect the wrapper to it */
+ tableCaption.setAttribute('id', this.id);
+ tableWrapper.setAttribute('aria-labelledby', this.id);
/* Reset the component */
tableBody.innerHTML = '';
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index f706d92f..3682c90c 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -53,7 +53,11 @@ Origins
client="mobile"
technologies="{{ technologies_str }}"
metric="origins"
+ id="origins-over-time"
>
+
+ The origins over time, compared for the selected technologies.
+
@@ -70,7 +74,11 @@ Good Core Web Vitals
client="mobile"
technologies="{{ technologies_str }}"
metric="origins_with_good_cwv"
+ id="good-cwv-over-time"
>
+
+ The amount of good core web vitals over time, compared for the selected technologies.
+
@@ -87,7 +95,11 @@
Median Lighthouse Performance
client="mobile"
technologies="{{ technologies_str }}"
metric="median_lighthouse_score_performance"
+ id="lighthouse-over-time"
>
+
+ The lighthouse scores over time, compared for the selected technologies.
+
@@ -104,7 +116,11 @@
Median bytes total
client="mobile"
technologies="{{ technologies_str }}"
metric="median_bytes_total"
+ id="weight-over-time"
>
+
+ The page weight over time, compared for the selected technologies.
+
diff --git a/templates/techreport/templates/table_cwv_overview_multitech.html b/templates/techreport/templates/table_cwv_overview_multitech.html
index 5f7949ea..c9350d08 100644
--- a/templates/techreport/templates/table_cwv_overview_multitech.html
+++ b/templates/techreport/templates/table_cwv_overview_multitech.html
@@ -6,7 +6,7 @@
- TODO: ADD CAPTION
+ The amount of origins with good Core Web Vitals of different technologies.
diff --git a/templates/techreport/templates/table_general_multi.html b/templates/techreport/templates/table_general_multi.html
index d3c038de..90e669d7 100644
--- a/templates/techreport/templates/table_general_multi.html
+++ b/templates/techreport/templates/table_general_multi.html
@@ -6,7 +6,9 @@
-
+
+ Multiple technology comparison
+
From 7f8855d972cb129962b59931bae90288e7e96aaa Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 20 Aug 2023 14:48:50 +0200
Subject: [PATCH 051/155] connect wrapper around tables to the table captions
(a11y)
---
src/js/components/tableGeneral.js | 8 +++++++-
src/js/components/tableGeneralMulti.js | 2 +-
templates/techreport/drilldown.html | 16 ++++++++++++++++
.../techreport/templates/table_general.html | 4 +++-
.../techreport/templates/table_overview.html | 2 +-
5 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
index 17801ee8..21674fc6 100644
--- a/src/js/components/tableGeneral.js
+++ b/src/js/components/tableGeneral.js
@@ -14,7 +14,7 @@ class TableGeneral extends HTMLElement {
}
static get observedAttributes() {
- return ['loaded', 'labels', 'columns', 'client', 'subcategory'];
+ return ['loaded', 'labels', 'columns', 'client', 'subcategory', 'id'];
}
attributeChangedCallback(property, oldValue, newValue) {
@@ -37,6 +37,12 @@ class TableGeneral extends HTMLElement {
}
setData() {
+ /* Set the caption id and connect the wrapper to it */
+ const tableWrapper = this.shadowRoot.querySelector('.table-ui-wrapper[role="region"]');
+ const tableCaption = this.shadowRoot.querySelector('table.table-ui caption');
+ tableCaption.setAttribute('id', this.id);
+ tableWrapper.setAttribute('aria-labelledby', this.id);
+
if(this.columns) {
const _columns = this.columns.replaceAll("*subcategory*", this.subcategory)
const columns = _columns.split(",");
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index 9bfafce1..474a4a18 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -42,7 +42,7 @@ class tableGenralMulti extends HTMLElement {
const tableHead = this.shadowRoot.querySelector('table.table-ui thead tr');
const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
const tableCaption = this.shadowRoot.querySelector('table.table-ui caption');
- const tableWrapper = this.shadowRoot.querySelector('table-ui-wrapper[role="region"]');
+ const tableWrapper = this.shadowRoot.querySelector('.table-ui-wrapper[role="region"]');
/* Set the caption id and connect the wrapper to it */
tableCaption.setAttribute('id', this.id);
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 20904151..e5ea1596 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -80,7 +80,11 @@ All data
data-scope="all-data"
client="mobile"
columns="date,client,origins"
+ id="origins-over-time"
>
+
+ Adoption over time
+
@@ -106,7 +110,11 @@ All data
client="mobile"
subcategory="cwv"
columns="date,client,origins_eligible_for_*subcategory*,origins_with_good_*subcategory*,pct_good_*subcategory*"
+ id="good-cwv-over-time"
>
+
+ Good CWVs over time.
+
@@ -122,7 +130,11 @@ All data
data-scope="all-data"
client="mobile"
columns="date,client,median_lighthouse_score_accessibility,median_lighthouse_score_performance,median_lighthouse_score_pwa,median_lighthouse_score_seo,median_lighthouse_score_best_practices"
+ id="median-lighthouse-over-time"
>
+
+ Median lighthouse scores over time.
+
@@ -138,7 +150,11 @@ All data
data-scope="all-data"
client="mobile"
columns="date,client,median_bytes_image,median_bytes_js,median_bytes_total"
+ id="weight-over-time"
>
+
+ The page weight over time.
+
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
index 728bd958..d5af7d20 100644
--- a/templates/techreport/templates/table_general.html
+++ b/templates/techreport/templates/table_general.html
@@ -6,7 +6,9 @@
-
+
+
+
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
index 288cbf52..c0578261 100644
--- a/templates/techreport/templates/table_overview.html
+++ b/templates/techreport/templates/table_overview.html
@@ -6,7 +6,7 @@
- % Of tested origins that had good Core Web Vitals
+ Percentage of tested origins that had good Core Web Vitals
From c42ee167f48100751a8ce8ba71c449621c32e8da Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 21 Aug 2023 12:02:42 +0200
Subject: [PATCH 052/155] WIP: add subcategory selector to tables + listen to
changes (prototype)
---
src/js/components/tableGeneral.js | 12 ++++++++++--
templates/techreport/templates/table_general.html | 6 ++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
index 21674fc6..b64a2407 100644
--- a/src/js/components/tableGeneral.js
+++ b/src/js/components/tableGeneral.js
@@ -3,6 +3,7 @@ class TableGeneral extends HTMLElement {
super();
this.allData = [];
+ this.subcategory = '';
this.attachShadow({ mode: 'open' });
const template = document.getElementById('table-general').content.cloneNode(true);
@@ -10,6 +11,13 @@ class TableGeneral extends HTMLElement {
}
connectedCallback() {
+ /* Listen to changes on the subcategory selector */
+ const subcategorySelector = this.shadowRoot.querySelector('[name="subcategory"]');
+ subcategorySelector.addEventListener('change', (event) => {
+ this.setAttribute('subcategory', event.target.value);
+ });
+
+ /* Render the component */
this.renderComponent();
}
@@ -20,7 +28,7 @@ class TableGeneral extends HTMLElement {
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue === newValue) return;
this[ property ] = newValue;
- this.renderComponent(property);
+ this.renderComponent();
}
setTitle() {
@@ -62,7 +70,7 @@ class TableGeneral extends HTMLElement {
}
}
- renderComponent(property) {
+ renderComponent() {
this.setTitle();
this.setData();
}
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
index d5af7d20..285b0c73 100644
--- a/templates/techreport/templates/table_general.html
+++ b/templates/techreport/templates/table_general.html
@@ -2,6 +2,12 @@
+ Subcategory
+
+ CWV
+ FID
+
+
From 31b3538c38f317b6c469edd15bf486c50018589e Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 22 Aug 2023 00:52:43 +0200
Subject: [PATCH 053/155] add subcategory selector through slots
---
src/js/components/tableGeneral.js | 20 ++++++----
templates/techreport/drilldown.html | 37 ++++++++++++++++++-
.../techreport/templates/table_general.html | 6 +--
3 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
index b64a2407..03aa583b 100644
--- a/src/js/components/tableGeneral.js
+++ b/src/js/components/tableGeneral.js
@@ -11,14 +11,8 @@ class TableGeneral extends HTMLElement {
}
connectedCallback() {
- /* Listen to changes on the subcategory selector */
- const subcategorySelector = this.shadowRoot.querySelector('[name="subcategory"]');
- subcategorySelector.addEventListener('change', (event) => {
- this.setAttribute('subcategory', event.target.value);
- });
-
- /* Render the component */
this.renderComponent();
+ this.renderSubcategorySelector();
}
static get observedAttributes() {
@@ -31,6 +25,18 @@ class TableGeneral extends HTMLElement {
this.renderComponent();
}
+ renderSubcategorySelector() {
+ /* Get the subcategory slot content. */
+ const subcategorySelector = this.shadowRoot.querySelector('slot[name="subcategory-selector"]');
+
+ /* Only add event listener if subcategory slots were added. */
+ if(subcategorySelector) {
+ subcategorySelector.addEventListener('change', (event) => {
+ this.setAttribute('subcategory', event.target.value);
+ });
+ }
+ }
+
setTitle() {
const columnHeading = this.shadowRoot.querySelector('table.table-ui thead tr');
const _columns = this.columns?.replaceAll("*subcategory*", this.subcategory)
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index e5ea1596..f121d726 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -92,6 +92,7 @@ All data
Core Web Vitals
Description
+
Latest data
Explanation
@@ -115,6 +116,18 @@
All data
Good CWVs over time.
+
+ Subcategory
+
+ Overall CWVs
+ LCP
+ FID
+ CLS
+ FCP
+ TTFB
+ INP
+
+
@@ -129,12 +142,23 @@ All data
Median lighthouse scores over time.
+
+ Subcategory
+
+ Performance
+ Accessibility
+ PWA
+ SEO
+ Best practices
+
+
@@ -149,12 +173,21 @@ All data
The page weight over time.
+
+ Subcategory
+
+ Image weight
+ Javascript transfer size
+ Total page weight
+
+
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
index 285b0c73..bfdc6d62 100644
--- a/templates/techreport/templates/table_general.html
+++ b/templates/techreport/templates/table_general.html
@@ -2,11 +2,7 @@
- Subcategory
-
- CWV
- FID
-
+
From 6f135ec498c171e1f57fd65f8b70e713b72f5d97 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 23 Aug 2023 00:45:18 +0200
Subject: [PATCH 054/155] add subcategories to multi tech view
---
src/js/components/tableGeneral.js | 2 +-
src/js/components/tableGeneralMulti.js | 37 +++++++--
static/components/summary.css | 1 -
static/css/techreport/techreport.css | 1 -
templates/techreport/comparison.html | 39 +++++++++-
templates/techreport/drilldown.html | 78 ++++++++++---------
templates/techreport/templates/filters.html | 2 -
.../techreport/templates/summary_linked.html | 2 -
.../templates/table_general_multi.html | 2 +
9 files changed, 113 insertions(+), 51 deletions(-)
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
index 03aa583b..040153f8 100644
--- a/src/js/components/tableGeneral.js
+++ b/src/js/components/tableGeneral.js
@@ -39,7 +39,7 @@ class TableGeneral extends HTMLElement {
setTitle() {
const columnHeading = this.shadowRoot.querySelector('table.table-ui thead tr');
- const _columns = this.columns?.replaceAll("*subcategory*", this.subcategory)
+ const _columns = this.columns?.replaceAll("*subcategory*", this.subcategory);
const columns = _columns?.split(",");
columnHeading.innerHTML = '';
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index 474a4a18..d6cf3833 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -5,6 +5,9 @@ import { getLatestEntry } from "../utils";
* Dataset: Based on selected metric (CWV, lighthouse, etc.)
* Columns: Selected technologies.
* Rows: Time entries.
+ * TODO:
+ * - Some functionality shared with tableGeneral.js -> Merge
+ * - Clean up code and naming
*/
class tableGenralMulti extends HTMLElement {
constructor() {
@@ -14,6 +17,7 @@ class tableGenralMulti extends HTMLElement {
this.technologies = '';
this.client = 'mobile';
this.metric = 'origins';
+ this.subcategory = '';
this.attachShadow({ mode: 'open' });
const template = document.getElementById('table-general-multitech').content.cloneNode(true);
@@ -22,10 +26,11 @@ class tableGenralMulti extends HTMLElement {
connectedCallback() {
this.renderComponent();
+ this.renderSubcategorySelector();
}
static get observedAttributes() {
- return ['loaded', 'client', 'all_data', 'technologies', 'metric', 'id'];
+ return ['loaded', 'client', 'all_data', 'subcategory', 'technologies', 'metric', 'id'];
}
attributeChangedCallback(property, oldValue, newValue) {
@@ -34,6 +39,18 @@ class tableGenralMulti extends HTMLElement {
this.renderComponent();
}
+ renderSubcategorySelector() {
+ /* Get the subcategory slot content. */
+ const subcategorySelector = this.shadowRoot.querySelector('slot[name="subcategory-selector"]');
+
+ /* Only add event listener if subcategory slots were added. */
+ if(subcategorySelector) {
+ subcategorySelector.addEventListener('change', (event) => {
+ this.setAttribute('subcategory', event.target.value);
+ });
+ }
+ }
+
setData() {
/* Turn the techs into an array */
const technologies = this.technologies?.split(",");
@@ -79,7 +96,7 @@ class tableGenralMulti extends HTMLElement {
/* Add a row to the table body for each of the time entries */
_dates.forEach(date => {
/* Select the needed templates */
- const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true);
+ const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true).querySelector('tr');
const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
/* Fill in the dates */
@@ -89,14 +106,22 @@ class tableGenralMulti extends HTMLElement {
/* For each of the technologies, select the chosen metric for the given date */
technologies.forEach(technology => {
const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
- const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client)?.find(row => row.date = date);
+ const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client)?.find(row => row.date === date);
+ const metric = this.metric?.replaceAll("*subcategory*", this.subcategory);
+
+ let cellContent;
+ if(_data && _data[metric]) {
+ cellContent = `${_data[metric]}${this.getAttribute('data-unit') || ''}`;
+ } else {
+ cellContent = '-';
+ }
- dataCellTemplate.querySelector('td').textContent = _data ? _data[this.metric] : '-';
- rowTemplate.append(dataCellTemplate);
+ dataCellTemplate.querySelector('td').textContent = cellContent;
+ rowTemplate.appendChild(dataCellTemplate);
});
/* Append the row to the table */
- tableBody.append(rowTemplate);
+ tableBody.appendChild(rowTemplate);
});
}
diff --git a/static/components/summary.css b/static/components/summary.css
index 659e0b57..68d63e84 100644
--- a/static/components/summary.css
+++ b/static/components/summary.css
@@ -1,4 +1,3 @@
-
.summary-linked-label {
font-weight: 600;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index c758b970..ebe192aa 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -231,7 +231,6 @@ button#add-tech {
row-gap: 1rem;
}
-
/* Timeseries cards */
.timeseries-container {
margin-top: 2rem;
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 3682c90c..43f01b9a 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -71,14 +71,28 @@ Good Core Web Vitals
Explanation
The amount of good core web vitals over time, compared for the selected technologies.
+
+ Subcategory
+
+ Overall CWVs
+ LCP
+ FID
+ CLS
+ FCP
+ TTFB
+ INP
+
+
@@ -94,12 +108,23 @@ Median Lighthouse Performance
data-scope="all-data"
client="mobile"
technologies="{{ technologies_str }}"
- metric="median_lighthouse_score_performance"
+ metric="median_lighthouse_score_*subcategory*"
+ subcategory="performance"
id="lighthouse-over-time"
>
The lighthouse scores over time, compared for the selected technologies.
+
+ Subcategory
+
+ Performance
+ Accessibility
+ PWA
+ SEO
+ Best practices
+
+
@@ -113,14 +138,22 @@ Median bytes total
Explanation
The page weight over time, compared for the selected technologies.
+ Subcategory
+
+ Image weight
+ Javascript transfer size
+ Total page weight
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index f121d726..7739ccc7 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -31,41 +31,49 @@
Summary
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 3d8cb704..a80c2a90 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -25,8 +25,6 @@
ALL
-
-
Rank
diff --git a/templates/techreport/templates/summary_linked.html b/templates/techreport/templates/summary_linked.html
index cb9f0e18..06477784 100644
--- a/templates/techreport/templates/summary_linked.html
+++ b/templates/techreport/templates/summary_linked.html
@@ -2,7 +2,6 @@
-
Label
@@ -12,5 +11,4 @@
Description
-
diff --git a/templates/techreport/templates/table_general_multi.html b/templates/techreport/templates/table_general_multi.html
index 90e669d7..bf2f51dd 100644
--- a/templates/techreport/templates/table_general_multi.html
+++ b/templates/techreport/templates/table_general_multi.html
@@ -2,6 +2,8 @@
+
+
From 5930b45d7ab38d31e80681c18d2afd718cecc836 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 23 Aug 2023 11:28:30 +0200
Subject: [PATCH 055/155] add units
---
src/js/components/tableGeneralMulti.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index d6cf3833..634e55ad 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -111,7 +111,8 @@ class tableGenralMulti extends HTMLElement {
let cellContent;
if(_data && _data[metric]) {
- cellContent = `${_data[metric]}${this.getAttribute('data-unit') || ''}`;
+ const value = _data[metric];
+ cellContent = `${value}${this.getAttribute('data-unit') || ''}`;
} else {
cellContent = '-';
}
From 9e1046e468a7844fbb95daf0c964a11ea933b1d3 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 23 Aug 2023 14:40:54 +0200
Subject: [PATCH 056/155] bugfix: remember filters when drilling down form
multitech view
---
src/js/components/tableCWVOverviewMulti.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/js/components/tableCWVOverviewMulti.js b/src/js/components/tableCWVOverviewMulti.js
index 36166965..413ef2c8 100644
--- a/src/js/components/tableCWVOverviewMulti.js
+++ b/src/js/components/tableCWVOverviewMulti.js
@@ -77,12 +77,18 @@ class tableCWVOverviewMulti extends HTMLElement {
});
const _latest = getLatestEntry(_clientDataSorted);
+ /* Get the filters from the URL */
+ const url = window.location.search;
+ const parameters = new URLSearchParams(url);
+ const geo = parameters.get('geo') || 'ALL';
+ const rank = parameters.get('rank') || 'ALL';
+
/* Fill in the tech names as row headings */
const row = document.createElement('tr');
const headingCell = document.createElement('th');
const technologyLinkEl = document.createElement('a');
technologyLinkEl.className = 'row-link';
- technologyLinkEl.href = `/reports/techreport/drilldown/?tech=${technology}`;
+ technologyLinkEl.href = `/reports/techreport/drilldown/?tech=${technology}&geo=${geo}&rank=${rank}`;
technologyLinkEl.innerHTML = technology;
headingCell.append(technologyLinkEl);
row.append(headingCell);
From 955bd7b990d4aa2ff93eae4a2a50207f8350366b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 6 Sep 2023 14:41:14 +0200
Subject: [PATCH 057/155] WIP - add graphs and toggle, category dropdown, and
update url on subcategory selection
---
CWV_TECH_REPORT.md | 22 +++
config/techreport.json | 110 ++++++++++--
server/routes.py | 2 +
src/js/components/filters.js | 23 +++
src/js/components/tableGeneral.js | 3 +
src/js/components/tableGeneralMulti.js | 3 +
src/js/techreport.js | 29 ++-
src/js/techreport/index.js | 0
src/js/techreport/timeseries.js | 167 ++++++++++++++++++
static/css/techreport/techreport.css | 7 +
templates/techreport/comparison.html | 59 ++++---
templates/techreport/components/card.html | 0
.../techreport/components/timeseries.html | 31 ++++
templates/techreport/drilldown.html | 83 +++++----
templates/techreport/techreport.html | 7 +
templates/techreport/templates/filters.html | 4 +-
.../techreport/templates/selector_tech.html | 16 +-
.../techreport/templates/table_general.html | 1 +
tools/generate/generate_js.js | 4 +
19 files changed, 484 insertions(+), 87 deletions(-)
create mode 100644 CWV_TECH_REPORT.md
create mode 100644 src/js/techreport/index.js
create mode 100644 src/js/techreport/timeseries.js
create mode 100644 templates/techreport/components/card.html
create mode 100644 templates/techreport/components/timeseries.html
diff --git a/CWV_TECH_REPORT.md b/CWV_TECH_REPORT.md
new file mode 100644
index 00000000..1f45b4e3
--- /dev/null
+++ b/CWV_TECH_REPORT.md
@@ -0,0 +1,22 @@
+# CWV Tech Report
+
+## Structure
+
+### HTML
+
+All the HTML files are located in the `templates/techreport` folder. The top level files in that folder are the main pages that will be rendered. The `components` subfolder contains reusable bits of HTML that can be included in the pages and templates. The `templates` subfolder contains ``s used in (web)components.
+
+```
+/templates
+ /techreport
+ /components
+ filters.html
+ ...
+ /templates
+ table_general.html
+ ...
+ comparison.html
+ drilldown.html
+ landing.html
+ ...
+```
diff --git a/config/techreport.json b/config/techreport.json
index c18c1ae2..ac6b64d1 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -133,29 +133,103 @@
"default": {
"app": ["ALL"]
},
- "good_cwv_timeseries": {
- "columns": [
- {
- "key": "date",
- "label": "Date"
+ "adoption_timeseries": {
+ "title": "All usage",
+ "description": "Placeholder",
+ "id": "adoption_timeseries",
+ "table": {
+ "columns": "date,client,origins"
+ },
+ "viz": {
+ "title": "Origins over time",
+ "metric": "origins",
+ "series": {
+ "breakdown": "client",
+ "values": ["desktop", "mobile"],
+ "defaults": [
+ {
+ "name": "Desktop origins",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "Mobile origins",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
},
- {
- "key": "client",
- "label": "Client"
+ "xAxis": {
+ "title": "Months",
+ "description": "accessibility description of x-axis",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
},
- {
- "key": "origins_eligible_for_*subcategory*",
- "label": "Eligible"
+ "yAxis": {
+ "title": "Origins",
+ "tickAmount": 3
+ }
+ }
+ },
+ "good_cwv_timeseries": {
+ "title": "Good Core Web Vitals over time",
+ "description": "Placeholder - combination of several metrics",
+ "id": "good_cwv_timeseries",
+ "table": {
+ "columns": "date,client,origins_eligible_for_*subcategory*,origins_with_good_*subcategory*,pct_good_*subcategory*"
+ },
+ "viz": {
+ "title": "Overall good CWVs over time",
+ "metric": "pct_good_cwv",
+ "height": 600,
+ "series": {
+ "breakdown": "client",
+ "values": ["desktop", "mobile"],
+ "defaults": [
+ {
+ "name": "Desktop origins",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "Mobile origins",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
},
- {
- "key": "origins_with_good_*subcategory*",
- "label": "Have good values"
+ "xAxis": {
+ "title": "Months",
+ "description": "accessibility description of x-axis",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
},
- {
- "key": "pct_good_*subcategory*",
- "label": "% With good values"
+ "yAxis": {
+ "title": "% Good CWVs"
}
- ]
+ }
}
}
},
diff --git a/server/routes.py b/server/routes.py
index 5ce224f5..a1a99bae 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -100,6 +100,8 @@ def techreport(page_id):
active_tech_report["filters"] = filters
+ print('active_tech_report', active_tech_report)
+
return render_template(
"techreport/%s.html" % page_id,
active_page=page_id,
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 401b823b..e1e902f7 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -65,6 +65,28 @@ function updateRank(ranks, filters) {
});
}
+function updateCategories(categories, filters) {
+ const select = document.querySelector('select#categories');
+
+ if(categories) {
+ select.innerHTML = '';
+
+ const all = document.createElement('option');
+ all.value = 'ALL';
+ all.innerHTML = 'ALL';
+ select.append(all);
+
+
+ Object.keys(categories).forEach((category) => {
+ const option = document.createElement('option');
+ option.value = category;
+ option.innerHTML = category;
+ select.append(option);
+ });
+
+ }
+}
+
function bindFilterListener() {
const submit = document.getElementById('submit-form');
if(submit) {
@@ -170,4 +192,5 @@ export const Filters = {
updateTechnologies,
updateGeo,
updateRank,
+ updateCategories,
}
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
index 040153f8..b445eda4 100644
--- a/src/js/components/tableGeneral.js
+++ b/src/js/components/tableGeneral.js
@@ -33,6 +33,9 @@ class TableGeneral extends HTMLElement {
if(subcategorySelector) {
subcategorySelector.addEventListener('change', (event) => {
this.setAttribute('subcategory', event.target.value);
+ const url = new URL(window.location.href);
+ url.searchParams.set(this.id, event.target.value);
+ window.history.replaceState(null, null, url);
});
}
}
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
index 634e55ad..cc91409e 100644
--- a/src/js/components/tableGeneralMulti.js
+++ b/src/js/components/tableGeneralMulti.js
@@ -47,6 +47,9 @@ class tableGenralMulti extends HTMLElement {
if(subcategorySelector) {
subcategorySelector.addEventListener('change', (event) => {
this.setAttribute('subcategory', event.target.value);
+ const url = new URL(window.location.href);
+ url.searchParams.set(this.id, event.target.value);
+ window.history.replaceState(null, null, url);
});
}
}
diff --git a/src/js/techreport.js b/src/js/techreport.js
index a9cecad9..a3c28e48 100644
--- a/src/js/techreport.js
+++ b/src/js/techreport.js
@@ -1,5 +1,6 @@
const { DrilldownHeader } = require("./components/drilldownHeader");
const { Filters } = require("./components/filters");
+const { Timeseries } = require("./techreport/timeseries");
const { getPercentage } = require("./utils");
class TechReport {
@@ -15,17 +16,31 @@ class TechReport {
this.getAllData();
Filters.bindFilterListener();
+ Timeseries.init(this.page, this.filters);
}
bindClientListener() {
const select = document.getElementById('client-breakdown');
+ const allDataComponents = document.querySelectorAll('[data-scope]');
+
if(select) {
select.onchange = (event) => {
const client = event.target.value;
- const allDataComponents = document.querySelectorAll('[data-scope]');
- allDataComponents.forEach(component => {
- component.setAttribute('client', client);
- });
+
+ allDataComponents.forEach(component => {
+ component.setAttribute('client', client);
+ });
+
+ this.filters = {
+ ...this.filters,
+ client: client
+ };
+
+ Timeseries.updateFilters(this.allData, this.filters);
+
+ const url = new URL(window.location.href);
+ url.searchParams.set(`client`, client);
+ window.history.replaceState(null, null, url);
}
}
}
@@ -58,6 +73,7 @@ class TechReport {
})
.catch(error => console.log('Something went wrong', error));
})).then(() => {
+ this.allData = data;
this.updateComponents(data);
});
}
@@ -74,6 +90,10 @@ class TechReport {
fetch('https://cdn.httparchive.org/reports/cwvtech/ranks.json')
.then(result => result.json())
.then(result => Filters.updateRank(result, this.filters));
+
+ fetch('https://cdn.httparchive.org/reports/cwvtech/categories.json')
+ .then(result => result.json())
+ .then(result => Filters.updateCategories(result, this.filters));
}
updateComponents(data) {
@@ -111,6 +131,7 @@ class TechReport {
const app = this.filters.app[0];
if(data && data[app]) {
+ Timeseries.updateData(data);
const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
latestComponents.forEach((component) => {
component.latest = data[app][0];
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
new file mode 100644
index 00000000..303bddad
--- /dev/null
+++ b/src/js/techreport/timeseries.js
@@ -0,0 +1,167 @@
+let pageConfig;
+let pageFilters;
+
+const colors = ['#04c7fd', '#a62aa4'];
+
+function init(page, filters) {
+ pageConfig = page.config;
+ pageFilters = filters;
+
+ updateAllComponents();
+ bindToggleButtons();
+}
+
+function bindToggleButtons() {
+ const buttons = Object.values(document.getElementsByClassName('show-table'));
+ buttons.forEach(button => {
+ button.addEventListener('click', toggleButton);
+ });
+}
+
+function toggleButton(event) {
+ const button = event.target;
+ const tableWrapper = document.getElementById(`${button.dataset.id}-table-wrapper`);
+ if(tableWrapper.classList.contains('hidden')) {
+ button.innerHTML = 'Hide table';
+ tableWrapper.classList.remove('hidden');
+ } else {
+ button.innerHTML = 'Show table';
+ tableWrapper.classList.add('hidden');
+ }
+}
+
+function updateData(data) {
+ updateAllComponents(data);
+}
+
+function updateAllComponents(data) {
+ const timeseries = document.querySelectorAll('[data-component="timeseries"]');
+ Array.from(timeseries).forEach(component => updateComponent(component, data));
+}
+
+function updateComponent(component, data) {
+ const id = component.dataset.id;
+ const config = pageConfig[id].viz;
+
+ drawViz(id, config, data);
+}
+
+function drawViz(id, config, data) {
+ const timeseries = defaults(config);
+
+ /* Accessibility configs */
+ if(config.caption) {
+ timeseries.caption = {
+ text: config.caption,
+ };
+ }
+
+ if(pageConfig[id].valueSuffix) {
+ timeseries.accessibility.point = {
+ ...timeseries.accessibility.point,
+ 'valueSuffix': pageConfig[id].valueSuffix,
+ }
+ }
+
+ /* Chart styling configs */
+ timeseries.chart = {
+ ...timeseries.chart,
+ height: config.height,
+ };
+
+ console.log(timeseries.chart);
+
+ /* Axis styling */
+ timeseries.yAxis = {
+ ...timeseries.yAxis,
+ tickAmount: config.yAxis.tickAmount,
+ }
+
+ timeseries.xAxis = {
+ ...timeseries.xAxis,
+ tickAmount: config.xAxis.tickAmount,
+ }
+
+ /* Set the data */
+ if(data) {
+ timeseries.series = getSeries(data, config);
+ timeseries.xAxis.categories = getCategories(data, config);
+ }
+
+ /* Render the chart */
+ Highcharts.chart(`${id}-timeseries`, timeseries);
+}
+
+function getCategories(data, config) {
+ const app = pageFilters.app[0];
+ const dates = [];
+ const sorted = data[app].sort((a, b) => new Date(a.date) - new Date(b.date));
+ sorted.forEach(entry => dates.push(entry.date));
+ return dates;
+}
+
+function getSeries(data, config) {
+ const series = [];
+ const app = pageFilters.app[0];
+ if(config.series.breakdown === 'client') {
+ config.series.values.forEach((value, index) => {
+ const filteredData = data[app].filter(entry => entry.client === value);
+ filteredData.sort((a, b) => new Date(a.date) - new Date(b.date));
+
+ const formattedData = [];
+ filteredData.forEach(row => formattedData.push(Number(row[config.metric])));
+
+ series.push(
+ {
+ name: value,
+ data: formattedData,
+ color: colors[index],
+ }
+ )
+ });
+ }
+
+ return series;
+}
+
+function defaults(config) {
+ const defaults = {
+ type: 'timeseries',
+ chart: {
+ colors: ['#070746', '#157F56', '#C9200D', '#AA0DC9'],
+ },
+ title: {
+ text: config.title,
+ },
+ accessibility: {},
+ series: config.series.defaults,
+ xAxis: {
+ title: {
+ text: config.xAxis.title,
+ },
+ categories: config.xAxis.defaults,
+ },
+ yAxis: {
+ title: {
+ text: config.yAxis.title,
+ },
+ },
+ };
+
+ return defaults;
+}
+
+function updateFilters(data, filters) {
+ /* Filters get saved so other functions have access to it*/
+ pageFilters = filters;
+
+ updateAllComponents(data);
+}
+
+
+export const Timeseries = {
+ init,
+ updateAllComponents,
+ updateData,
+ updateFilters,
+};
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index ebe192aa..d3550db3 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -346,6 +346,13 @@ button#add-tech {
max-width: 50rem;
}
+.highcharts-title {
+ font-weight: normal !important;
+ fill: var(--color-text) !important;
+ font-family: "Open Sans", sans-serif !important;
+ font-size: 0.875rem !important;
+}
+
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 43f01b9a..0469de58 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -22,8 +22,8 @@
Client
- Mobile
- Desktop
+ Mobile
+ Desktop
@@ -34,7 +34,7 @@ Comparing {{ technologies | length }} technologies
@@ -50,7 +50,7 @@ Origins
Explanation
Good Core Web Vitals
@@ -84,13 +84,13 @@ Good Core Web Vitals
Subcategory
- Overall CWVs
- LCP
- FID
- CLS
- FCP
- TTFB
- INP
+ Overall CWVs
+ LCP
+ FID
+ CLS
+ FCP
+ TTFB
+ INP
@@ -106,11 +106,11 @@ Median Lighthouse Performance
Explanation
The lighthouse scores over time, compared for the selected technologies.
@@ -118,11 +118,11 @@ Median Lighthouse Performance
Subcategory
- Performance
- Accessibility
- PWA
- SEO
- Best practices
+ Performance
+ Accessibility
+ PWA
+ SEO
+ Best practices
@@ -139,21 +139,24 @@ Median bytes total
The page weight over time, compared for the selected technologies.
Subcategory
-
- Image weight
- Javascript transfer size
- Total page weight
-
+
+ Subcategory
+
+ Image weight
+ Javascript transfer size
+ Total page weight
+
+
diff --git a/templates/techreport/components/card.html b/templates/techreport/components/card.html
new file mode 100644
index 00000000..e69de29b
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
new file mode 100644
index 00000000..bfe88ec9
--- /dev/null
+++ b/templates/techreport/components/timeseries.html
@@ -0,0 +1,31 @@
+
+
{{ timeseries.title }}
+
{{ timeseries.description }}
+
+ {% if timeseries.summary %}
+
+ {% endif %}
+
+
+
+
+
Show table
+
+
+
+
+ {{ timeseries.title }}
+
+
+
+
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 7739ccc7..254790d3 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -22,8 +22,8 @@
Client
- Mobile
- Desktop
+ Mobile
+ Desktop
@@ -37,7 +37,7 @@ Summary
link="#adoption"
key="origins"
data-scope="all-data"
- client="mobile"
+ client="{{ request.args.get('client', '') or 'mobile' }}"
>
@@ -48,7 +48,7 @@ Summary
link="#good-cwvs"
key="origins_with_good_cwv"
data-scope="all-data"
- client="mobile"
+ client="{{ request.args.get('client', '') or 'mobile' }}"
>
@@ -59,7 +59,7 @@ Summary
link="#lighthouse"
key="median_lighthouse_score_performance"
data-scope="all-data"
- client="mobile"
+ client="{{ request.args.get('client', '') or 'mobile' }}"
>
@@ -70,7 +70,7 @@ Summary
link="#page-weight"
key="median_bytes_total"
data-scope="all-data"
- client="mobile"
+ client="{{ request.args.get('client', '') or 'mobile' }}"
>
@@ -80,13 +80,22 @@ Summary
Adoption
Description
-
+ {% set timeseries = tech_report_page.config.adoption_timeseries %}
+ {% include "techreport/components/timeseries.html" %}
+
+
+
@@ -106,18 +115,19 @@
Latest data
Explanation
-
+
+
+
+ {% set timeseries = tech_report_page.config.good_cwv_timeseries %}
+ {% set subcategory = request.args.get('good-cwv-over-time', '') or 'cwv' %}
+ {% include "techreport/components/timeseries.html" %}
@@ -147,11 +163,12 @@ Lighthouse
All data
Explanation
+
@@ -160,11 +177,11 @@ All data
Subcategory
- Performance
- Accessibility
- PWA
- SEO
- Best practices
+ Performance
+ Accessibility
+ PWA
+ SEO
+ Best practices
@@ -178,12 +195,14 @@
Page weight
All data
Explanation
+
The page weight over time.
@@ -191,9 +210,9 @@ All data
Subcategory
- Image weight
- Javascript transfer size
- Total page weight
+ Image weight
+ Javascript transfer size
+ Total page weight
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 608c5a84..676c9642 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -74,6 +74,12 @@
{% block scripts %}
{{ super() }}
+
+
+
+
+
+
@@ -83,6 +89,7 @@
+
-
+
+
+
-
+
-
+
+
diff --git a/templates/techreport/templates/summary_linked.html b/templates/techreport/templates/summary_linked.html
deleted file mode 100644
index 4ce17af2..00000000
--- a/templates/techreport/templates/summary_linked.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
- Label
-
-
- Value
-
-
-
-
-
- Description
-
-
From 74b1ae24dccd492dc7b36ec4ef42f7b643852a5f Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 26 Sep 2023 02:59:28 +0200
Subject: [PATCH 065/155] update summary on client select
---
config/techreport.json | 7 +++
src/js/techreport/index.js | 13 +----
src/js/techreport/section.js | 56 +++++++++++++++----
src/js/techreport/summaryCards.js | 50 +++++++++++++----
.../techreport/components/summary_card.html | 7 ++-
templates/techreport/drilldown.html | 13 ++++-
6 files changed, 111 insertions(+), 35 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 2b1d0244..6e7d6406 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -163,6 +163,13 @@
"description": "Median lighthouse performance score across tested origins.",
"url": "#lighthouse"
},
+ {
+ "metric": "median_lighthouse_score_accessibility",
+ "label": "Lighthouse accessibility",
+ "suffix": "",
+ "description": "Median lighthouse accessibility score across tested origins.",
+ "url": "#lighthouse&median-lighthouse-over-time=accessibility"
+ },
{
"metric": "median_bytes_total",
"label": "Page weight",
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index daf2d649..80c7cd1c 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -70,7 +70,9 @@ class TechReport {
client: client
};
- // Timeseries.updateFilters(this.page.config, this.filters, this.allData);
+ Object.values(this.sections).forEach(section => {
+ section.updateActiveClient(client);
+ });
const url = new URL(window.location.href);
url.searchParams.set(`client`, client);
@@ -188,17 +190,8 @@ class TechReport {
section.updateSection();
});
- SummaryCards.updateCards(data[app]);
-
// Update web components
// TODO: Change to same system as sections/timeseries
- const latestComponents = document.querySelectorAll('[data-scope="all-latest"]');
- latestComponents.forEach((component) => {
- component.latest = data[app][0];
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- });
-
const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
allDataComponents.forEach((component) => {
component.allData = data[app];
diff --git a/src/js/techreport/section.js b/src/js/techreport/section.js
index 1be1a4f1..32cdec81 100644
--- a/src/js/techreport/section.js
+++ b/src/js/techreport/section.js
@@ -1,33 +1,69 @@
+import SummaryCard from "./summaryCards";
+
class Section {
constructor(id, config, filters, data) {
this.id = id;
this.data = data;
this.pageConfig = config;
this.pageFilters = filters;
- this.timeseries = {};
+ this.components = {};
this.initializeComponents();
}
initializeComponents() {
const section = document.getElementById(this.id);
- const timeseriesComponents = section.querySelectorAll('[data-component="timeseries"]');
- Object.values(timeseriesComponents).forEach(component => {
- this.timeseries[component.dataset.id] = new Timeseries(
- component.dataset.id,
- this.pageConfig,
- this.pageFilters,
- this.data
- );
+
+ // Initialize components
+ section.querySelectorAll('[data-component]').forEach(component => {
+ switch(component.dataset.component) {
+ case "timeseries":
+ this.initializeTimeseries(component);
+ break;
+
+ case "summaryCard":
+ this.initializeSummaryCards(component);
+ break;
+
+ default:
+ break;
+ }
});
}
+ initializeSummaryCards(component) {
+ this.components[component.dataset.id] = new SummaryCard(
+ component.dataset.id,
+ this.pageConfig,
+ this.pageFilters,
+ this.data
+ );
+ }
+
+ initializeTimeseries(component) {
+ this.components[component.dataset.id] = new Timeseries(
+ component.dataset.id,
+ this.pageConfig,
+ this.pageFilters,
+ this.data
+ );
+ }
+
updateSection() {
- Object.values(this.timeseries).forEach(component => {
+ Object.values(this.components).forEach(component => {
component.data = this.data;
component.updateContent();
});
}
+
+ updateActiveClient(client) {
+ Object.values(this.components).forEach(component => {
+ if(component.client) {
+ component.client = client;
+ component.updateContent();
+ }
+ });
+ }
}
window.Section = Section;
diff --git a/src/js/techreport/summaryCards.js b/src/js/techreport/summaryCards.js
index a07c4797..887f9a58 100644
--- a/src/js/techreport/summaryCards.js
+++ b/src/js/techreport/summaryCards.js
@@ -1,15 +1,41 @@
-function updateCards(data) {
- console.log('data', data);
- const cards = document.querySelectorAll('[data-component="summaryCard"');
- cards.forEach(card => {
- const metric = card.dataset.metric;
- const value = data[0][metric];
- if(value) {
- card.querySelector('[data-slot="value"]').innerHTML = value;
+/* Summary cards.
+ * Show static values for given metrics.
+ */
+
+class SummaryCard {
+ constructor(id, config, filters, data) {
+ this.data = data;
+ this.id = id;
+ this.pageConfig = config;
+ this.pageFilters = filters;
+ this.client = 'mobile'; //TODO: get default from config
+ }
+
+ updateContent() {
+ if(this.data) {
+ // Select the HTML element that corresponds with this card
+ const query = `[data-component="summaryCard"][data-id="${this.id}"]`;
+ const card = document.querySelector(query);
+
+ // Get the latest data for the selected app/tech
+ const app = this.pageFilters.app[0];
+ const client = this.client;
+
+ const filteredData = this.data?.[app]?.filter(entry => entry.client === client);
+ filteredData?.sort((a, b) => new Date(b.date) - new Date(a.date));
+ const latest = filteredData[0];
+
+ // Select value based on a pre-defined metric
+ const metric = card.dataset.metric;
+ const value = latest[metric];
+
+ if(value) {
+ card.querySelector('[data-slot="value"]').innerHTML = value;
+ }
}
- });
-}
-export const SummaryCards = {
- updateCards,
+ }
+
}
+
+export default SummaryCard;
diff --git a/templates/techreport/components/summary_card.html b/templates/techreport/components/summary_card.html
index 7395fb49..4b58683f 100644
--- a/templates/techreport/components/summary_card.html
+++ b/templates/techreport/components/summary_card.html
@@ -1,4 +1,9 @@
-
+
{{ summary.label }}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index d2d6b0c1..b1d93f6b 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -27,8 +27,13 @@
-
-
+
+
Summary
{% for summary in tech_report_page.config.summary %}
@@ -42,6 +47,7 @@
Summary
id="good-cwvs"
class="block-m report-section"
data-type="section"
+ data-api="cwv"
>
Core Web Vitals
Description
@@ -58,6 +64,7 @@
Core Web Vitals
id="lighthouse"
class="block-m report-section"
data-type="section"
+ data-api="lighthouse"
>
Lighthouse
Description
@@ -74,6 +81,7 @@
Lighthouse
id="page-weight"
class="block-m report-section"
data-type="section"
+ data-api="page-weight"
>
Page weight
Description
@@ -89,6 +97,7 @@
Page weight
id="adoption"
class="block-m report-section"
data-type="section"
+ data-api="adoption"
>
Adoption
Description
From e4854f5375dfdcc16f6ad15af9c637d77f3eb19e Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Sep 2023 02:54:35 +0200
Subject: [PATCH 066/155] clean up card components + bug fixes
---
src/js/techreport/index.js | 58 ++++++++++++-------
src/js/techreport/section.js | 13 +----
src/js/techreport/summaryCards.js | 4 +-
.../techreport/components/summary_card.html | 4 ++
templates/techreport/drilldown.html | 4 ++
5 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 80c7cd1c..17b60e3d 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -55,32 +55,48 @@ class TechReport {
// Watch for changes in the client dropdown
bindClientListener() {
const select = document.getElementById('client-breakdown');
- const allDataComponents = document.querySelectorAll('[data-scope]');
if(select) {
- select.onchange = (event) => {
- const client = event.target.value;
-
- allDataComponents.forEach(component => {
- component.setAttribute('client', client);
- });
-
- this.filters = {
- ...this.filters,
- client: client
- };
-
- Object.values(this.sections).forEach(section => {
- section.updateActiveClient(client);
- });
-
- const url = new URL(window.location.href);
- url.searchParams.set(`client`, client);
- window.history.replaceState(null, null, url);
- }
+ select.onchange = (event) => this.updateClient(event);
}
}
+ updateClient(event) {
+ const client = event.target.value;
+
+ // Update web components
+ document.querySelectorAll('[data-scope]').forEach(component => {
+ component.setAttribute('client', client);
+ });
+
+ // Update the filters object
+ this.filters = {
+ ...this.filters,
+ client: client
+ };
+
+ // Update the URL
+ const url = new URL(window.location.href);
+ url.searchParams.set(`client`, client);
+ window.history.replaceState(null, null, url);
+
+ // Update selected client property everywhere
+ document.querySelectorAll('[data-client]').forEach(component => {
+ component.dataset.client = client;
+ });
+
+ // Update the sections
+ Object.values(this.sections).forEach(section => {
+ section.updateSection();
+ });
+
+ // Update labels
+ document.querySelectorAll('[data-slot="client"]').forEach(component => {
+ component.innerHTML = client;
+ })
+
+ }
+
// Fetch all the data based on search criteria and config
// TODO: Will be moved to the section level with new APIs
getAllData() {
diff --git a/src/js/techreport/section.js b/src/js/techreport/section.js
index 32cdec81..46e82900 100644
--- a/src/js/techreport/section.js
+++ b/src/js/techreport/section.js
@@ -51,17 +51,10 @@ class Section {
updateSection() {
Object.values(this.components).forEach(component => {
- component.data = this.data;
- component.updateContent();
- });
- }
-
- updateActiveClient(client) {
- Object.values(this.components).forEach(component => {
- if(component.client) {
- component.client = client;
- component.updateContent();
+ if(component.data !== this.data) {
+ component.data = this.data;
}
+ component.updateContent();
});
}
}
diff --git a/src/js/techreport/summaryCards.js b/src/js/techreport/summaryCards.js
index 887f9a58..2aa42178 100644
--- a/src/js/techreport/summaryCards.js
+++ b/src/js/techreport/summaryCards.js
@@ -19,8 +19,7 @@ class SummaryCard {
// Get the latest data for the selected app/tech
const app = this.pageFilters.app[0];
- const client = this.client;
-
+ const client = card.dataset.client || this.client;
const filteredData = this.data?.[app]?.filter(entry => entry.client === client);
filteredData?.sort((a, b) => new Date(b.date) - new Date(a.date));
const latest = filteredData[0];
@@ -29,6 +28,7 @@ class SummaryCard {
const metric = card.dataset.metric;
const value = latest[metric];
+ // Update the html
if(value) {
card.querySelector('[data-slot="value"]').innerHTML = value;
}
diff --git a/templates/techreport/components/summary_card.html b/templates/techreport/components/summary_card.html
index 4b58683f..8a885a9d 100644
--- a/templates/techreport/components/summary_card.html
+++ b/templates/techreport/components/summary_card.html
@@ -3,6 +3,7 @@
data-component="summaryCard"
data-metric="{{ summary.metric }}"
data-id="summary-{{ summary.metric }}"
+ data-client="{{ request.args.get('client', '') or 'mobile' }}"
>
{{ summary.label }}
@@ -14,4 +15,7 @@
{{ summary.description }}
+
+ Client: Mobile
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index b1d93f6b..db2f45c1 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -35,6 +35,7 @@
data-api="cwv,lighthouse,page-weight"
>
Summary
+ Based on the latest data.
{% for summary in tech_report_page.config.summary %}
{% include "techreport/components/summary_card.html" %}
@@ -56,6 +57,9 @@
Core Web Vitals
{% set timeseries = tech_report_page.config.good_cwv_timeseries %}
{% set subcategory = request.args.get('good-cwv-over-time', '') or 'cwv' %}
{% include "techreport/components/timeseries.html" %}
+
+ Client: Mobile
+
From 33a8b1c824e9bd0331e25a64c78e4da21d0175bd Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Sep 2023 03:14:24 +0200
Subject: [PATCH 067/155] style client in summary card
---
src/js/techreport/index.js | 9 +-
static/css/techreport/techreport.css | 133 ++++++++++--------
.../techreport/components/summary_card.html | 2 +-
.../techreport/components/timeseries.html | 3 +
templates/techreport/drilldown.html | 4 -
5 files changed, 80 insertions(+), 71 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 17b60e3d..1624ca40 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -37,7 +37,6 @@ class TechReport {
// TODO
initializeLanding() {
-
}
// TODO
@@ -69,18 +68,12 @@ class TechReport {
component.setAttribute('client', client);
});
- // Update the filters object
- this.filters = {
- ...this.filters,
- client: client
- };
-
// Update the URL
const url = new URL(window.location.href);
url.searchParams.set(`client`, client);
window.history.replaceState(null, null, url);
- // Update selected client property everywhere
+ // Update selected client property ever
document.querySelectorAll('[data-client]').forEach(component => {
component.dataset.client = client;
});
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 42b0d38b..889615d3 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -34,56 +34,11 @@
--graph-color-labels: #62777B;
}
-/* Page heading */
-.intro {
- border: none;
- margin-top: 0;
- background-color: transparent;
- padding: 4rem 0;
-}
-
-.intro h1 {
- font-size: var(--font-size-xlarge);
- margin-bottom: 2.5rem;
- margin-top: 0;
-}
-
-.intro h1 span.subtitle {
- font-size: 1.15rem;
- display: block;
- margin-bottom: 0.5rem;
-}
-
-.intro p {
- font-size: 1.15rem;
- max-width: 45rem;
-}
-
-.intro h1 + p {
- padding: 0;
-}
-
-.intro ul {
- padding-left: 0;
- margin-left: 0;
-}
-
-/* Categories */
-.categories {
- margin: 1rem 0;
-}
+/* ------------------------- */
+/* ---- Building blocks ---- */
+/* ------------------------- */
-.categories .cell {
- display: inline-block;
- padding: 0.25rem 0.75rem;
- border-radius: 1rem;
- border: 1px solid var(--color-text);
- font-size: 0.875rem;
- margin-bottom: 0.5rem;
-}
-
-
-/* Building blocks */
+/* CTA */
.cta-link {
background-color: var(--color-teal-dark);
color: var(--color-text-inverted);
@@ -111,6 +66,16 @@
margin-top: 1rem;
}
+/* Filter info */
+p.meta {
+ font-size: 0.75rem;
+ color: var(--color-text-lighter);
+}
+
+p.meta span {
+ font-weight: 600;
+}
+
/* -------------------- */
/* ---- Components ---- */
/* -------------------- */
@@ -280,11 +245,58 @@ button#add-tech {
}
-
/* -------------------- */
/* ----- Sections ----- */
/* -------------------- */
+/* Page heading */
+.intro {
+ border: none;
+ margin-top: 0;
+ background-color: transparent;
+ padding: 4rem 0;
+}
+
+.intro h1 {
+ font-size: var(--font-size-xlarge);
+ margin-bottom: 2.5rem;
+ margin-top: 0;
+}
+
+.intro h1 span.subtitle {
+ font-size: 1.15rem;
+ display: block;
+ margin-bottom: 0.5rem;
+}
+
+.intro p {
+ font-size: 1.15rem;
+ max-width: 45rem;
+}
+
+.intro h1 + p {
+ padding: 0;
+}
+
+.intro ul {
+ padding-left: 0;
+ margin-left: 0;
+}
+
+.intro .categories {
+ margin: 1rem 0;
+}
+
+.intro .categories .cell {
+ display: inline-block;
+ padding: 0.25rem 0.75rem;
+ border-radius: 1rem;
+ border: 1px solid var(--color-text);
+ font-size: 0.875rem;
+ margin-bottom: 0.5rem;
+}
+
+
.report-content {
background-image: linear-gradient(#C0CED0, rgba(238,238,238,0));
border-top: 1px solid #6A797C;
@@ -333,17 +345,14 @@ button#add-tech {
margin-bottom: 0;
}
-/* Summary */
-.summary {
+[data-component="summaryCard"] {
position: relative;
- z-index: 1;
- margin-bottom: 4rem;
+ padding-bottom: 3rem;
}
-.summary h2 {
- font-size: 1rem;
- font-weight: 600;
- margin-bottom: 1rem;
+[data-component="summaryCard"] > p.meta {
+ position: absolute;
+ bottom: 1rem;
}
/* Main data */
@@ -417,6 +426,10 @@ button#add-tech {
font-size: var(--font-size-medium);
}
+/* -------------------- */
+/* ---- Highcharts ---- */
+/* -------------------- */
+
/* Highcharts */
.highcharts-title {
font-weight: normal !important;
@@ -443,6 +456,10 @@ path.highcharts-tick {
display: none;
}
+/* ----------------------- */
+/* ---- Media queries ---- */
+/* ----------------------- */
+
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
@media screen and (max-height: 25rem) {
diff --git a/templates/techreport/components/summary_card.html b/templates/techreport/components/summary_card.html
index 8a885a9d..a698d89e 100644
--- a/templates/techreport/components/summary_card.html
+++ b/templates/techreport/components/summary_card.html
@@ -16,6 +16,6 @@
{{ summary.description }}
- Client: Mobile
+ Client: {{ request.args.get('client', '') or 'mobile' }}
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index 7820d267..b4ba007e 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -47,4 +47,7 @@
{{ timeseries.title }}
+
+ Client: {{ request.args.get('client', '') or 'mobile' }}
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index db2f45c1..b1d93f6b 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -35,7 +35,6 @@
data-api="cwv,lighthouse,page-weight"
>
Summary
- Based on the latest data.
{% for summary in tech_report_page.config.summary %}
{% include "techreport/components/summary_card.html" %}
@@ -57,9 +56,6 @@
Core Web Vitals
{% set timeseries = tech_report_page.config.good_cwv_timeseries %}
{% set subcategory = request.args.get('good-cwv-over-time', '') or 'cwv' %}
{% include "techreport/components/timeseries.html" %}
-
- Client: Mobile
-
From 4ef31da3f1457039caa1b146688d65e4b992490a Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Sep 2023 03:14:57 +0200
Subject: [PATCH 068/155] update styling
---
static/css/techreport/techreport.css | 1 +
1 file changed, 1 insertion(+)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 889615d3..65c3360b 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -70,6 +70,7 @@
p.meta {
font-size: 0.75rem;
color: var(--color-text-lighter);
+ margin-top: 1rem;
}
p.meta span {
From a0dd98e59debda5e8652fbcbc3afea5cfefa7f33 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Sep 2023 04:37:53 +0200
Subject: [PATCH 069/155] add table alternatives as general html+js instead of
webcomponent
---
config/techreport.json | 81 +++++++++++++-
src/js/techreport/index.js | 7 +-
src/js/techreport/table.js | 36 ++++++
src/js/techreport/timeseries.js | 3 +
static/css/techreport/techreport.css | 105 ++++++++++++++++++
templates/techreport/components/table.html | 29 +++++
.../techreport/components/timeseries.html | 15 +--
7 files changed, 254 insertions(+), 22 deletions(-)
create mode 100644 src/js/techreport/table.js
create mode 100644 templates/techreport/components/table.html
diff --git a/config/techreport.json b/config/techreport.json
index 6e7d6406..0fd7914c 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -182,9 +182,23 @@
"title": "All usage",
"description": "Placeholder",
"id": "adoption_timeseries",
-
"table": {
- "columns": "date,client,origins"
+ "param":"",
+ "caption": "Usage placeholder",
+ "columns": [
+ {
+ "key": "date",
+ "name": "Date"
+ },
+ {
+ "key": "client",
+ "name": "Client"
+ },
+ {
+ "key": "origins",
+ "name": "Origins"
+ }
+ ]
},
"viz": {
"title": "Origins over time",
@@ -277,7 +291,32 @@
]
},
"table": {
- "columns": "date,client,origins_eligible_for_*subcategory*,origins_with_good_*subcategory*,pct_good_*subcategory*"
+ "param":"good-cwv-over-time",
+ "default": "cwv",
+ "caption": "Good Core Web Vitals placeholder",
+ "columns": [
+ {
+ "key": "date",
+ "name": "Date",
+ "type": "heading"
+ },
+ {
+ "key": "client",
+ "name": "Client"
+ },
+ {
+ "key": "origins_eligible_for_*subcategory*",
+ "name": "Eligible"
+ },
+ {
+ "key": "origins_with_good_*subcategory*",
+ "name": "Good scores"
+ },
+ {
+ "key": "pct_good_*subcategory*",
+ "name": "% Good scores"
+ }
+ ]
},
"summary": true,
"viz": {
@@ -369,7 +408,23 @@
]
},
"table": {
- "columns": "date,client,median_lighthouse_score_*subcategory*"
+ "param":"median-lighthouse-over-time",
+ "default": "performance",
+ "caption": "Lighthouse scores",
+ "columns": [
+ {
+ "key": "date",
+ "name": "Date"
+ },
+ {
+ "key": "client",
+ "name": "Client"
+ },
+ {
+ "key": "median_lighthouse_score_*subcategory*",
+ "name": "Median score"
+ }
+ ]
},
"viz": {
"base": "median_lighthouse_score_",
@@ -450,7 +505,23 @@
]
},
"table": {
- "columns": "date,client,median_bytes_*subcategory*"
+ "param":"weight-over-time",
+ "default": "image",
+ "caption": "Weight",
+ "columns": [
+ {
+ "name": "Date",
+ "key": "date"
+ },
+ {
+ "name": "Client",
+ "key": "client"
+ },
+ {
+ "name": "Median Bytes",
+ "key": "median_bytes_*subcategory*"
+ }
+ ]
},
"viz": {
"base": "median_bytes_",
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 1624ca40..49e84e44 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -63,17 +63,12 @@ class TechReport {
updateClient(event) {
const client = event.target.value;
- // Update web components
- document.querySelectorAll('[data-scope]').forEach(component => {
- component.setAttribute('client', client);
- });
-
// Update the URL
const url = new URL(window.location.href);
url.searchParams.set(`client`, client);
window.history.replaceState(null, null, url);
- // Update selected client property ever
+ // Update selected client property everywhere
document.querySelectorAll('[data-client]').forEach(component => {
component.dataset.client = client;
});
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
new file mode 100644
index 00000000..e42f0878
--- /dev/null
+++ b/src/js/techreport/table.js
@@ -0,0 +1,36 @@
+// TODO: expected data format: rows[{column:...}]
+function structureData() {
+
+}
+
+function updateTable(id, config, app, data) {
+ const component = document.getElementById(`table-${id}`)
+ const tbody = component.querySelector('tbody');
+ tbody.innerHTML = '';
+
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+ const subcategory = urlSubcategory || config.default || '';
+
+ data[app]?.forEach(entry => {
+ const tr = document.createElement('tr');
+
+ config.columns?.forEach(column => {
+ let element = document.createElement('td');
+ if(column.type === "heading") {
+ element = document.createElement('th');
+ }
+
+ const key = column.key.replaceAll("*subcategory*", subcategory);
+ const value = entry[key];
+ element.innerHTML = value;
+ tr.appendChild(element);
+ });
+
+ tbody.appendChild(tr);
+ });
+}
+
+export const Table = {
+ updateTable,
+}
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index fd1a3070..16207ee7 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -1,3 +1,5 @@
+import { Table } from "./table";
+
class Timeseries {
// Create the component
constructor(id, config, filters, data) {
@@ -56,6 +58,7 @@ class Timeseries {
this.updateSummary();
}
this.updateViz();
+ Table.updateTable(this.id, this.pageConfig[this.id]?.table, this.pageFilters.app[0], this.data);
}
// Update the summary with the latest data for all categories
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 65c3360b..8213e695 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -245,6 +245,111 @@ button#add-tech {
border: 1px solid black;
}
+/* General tables */
+.table-ui-wrapper {
+ overflow: auto;
+}
+
+.table-ui-wrapper:focus-visible {
+ outline: 1.5px solid var(--color-teal-dark);
+ outline-offset: 1.5px;
+}
+
+.table-ui {
+ width: 100%;
+ margin: 1rem 0;
+ border-collapse: collapse;
+}
+
+.table-ui tr {
+ border-bottom: 1px solid var(--color-card-border);
+ width: 100%;
+}
+
+.table-ui tr:last-child {
+ border-bottom: none;
+}
+
+.table-ui thead {
+ font-size: 0.875rem;
+ border-bottom: 1px solid var(--color-text);
+}
+
+.table-ui :is(td, th) {
+ min-width: 5rem;
+}
+
+.table-ui :is(td, th):not(:last-child) {
+ padding: 1rem 2rem 1rem 0;
+}
+
+.table-ui tbody tr {
+ border-bottom: 1px solid var(--color-card-border);
+}
+
+.table-ui tbody th {
+ font-weight: normal;
+}
+
+.table-ui :is(td, th) {
+ text-align: left;
+}
+
+.table-ui :is(td, th) strong {
+ margin-right: 0.1rem;
+ font-weight: 600;
+}
+
+.table-ui tr a {
+ color: var(--color-link);
+ text-decoration: underline;
+ width: 100%;
+ display: block;
+}
+
+.table-ui tr .row-link:is(:hover, :focus) {
+ text-decoration-thickness: 3px;
+}
+
+.table-ui tr:has(.row-link:hover) {
+ background-color: var(--table-row-hover);
+}
+
+.table-ui tr:has(.row-link:focus) {
+ background-color: var(--table-row-hover);
+ border: 1.5px solid var(--color-teal-dark);
+}
+
+.table-ui tr:has(.row-link:focus) :is(th, td) {
+ border-bottom: 1.5px solid var(--color-teal-dark);
+ border-top: 1.5px solid var(--color-teal-dark);
+}
+
+.table-ui tr:has(.row-link:focus) .row-link:focus {
+ /* So the outline only gets removed in browsers that support :has */
+ outline-style: dotted;
+}
+
+.table-ui td ul {
+ height: 30px;
+ display: flex;
+ align-items: flex-end;
+ column-gap: 1px;
+}
+
+.table-ui td ul li {
+ border: 1px solid var(--graph-color-primary-darker);
+ height: 100%;
+ background-image: linear-gradient(
+ transparent calc(100% - var(--height)),
+ var(--graph-color-primary) calc(100% - var(--height)) 100%
+ );
+ border-radius: 1px 1px 0 0;
+ flex: 1;
+ list-style-type: none;
+}
+
+
/* -------------------- */
/* ----- Sections ----- */
diff --git a/templates/techreport/components/table.html b/templates/techreport/components/table.html
new file mode 100644
index 00000000..0c6fd519
--- /dev/null
+++ b/templates/techreport/components/table.html
@@ -0,0 +1,29 @@
+
+
+
+
+ {{ table.caption }}
+
+
+ {% for column in table.columns %}
+ {{ column.name }}
+ {% endfor %}
+
+
+
+ {% if table.rows %}
+ {% for row in table.rows %}
+ {% if row.header == "true" %}
+ {{ row.name }}
+ {% else %}
+ {{ row.name }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+
+
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index b4ba007e..2d2651e4 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -34,17 +34,10 @@ {{ timeseries.title }}
Show table
-
-
- {{ timeseries.title }}
-
-
+ {% set table = timeseries.table %}
+ {% set id = timeseries.id %}
+ {% set client = request.args.get('client', '') or 'mobile' %}
+ {% include "techreport/components/table.html" %}
From 6d5b7619f17c2c2488df653af6337fdc0b9f1240 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 02:34:22 +0200
Subject: [PATCH 070/155] style table alts
---
config/techreport.json | 252 ++++++++++--------
src/js/techreport/index.js | 15 +-
src/js/techreport/table.js | 69 ++++-
src/js/utils.js | 6 +-
static/css/techreport/techreport.css | 84 +++++-
templates/techreport/components/table.html | 12 +-
.../techreport/components/timeseries.html | 2 +-
7 files changed, 313 insertions(+), 127 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 0fd7914c..fbdb13c1 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -17,86 +17,25 @@
"performance",
"pwa",
"seo"
+ ],
+ "lighthouse_brackets": [
+ {
+ "name": "poor",
+ "min": 0,
+ "max": 49
+ },
+ {
+ "name": "improvement",
+ "min": 50,
+ "max": 89
+ },
+ {
+ "name": "good",
+ "min": 90,
+ "max": 100
+ }
]
},
- "labels": {
- "values": {
- "date": "Date",
- "client": "Client",
- "origins": "Origins",
-
- "origins_eligible_for_cwv": "Eligible",
- "origins_eligible_for_fid": "Eligible",
- "origins_eligible_for_cls": "Eligible",
- "origins_eligible_for_lcp": "Eligible",
- "origins_eligible_for_fcp": "Eligible",
- "origins_eligible_for_inp": "Eligible",
- "origins_eligible_for_ttfb": "Eligible",
-
- "origins_with_good_cwv": "Having good CWVs",
- "origins_with_good_fid": "Having good FID",
- "origins_with_good_cls": "Having good CLS",
- "origins_with_good_lcp": "Having good LCP",
- "origins_with_good_fcp": "Having good FCP",
- "origins_with_good_inp": "Having good INP",
- "origins_with_good_ttfb": "Having good TTFB",
-
- "pct_good_cwv": "% Good CWVs",
- "pct_good_fid": "% Good FID",
- "pct_good_cls": "% Good CLS",
- "pct_good_lcp": "% Good LCP",
- "pct_good_fcp": "% Good FCP",
- "pct_good_inp": "% Good INP",
- "pct_good_ttfb": "% Good TTFB",
-
- "median_lighthouse_score_accessibility": "Median accessibility",
- "median_lighthouse_score_performance": "Median performance",
- "median_lighthouse_score_pwa": "Median PWA",
- "median_lighthouse_score_seo": "Median SEO",
- "median_lighthouse_score_best_practices": "Median best practices",
-
- "median_bytes_image":"Median bytes image",
- "median_bytes_js":"Median bytes js",
- "median_bytes_total":"Median bytes total"
- }
- },
- "metrics": {
- "cwv": {
- "title": "Core Web Vitals",
- "shortened": "CWVs",
- "description": ""
- },
- "lcp": {
- "title": "Largest Contentful Paint",
- "shortened": "LCP",
- "description": ""
- },
- "fid": {
- "title": "First Input Delay",
- "shortened": "FID",
- "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
- },
- "cls": {
- "title": "Cumulative Layout Shift",
- "shortened": "CLS",
- "description": ""
- },
- "fcp": {
- "title": "First Contentful Paint",
- "shortened": "FCP",
- "description": ""
- },
- "inp": {
- "title": "Interaction to Next Paint",
- "shortened": "INP",
- "description": ""
- },
- "ttfb": {
- "title": "Time to First Byte",
- "shortened": "TTFB",
- "description": ""
- }
- },
"pages": {
"landing": {
"id": "landing",
@@ -189,15 +128,15 @@
{
"key": "date",
"name": "Date"
- },
- {
- "key": "client",
- "name": "Client"
- },
+ },
{
"key": "origins",
"name": "Origins"
- }
+ },
+ {
+ "key": "client",
+ "name": "Client"
+ }
]
},
"viz": {
@@ -299,23 +238,29 @@
"key": "date",
"name": "Date",
"type": "heading"
- },
- {
- "key": "client",
- "name": "Client"
- },
+ },
{
- "key": "origins_eligible_for_*subcategory*",
- "name": "Eligible"
- },
+ "key": "pct_good_*subcategory*",
+ "name": "% Good scores",
+ "suffix": "%",
+ "className": "main-cell pct-value"
+ },
{
"key": "origins_with_good_*subcategory*",
- "name": "Good scores"
- },
+ "name": "Good scores",
+ "className": "good-scores",
+ "hiddenSuffix": "/"
+ },
{
- "key": "pct_good_*subcategory*",
- "name": "% Good scores"
- }
+ "key": "origins_eligible_for_*subcategory*",
+ "name": "Eligible",
+ "className": "eligible"
+ },
+ {
+ "key": "client",
+ "name": "Client",
+ "className": "client"
+ }
]
},
"summary": true,
@@ -415,15 +360,17 @@
{
"key": "date",
"name": "Date"
- },
- {
- "key": "client",
- "name": "Client"
- },
+ },
{
"key": "median_lighthouse_score_*subcategory*",
- "name": "Median score"
- }
+ "name": "Median score",
+ "className": "main-cell"
+ },
+ {
+ "key": "client",
+ "name": "Client",
+ "className": "client"
+ }
]
},
"viz": {
@@ -512,15 +459,18 @@
{
"name": "Date",
"key": "date"
- },
- {
- "name": "Client",
- "key": "client"
- },
+ },
{
"name": "Median Bytes",
- "key": "median_bytes_*subcategory*"
- }
+ "key": "median_bytes_*subcategory*",
+ "suffix": "kB",
+ "className": "main-cell"
+ },
+ {
+ "name": "Client",
+ "key": "client",
+ "className": "client"
+ }
]
},
"viz": {
@@ -593,6 +543,86 @@
"description": "Comparison placeholder"
}
},
+
+ "labels": {
+ "values": {
+ "date": "Date",
+ "client": "Client",
+ "origins": "Origins",
+
+ "origins_eligible_for_cwv": "Eligible",
+ "origins_eligible_for_fid": "Eligible",
+ "origins_eligible_for_cls": "Eligible",
+ "origins_eligible_for_lcp": "Eligible",
+ "origins_eligible_for_fcp": "Eligible",
+ "origins_eligible_for_inp": "Eligible",
+ "origins_eligible_for_ttfb": "Eligible",
+
+ "origins_with_good_cwv": "Having good CWVs",
+ "origins_with_good_fid": "Having good FID",
+ "origins_with_good_cls": "Having good CLS",
+ "origins_with_good_lcp": "Having good LCP",
+ "origins_with_good_fcp": "Having good FCP",
+ "origins_with_good_inp": "Having good INP",
+ "origins_with_good_ttfb": "Having good TTFB",
+
+ "pct_good_cwv": "% Good CWVs",
+ "pct_good_fid": "% Good FID",
+ "pct_good_cls": "% Good CLS",
+ "pct_good_lcp": "% Good LCP",
+ "pct_good_fcp": "% Good FCP",
+ "pct_good_inp": "% Good INP",
+ "pct_good_ttfb": "% Good TTFB",
+
+ "median_lighthouse_score_accessibility": "Median accessibility",
+ "median_lighthouse_score_performance": "Median performance",
+ "median_lighthouse_score_pwa": "Median PWA",
+ "median_lighthouse_score_seo": "Median SEO",
+ "median_lighthouse_score_best_practices": "Median best practices",
+
+ "median_bytes_image":"Median bytes image",
+ "median_bytes_js":"Median bytes js",
+ "median_bytes_total":"Median bytes total"
+ }
+ },
+ "metrics": {
+ "cwv": {
+ "title": "Core Web Vitals",
+ "shortened": "CWVs",
+ "description": ""
+ },
+ "lcp": {
+ "title": "Largest Contentful Paint",
+ "shortened": "LCP",
+ "description": ""
+ },
+ "fid": {
+ "title": "First Input Delay",
+ "shortened": "FID",
+ "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ },
+ "cls": {
+ "title": "Cumulative Layout Shift",
+ "shortened": "CLS",
+ "description": ""
+ },
+ "fcp": {
+ "title": "First Contentful Paint",
+ "shortened": "FCP",
+ "description": ""
+ },
+ "inp": {
+ "title": "Interaction to Next Paint",
+ "shortened": "INP",
+ "description": ""
+ },
+ "ttfb": {
+ "title": "Time to First Byte",
+ "shortened": "TTFB",
+ "description": ""
+ }
+ },
+
"graphic": {
"bgcolor": "#fff",
"primary": {
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 49e84e44..c0543964 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -1,7 +1,6 @@
const { DrilldownHeader } = require("../components/drilldownHeader");
const { Filters } = require("../components/filters");
const { getPercentage } = require("../utils");
-const { SummaryCards } = require('./summaryCards');
class TechReport {
constructor(pageId, page, config, labels) {
@@ -42,11 +41,19 @@ class TechReport {
// TODO
initializeReport() {
Filters.bindFilterListener();
+
const sections = document.querySelectorAll('[data-type="section"]');
+ // TODO: add general config too
sections.forEach(section => {
- const reportSection = new Section(section.id, this.page.config, this.filters, this.allData);
+ const reportSection = new Section(
+ section.id,
+ this.page.config,
+ this.filters,
+ this.allData
+ );
this.sections[section.id] = reportSection;
});
+
this.bindClientListener();
this.updateStyling();
}
@@ -120,9 +127,7 @@ class TechReport {
entry[`pct_good_${cwv}`] = getPercentage(entry[`origins_with_good_${cwv}`], entry[`origins_with_any_${cwv}`]);
});
- /* Turn the LH score from a decimal to an int
- * If this is changed in the new APIs then we can remove this
- */
+ // Turn the LH score from a decimal to an int
this.config.lighthouse_subcategories.forEach(metric => {
entry[`median_lighthouse_score_${metric}`] = parseInt(entry[`median_lighthouse_score_${metric}`] * 100);
})
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index e42f0878..ca6a3e36 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -4,29 +4,84 @@ function structureData() {
}
function updateTable(id, config, app, data) {
+ // Select a table based on the passed in id
const component = document.getElementById(`table-${id}`)
const tbody = component.querySelector('tbody');
+
+ // Reset what's in the table before adding new content
tbody.innerHTML = '';
+ // Get the selected subcategory
const urlParams = new URLSearchParams(window.location.search);
const urlSubcategory = urlParams.get(config.param);
const subcategory = urlSubcategory || config.default || '';
- data[app]?.forEach(entry => {
+ // Filter data by selected client
+ const client = component.dataset.client || 'mobile';
+ const _data = data[app]?.filter(entry => entry.client === client);
+
+ // Create a new row for each entry in the data
+ _data?.forEach(entry => {
const tr = document.createElement('tr');
+ // Add a (regular or heading) cell based on configured columns
config.columns?.forEach(column => {
- let element = document.createElement('td');
- if(column.type === "heading") {
- element = document.createElement('th');
- }
+ const cellType = column.type === "heading" ? 'th' : 'td';
+ let cell = document.createElement(cellType);
+
+ let label = '';
+ let className = column.className;
const key = column.key.replaceAll("*subcategory*", subcategory);
const value = entry[key];
- element.innerHTML = value;
- tr.appendChild(element);
+
+ // Fill in the data if it exists
+ if(value && value !== '') {
+ const suffix = column.suffix || '';
+ label = `${value}${suffix}`;
+ } else {
+ label = 'N/A';
+ className += ' no-data'
+ }
+
+ // Wrap the label in a span for styling
+ const wrapper = document.createElement('span');
+ wrapper.innerHTML = label;
+ cell.append(wrapper);
+
+ // For stylized columns (eg out of )
+ if(column.hiddenSuffix) {
+ const hiddenSuffix = document.createElement('span');
+ hiddenSuffix.setAttribute('aria-hidden', 'true');
+ hiddenSuffix.innerHTML = column.hiddenSuffix;
+
+ const labelWrapper = document.createElement('span');
+ const cellWrapper = document.createElement(cellType);
+
+ labelWrapper.innerHTML = label;
+
+ cellWrapper.appendChild(labelWrapper);
+ cellWrapper.appendChild(hiddenSuffix);
+
+ cell = cellWrapper;
+ }
+
+ // Expose percentages to css to use for styling
+ if(label.includes('%')) {
+ cell.setAttribute('style', `--cell-value: ${value}%`);
+ cell.dataset.value = value;
+ }
+
+ // Add classnames from the config
+ if(column.className) {
+ cell.className = className;
+ }
+
+ // Add cell to the row
+ tr.appendChild(cell);
});
+ // Update the table
tbody.appendChild(tr);
});
}
diff --git a/src/js/utils.js b/src/js/utils.js
index 1784ab3b..97bfc552 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -102,5 +102,9 @@ export const getLatestEntry = (data) => {
};
export const getPercentage = (x, y) => {
- return parseInt(parseInt(x) / parseInt(y) * 10000) / 100;
+ if(y && y > 0) {
+ return parseInt(parseInt(x) / parseInt(y) * 10000) / 100;
+ }
+
+ return;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 8213e695..0228bf61 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -280,7 +280,7 @@ button#add-tech {
}
.table-ui :is(td, th):not(:last-child) {
- padding: 1rem 2rem 1rem 0;
+ padding: 1rem 1rem 1rem 0;
}
.table-ui tbody tr {
@@ -349,7 +349,63 @@ button#add-tech {
list-style-type: none;
}
+.table-ui .no-data {
+ color: var(--color-text-lighter);
+}
+
+.table-ui .client {
+ text-align: right;
+}
+
+.table-ui .good-scores {
+ text-align: right;
+}
+
+.table-ui .eligible {
+ font-size: 0.825rem;
+ position: relative;
+ top: 0.05rem;
+}
+
+.table-ui td.eligible {
+ color: var(--color-text-lighter);
+}
+
+.table-ui .good-scores span[aria-hidden] {
+ font-weight: 400;
+ font-size: 0.825rem;
+ margin-left: 1rem;
+}
+.table-ui td.main-cell {
+ font-weight: 600;
+}
+
+.table-ui td.pct-value {
+ position: relative;
+}
+
+.table-ui td.pct-value[data-value] span {
+ width: 4.5rem;
+ display: block;
+}
+
+.table-ui td.pct-value[data-value] span:after {
+ content: '';
+ display: block;
+ height: 0.5rem;
+ width: 100%;
+ width: calc(100% - 4.5rem);
+ position: absolute;
+ top: 1.5rem;
+ right: 0;
+ border: 1px solid var(--color-teal-dark);
+ background-image: linear-gradient(
+ 90deg,
+ var(--color-teal-dark) 0% var(--cell-value),
+ transparent var(--cell-value) 100%
+ );
+}
/* -------------------- */
/* ----- Sections ----- */
@@ -575,6 +631,28 @@ path.highcharts-tick {
}
/* Smaller screens */
+@media screen and (max-width: 50rem) {
+ .table-ui td.pct-value[data-value] span {
+ width: 100%;
+ }
+
+ .table-ui .pct-value {
+ min-width: 10rem;
+ }
+
+ .table-ui td.pct-value[data-value] span:after {
+ display: none;
+ }
+
+ .table-ui tbody * {
+ font-size: 1rem;
+ }
+
+ .table-ui .good-scores span[aria-hidden] {
+ display: none;
+ }
+}
+
@media screen and (max-width: 46rem) {
.summary-grid {
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
@@ -583,4 +661,8 @@ path.highcharts-tick {
.summary-grid > * {
max-width: 95vw;
}
+
+ .table-ui :is(td, th) {
+ min-width: 7.5rem;
+ }
}
diff --git a/templates/techreport/components/table.html b/templates/techreport/components/table.html
index 0c6fd519..b42fb07f 100644
--- a/templates/techreport/components/table.html
+++ b/templates/techreport/components/table.html
@@ -10,7 +10,17 @@
{% for column in table.columns %}
- {{ column.name }}
+
+ {{ column.name }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
{% endfor %}
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index 2d2651e4..dfd4dcef 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -20,7 +20,7 @@ {{ timeseries.title }}
{% for breakdown in timeseries.viz.series["values"] %}
{{ breakdown.name }}
-
00{{ breakdown.suffix }}
+
00{% if breakdown.suffix == "%" %}.00{% endif %}{{ breakdown.suffix }}
{% endfor %}
{% endif %}
From 31ce9fb4a83c061a2a8f42b48046d32e8e01e049 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 03:54:59 +0200
Subject: [PATCH 071/155] update title and description of cards based on
selected subcategory
---
config/techreport.json | 68 ++++++++++++++++---
src/js/techreport/index.js | 10 ++-
src/js/techreport/timeseries.js | 17 +++++
.../techreport/components/timeseries.html | 12 +++-
4 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index fbdb13c1..aeb13436 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -201,31 +201,45 @@
"options": [
{
"label": "Overall good CWVs",
- "value": "cwv"
+ "value": "cwv",
+ "title": "Origins with overall good Core Web Vitals",
+ "description": "overall todo"
},
{
"label": "LCP",
- "value": "lcp"
+ "value": "lcp",
+ "title": "Origins with good LCP",
+ "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
},
{
"label": "FID",
- "value": "fid"
+ "value": "fid",
+ "title": "Origins with good FID",
+ "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
},
{
"label": "CLS",
- "value": "cls"
+ "value": "cls",
+ "title": "Origins with good CLS",
+ "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
},
{
"label": "FCP",
- "value": "fcp"
+ "value": "fcp",
+ "title": "Origins with good FCP",
+ "description": "todo find fcp description"
},
{
"label": "TTFB",
- "value": "ttfb"
+ "value": "ttfb",
+ "title": "Origins with good TTFB",
+ "description": "todo find fcp description"
},
{
"label": "INP",
- "value": "inp"
+ "value": "inp",
+ "title": "Origins with good LCP",
+ "description": "todo find fcp description"
}
]
},
@@ -268,7 +282,7 @@
"base": "pct_good_",
"default": "cwv",
"param": "good-cwv-over-time",
- "title": "Overall good CWVs over time",
+ "title": "Origins with good scores over time",
"metric": "pct_good_cwv",
"height": 600,
"series": {
@@ -545,6 +559,44 @@
},
"labels": {
+ "metrics": {
+ "cwv": {
+ "label": "Overall good CWVs",
+ "title": "Origins with overall good Core Web Vitals",
+ "description": "overall todo"
+ },
+ "lcp": {
+ "label": "LCP",
+ "title": "Origins with good LCP",
+ "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
+ },
+ "fid": {
+ "label": "FID",
+ "title": "Origins with good FID",
+ "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ },
+ "cls": {
+ "label": "CLS",
+ "title": "Origins with good CLS",
+ "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
+ },
+ "fcp": {
+ "label": "FCP",
+ "value": "fcp",
+ "title": "Origins with good FCP",
+ "description": "todo find fcp description"
+ },
+ "ttfb": {
+ "label": "TTFB",
+ "title": "Origins with good TTFB",
+ "description": "todo find fcp description"
+ },
+ "inp": {
+ "label": "INP",
+ "title": "Origins with good LCP",
+ "description": "todo find fcp description"
+ }
+ },
"values": {
"date": "Date",
"client": "Client",
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index c0543964..fcd60b0e 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -6,12 +6,20 @@ class TechReport {
constructor(pageId, page, config, labels) {
this.filters = page.filters;
this.allData = [];
- this.page = page;
this.config = config;
this.labels = labels;
this.pageId = pageId;
this.sections = {};
+ // Pass the labels into the page data
+ this.page = {
+ ...page,
+ config: {
+ ...page.config,
+ labels: labels,
+ }
+ };
+
// Load the page
this.initializePage();
this.getAllData();
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 16207ee7..c18bae15 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -36,6 +36,7 @@ class Timeseries {
// Re-render the content
this.updateContent();
+ this.updateInfo(event.target.value);
}
}
@@ -52,6 +53,22 @@ class Timeseries {
}
}
+ // Re-render the title, description, and text labels
+ updateInfo(value) {
+ const option = this.pageConfig?.labels?.metrics[value];
+ const component = document.querySelector(`[data-id="${this.id}"]`);
+
+ if(option && option.title) {
+ const title = component.querySelector('h3');
+ title.innerHTML = option.title;
+ }
+
+ if(option && option.description) {
+ const descr = component.querySelector('.descr');
+ descr.innerHTML = option.description;
+ }
+ }
+
// Re-render the contents of the component
updateContent() {
if(this.pageConfig[this.id]?.summary) {
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index dfd4dcef..a28f2346 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -5,8 +5,16 @@
{% include "techreport/components/subcategory.html" %}
{% endif %}
- {{ timeseries.title }}
- {{ timeseries.description }}
+ {% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
+ {% set title = timeseries.title %}
+ {% set descr = timeseries.description %}
+ {% if tech_report_labels.metrics[selectedParam] %}
+ {% set title = tech_report_labels.metrics[selectedParam].title %}
+ {% set descr = tech_report_labels.metrics[selectedParam].description %}
+ {% endif %}
+
+ {{ title }}
+ {{ descr }}
{% if timeseries.summary %}
From 6b0816ca04c57112d344c01c5f5a322af4c6f54f Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 04:07:35 +0200
Subject: [PATCH 072/155] add geo and rank info for each component (on the
drilldown page)
---
src/js/techreport/index.js | 3 +--
static/css/techreport/techreport.css | 13 +++++++++++--
templates/techreport/components/filter_meta.html | 11 +++++++++++
templates/techreport/components/summary_card.html | 3 ---
templates/techreport/components/timeseries.html | 4 +---
templates/techreport/drilldown.html | 1 +
6 files changed, 25 insertions(+), 10 deletions(-)
create mode 100644 templates/techreport/components/filter_meta.html
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index fcd60b0e..d90a8add 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -96,8 +96,7 @@ class TechReport {
// Update labels
document.querySelectorAll('[data-slot="client"]').forEach(component => {
component.innerHTML = client;
- })
-
+ });
}
// Fetch all the data based on search criteria and config
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 0228bf61..84c2c193 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -67,13 +67,22 @@
}
/* Filter info */
-p.meta {
+.meta {
font-size: 0.75rem;
color: var(--color-text-lighter);
margin-top: 1rem;
}
-p.meta span {
+.meta li {
+ list-style-type: none;
+ display: inline-block;
+}
+
+.meta li:not(:last-child) {
+ margin-right: 2rem;
+}
+
+.meta span {
font-weight: 600;
}
diff --git a/templates/techreport/components/filter_meta.html b/templates/techreport/components/filter_meta.html
new file mode 100644
index 00000000..28734686
--- /dev/null
+++ b/templates/techreport/components/filter_meta.html
@@ -0,0 +1,11 @@
+
diff --git a/templates/techreport/components/summary_card.html b/templates/techreport/components/summary_card.html
index a698d89e..d2e2443a 100644
--- a/templates/techreport/components/summary_card.html
+++ b/templates/techreport/components/summary_card.html
@@ -15,7 +15,4 @@
{{ summary.description }}
-
- Client: {{ request.args.get('client', '') or 'mobile' }}
-
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index a28f2346..3727932c 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -48,7 +48,5 @@ {{ title }}
{% include "techreport/components/table.html" %}
-
- Client: {{ request.args.get('client', '') or 'mobile' }}
-
+ {% include "techreport/components/filter_meta.html" %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index b1d93f6b..087fdcad 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -40,6 +40,7 @@ Summary
{% include "techreport/components/summary_card.html" %}
{% endfor %}
+ {% include "techreport/components/filter_meta.html" %}
From 92047299b29cfae8369e792b84ba0b03a7bc2907 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 04:22:59 +0200
Subject: [PATCH 073/155] style subcategory selector
---
static/css/techreport/techreport.css | 27 ++++++++++++++
.../techreport/components/timeseries.html | 35 +++++++++++--------
2 files changed, 48 insertions(+), 14 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 84c2c193..288812cf 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -416,6 +416,33 @@ button#add-tech {
);
}
+/* Metric components */
+.component-heading-wrapper {
+ display: flex;
+ flex-wrap: wrap-reverse;
+}
+
+.component-heading-wrapper > * {
+ flex: 1;
+}
+
+.component-heading {
+ max-width: 90vw;
+}
+
+.component-heading h3 {
+ margin-top: 0;
+}
+
+.component-filters {
+ text-align: right;
+}
+
+.component-filters label {
+ display: block;
+ font-weight: normal;
+}
+
/* -------------------- */
/* ----- Sections ----- */
/* -------------------- */
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index 3727932c..c7c376ac 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -1,20 +1,27 @@
- {% if timeseries.subcategory %}
- {% set subcategory = timeseries.subcategory %}
- {% set id = timeseries.id %}
- {% include "techreport/components/subcategory.html" %}
- {% endif %}
+
+
+ {% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
+ {% set title = timeseries.title %}
+ {% set descr = timeseries.description %}
+ {% if tech_report_labels.metrics[selectedParam] %}
+ {% set title = tech_report_labels.metrics[selectedParam].title %}
+ {% set descr = tech_report_labels.metrics[selectedParam].description %}
+ {% endif %}
- {% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
- {% set title = timeseries.title %}
- {% set descr = timeseries.description %}
- {% if tech_report_labels.metrics[selectedParam] %}
- {% set title = tech_report_labels.metrics[selectedParam].title %}
- {% set descr = tech_report_labels.metrics[selectedParam].description %}
- {% endif %}
+
{{ title }}
+
{{ descr }}
+
+
+
+ {% if timeseries.subcategory %}
+ {% set subcategory = timeseries.subcategory %}
+ {% set id = timeseries.id %}
+ {% include "techreport/components/subcategory.html" %}
+ {% endif %}
+
+
-
{{ title }}
-
{{ descr }}
{% if timeseries.summary %}
From 7029693616225ee536827fcc250e38ce6c645c96 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 19:01:14 +0200
Subject: [PATCH 074/155] add summary to metric sections
---
config/techreport.json | 93 +++++++++++++++++++
src/js/techreport/summaryCards.js | 2 +
static/css/techreport/general.css | 2 +-
static/css/techreport/techreport.css | 11 ++-
.../techreport/components/subcategory.html | 2 +-
.../techreport/components/summary_card.html | 7 +-
.../techreport/components/timeseries.html | 4 +-
templates/techreport/drilldown.html | 31 +++++++
8 files changed, 146 insertions(+), 6 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index aeb13436..5b0fff22 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -190,6 +190,46 @@
}
}
},
+ "good_cwv_summary": {
+ "title": "Latest Core Web Vitals",
+ "cards": [
+ {
+ "metric": "pct_good_cwv",
+ "label": "Good CWVs",
+ "suffix": "%",
+ "description": "Origins with overall good core web vitals.",
+ "url": "?good-cwv-over-time=cwv#good-cwvs"
+ },
+ {
+ "metric": "pct_good_lcp",
+ "label": "Good LCP",
+ "suffix": "%",
+ "description": "Percentage of origins with good LCP scores (under 0.25s).",
+ "url": "?good-cwv-over-time=lcp#good-cwvs"
+ },
+ {
+ "metric": "pct_good_fid",
+ "label": "Good FID",
+ "suffix": "%",
+ "description": "Percentage of origins with good FID scores (under xxx).",
+ "url": "?good-cwv-over-time=fid#good-cwvs"
+ },
+ {
+ "metric": "pct_good_cls",
+ "label": "Good CLS",
+ "suffix": "%",
+ "description": "Percentage of origins with good CLS scores (under xxx).",
+ "url": "?good-cwv-over-time=cls#good-cwvs"
+ },
+ {
+ "metric": "pct_good_inp",
+ "label": "Good INP",
+ "suffix": "%",
+ "description": "Percentage of origins with good INP scores (under xxx).",
+ "url": "?good-cwv-over-time=inp#good-cwvs"
+ }
+ ]
+ },
"good_cwv_timeseries": {
"title": "Good Core Web Vitals over time",
"description": "Placeholder - combination of several metrics",
@@ -334,6 +374,36 @@
}
}
},
+ "lighthouse_summary": {
+ "title": "Latest lightroom scores",
+ "cards": [
+ {
+ "metric": "median_lighthouse_score_performance",
+ "label": "Performance",
+ "url": "?median-lighthouse-over-time=performance#lighthouse"
+ },
+ {
+ "metric": "median_lighthouse_score_accessibility",
+ "label": "Accessibility",
+ "url": "?median-lighthouse-over-time=accessibility#lighthouse"
+ },
+ {
+ "metric": "median_lighthouse_score_seo",
+ "label": "SEO",
+ "url": "?median-lighthouse-over-time=seo#lighthouse"
+ },
+ {
+ "metric": "median_lighthouse_score_pwa",
+ "label": "PWA",
+ "url": "?median-lighthouse-over-time=pwa#lighthouse"
+ },
+ {
+ "metric": "median_lighthouse_score_best_practices",
+ "label": "Best Practices",
+ "url": "?median-lighthouse-over-time=best_practices#lighthouse"
+ }
+ ]
+ },
"lighthouse_timeseries": {
"title": "Lighthouse over time",
"description": "Placeholder text",
@@ -441,6 +511,29 @@
}
}
},
+ "weight_summary": {
+ "title": "Latest page weight",
+ "cards": [
+ {
+ "metric": "median_bytes_image",
+ "label": "Image Weight",
+ "url": "?weight-over-time=image#page-weight",
+ "suffix": " kB"
+ },
+ {
+ "metric": "median_bytes_js",
+ "label": "JavaScript Size",
+ "url": "?weight-over-time=js#page-weight",
+ "suffix": " kB"
+ },
+ {
+ "metric": "median_bytes_total",
+ "label": "Total Page Weight",
+ "url": "?weight-over-time=total#page-weight",
+ "suffix": " kB"
+ }
+ ]
+ },
"weight_timeseries": {
"title": "Weight over time",
"description": "Placeholder text",
diff --git a/src/js/techreport/summaryCards.js b/src/js/techreport/summaryCards.js
index 2aa42178..7386b907 100644
--- a/src/js/techreport/summaryCards.js
+++ b/src/js/techreport/summaryCards.js
@@ -28,6 +28,8 @@ class SummaryCard {
const metric = card.dataset.metric;
const value = latest[metric];
+ console.log('latest', latest);
+
// Update the html
if(value) {
card.querySelector('[data-slot="value"]').innerHTML = value;
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 73a3b4de..1748da97 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -22,7 +22,7 @@ p {
margin: 0;
}
-:is(a, button, select):focus {
+:is(a, button, select):focus-visible {
outline: 1.5px solid var(--color-teal-dark);
outline-offset: 1.5px;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 288812cf..7d78a76d 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -209,6 +209,10 @@ button#add-tech {
row-gap: 1rem;
}
+.summary-grid + .card {
+ margin-top: 1rem;
+}
+
/* Timeseries cards */
.timeseries-container {
margin-top: 2rem;
@@ -441,6 +445,11 @@ button#add-tech {
.component-filters label {
display: block;
font-weight: normal;
+ font-size: 0.875rem;
+}
+
+.component-filters select {
+ font-size: 1rem;
}
/* -------------------- */
@@ -584,7 +593,7 @@ button#add-tech {
margin-top: 2rem;
}
-.data-summary .heading {
+.data-summary .heading h4 {
font-size: 0.875rem;
color: var(--color-text-lighter);
text-transform: uppercase;
diff --git a/templates/techreport/components/subcategory.html b/templates/techreport/components/subcategory.html
index 3129e443..fb0f49da 100644
--- a/templates/techreport/components/subcategory.html
+++ b/templates/techreport/components/subcategory.html
@@ -1,5 +1,5 @@
{% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
-Subcategory
+Metric
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index c7c376ac..e73e4cf6 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -26,9 +26,9 @@
{{ title }}
{% if timeseries.summary %}
{% if timeseries.viz.series.breakdown == 'client' %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 087fdcad..f2120cd0 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -53,6 +53,16 @@
Summary
Core Web Vitals
Description
+ {% if tech_report_page.config.good_cwv_summary %}
+
{{ tech_report_page.config.good_cwv_summary.title }}
+
+ {% for summary in tech_report_page.config.good_cwv_summary.cards %}
+ {% set section_prefix = "cwv" %}
+ {% include "techreport/components/summary_card.html" %}
+ {% endfor %}
+
+ {% endif %}
+
{% set timeseries = tech_report_page.config.good_cwv_timeseries %}
{% set subcategory = request.args.get('good-cwv-over-time', '') or 'cwv' %}
@@ -70,6 +80,16 @@
Core Web Vitals
Lighthouse
Description
+ {% if tech_report_page.config.lighthouse_summary %}
+ {% set section_prefix = "lighthouse" %}
+
{{ tech_report_page.config.lighthouse_summary.title }}
+
+ {% for summary in tech_report_page.config.lighthouse_summary.cards %}
+ {% include "techreport/components/summary_card.html" %}
+ {% endfor %}
+
+ {% endif %}
+
{% set timeseries = tech_report_page.config.lighthouse_timeseries %}
{% set subcategory = request.args.get('median-lighthouse-over-time', '') or 'cwv' %}
@@ -86,6 +106,17 @@
Lighthouse
>
Page weight
Description
+
+ {% if tech_report_page.config.weight_summary %}
+ {% set section_prefix = "weight" %}
+
{{ tech_report_page.config.weight_summary.title }}
+
+ {% for summary in tech_report_page.config.weight_summary.cards %}
+ {% include "techreport/components/summary_card.html" %}
+ {% endfor %}
+
+ {% endif %}
+
{% set timeseries = tech_report_page.config.weight_timeseries %}
{% include "techreport/components/timeseries.html" %}
From daac7ed2b652a8988d3df2aa156dd7023a2edbb4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 28 Sep 2023 19:05:27 +0200
Subject: [PATCH 075/155] update styling
---
static/css/techreport/general.css | 2 ++
static/css/techreport/techreport.css | 33 +++++-----------------------
2 files changed, 8 insertions(+), 27 deletions(-)
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 1748da97..26d81805 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -15,6 +15,8 @@ h1 {
h2 {
font-size: var(--font-size-large);
+ margin-bottom: 0;
+ margin-top: 0;
}
/* Overwrite margin that's set elsewhere */
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 7d78a76d..b8cb6116 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -513,7 +513,12 @@ button#add-tech {
}
.report-section {
- margin-bottom: 4rem;
+ margin-bottom: 6rem;
+}
+
+.report-section + .report-section {
+ padding-top: 4rem;
+ border-top: 1px solid var(--color-text-lighter);
}
.report-content:has(> .error) {
@@ -562,32 +567,6 @@ button#add-tech {
bottom: 1rem;
}
-/* Main data */
-.page-data {
- margin-top: -4rem;
- padding: 8rem 0;
- border-top: 1px solid var(--color-teal-medium);
- background-image:
- linear-gradient(
- var(--color-teal-faded) 60%,
- var(--color-page-background)
- );
- background-size: 100% 25rem;
- background-repeat: no-repeat;
-}
-
-.page-data h2 {
- margin-bottom: 1rem;
-}
-
-.metric-block + .metric-block {
- margin-top: 6rem;
-}
-
-.block-description {
- max-width: 50rem;
-}
-
/* Chart summary list */
.data-summary {
margin-top: 2rem;
From 3dd93be0512784ac1965971e9466eea7656cc579 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 29 Sep 2023 01:56:01 +0200
Subject: [PATCH 076/155] clean up styles
---
src/js/techreport/summaryCards.js | 2 --
static/css/techreport/general.css | 8 ++++++--
static/css/techreport/techreport.css | 5 -----
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/js/techreport/summaryCards.js b/src/js/techreport/summaryCards.js
index 7386b907..2aa42178 100644
--- a/src/js/techreport/summaryCards.js
+++ b/src/js/techreport/summaryCards.js
@@ -28,8 +28,6 @@ class SummaryCard {
const metric = card.dataset.metric;
const value = latest[metric];
- console.log('latest', latest);
-
// Update the html
if(value) {
card.querySelector('[data-slot="value"]').innerHTML = value;
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 26d81805..e3e4e0db 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -15,10 +15,14 @@ h1 {
h2 {
font-size: var(--font-size-large);
- margin-bottom: 0;
- margin-top: 0;
}
+h2 + p {
+ margin: 0;
+ padding: 0;
+}
+
+
/* Overwrite margin that's set elsewhere */
p {
margin: 0;
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index b8cb6116..fa6329d3 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -516,11 +516,6 @@ button#add-tech {
margin-bottom: 6rem;
}
-.report-section + .report-section {
- padding-top: 4rem;
- border-top: 1px solid var(--color-text-lighter);
-}
-
.report-content:has(> .error) {
background-image: none;
padding-top: 0;
From b0d2f34b7e81130b025bb15beaa97312c5793fc4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 30 Sep 2023 02:05:36 +0200
Subject: [PATCH 077/155] add support for app comparison tables
---
config/techreport.json | 83 ++++++++-
server/routes.py | 13 +-
src/js/techreport/index.js | 10 +-
src/js/techreport/table.js | 144 ++++++++++++----
src/js/techreport/timeseries.js | 29 +++-
templates/techreport/comparison.html | 178 +++++++-------------
templates/techreport/comparison_backup.html | 165 ++++++++++++++++++
templates/techreport/components/table.html | 41 +++--
templates/techreport/drilldown.html | 2 +-
9 files changed, 492 insertions(+), 173 deletions(-)
create mode 100644 templates/techreport/comparison_backup.html
diff --git a/config/techreport.json b/config/techreport.json
index 5b0fff22..6481b532 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -644,7 +644,88 @@
"subtitle": "Technology Report",
"config": {
"default": {
- "app": ["ALL", "WordPress", "Drupal"]
+ "app": ["ALL", "WordPress", "Drupal"],
+ "series": {
+ "breakdown": "app"
+ }
+ },
+ "good_cwv_timeseries": {
+ "title": "Good Core Web Vitals over time",
+ "description": "Placeholder - combination of several metrics",
+ "id": "good_cwv_timeseries",
+ "subcategory": {
+ "base": "pct_good_",
+ "param": "good-cwv-over-time",
+ "default": "cwv",
+ "options": [
+ {
+ "label": "Overall good CWVs",
+ "value": "cwv",
+ "title": "Origins with overall good Core Web Vitals",
+ "description": "overall todo"
+ },
+ {
+ "label": "LCP",
+ "value": "lcp",
+ "title": "Origins with good LCP",
+ "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
+ },
+ {
+ "label": "FID",
+ "value": "fid",
+ "title": "Origins with good FID",
+ "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ },
+ {
+ "label": "CLS",
+ "value": "cls",
+ "title": "Origins with good CLS",
+ "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
+ },
+ {
+ "label": "FCP",
+ "value": "fcp",
+ "title": "Origins with good FCP",
+ "description": "todo find fcp description"
+ },
+ {
+ "label": "TTFB",
+ "value": "ttfb",
+ "title": "Origins with good TTFB",
+ "description": "todo find fcp description"
+ },
+ {
+ "label": "INP",
+ "value": "inp",
+ "title": "Origins with good LCP",
+ "description": "todo find fcp description"
+ }
+ ]
+ },
+ "table": {
+ "param": "good-cwv-over-time",
+ "default": "cwv",
+ "caption": "Good Core Web Vitals placeholder",
+ "columns": [
+ {
+ "key": "date",
+ "name": "Date",
+ "type": "heading"
+ },
+ {
+ "key": "pct_good_*subcategory*",
+ "name": "App",
+ "breakdown": "app",
+ "suffix": "%",
+ "className": "main-cell pct-value"
+ },
+ {
+ "key": "client",
+ "name": "Client",
+ "className": "client"
+ }
+ ]
+ }
}
},
"description": "Comparison placeholder"
diff --git a/server/routes.py b/server/routes.py
index 5ce224f5..cc6e42b4 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -78,15 +78,15 @@ def techreport(page_id):
# Get the settings for the current page
active_tech_report = tech_report.get("pages").get(page_id)
- # Combine technologies from the URL with the pre-defined ones from the config
- # Because sometimes we want 'ALL' in addition to chosen tech
- requested_technologies = "ALL"
- default_technologies = active_tech_report.get("config").get("default").get("app")
+ # Add the technologies requested in the URL to the filters
+ # Use the default configured techs as fallback
+ # Use ["ALL"] if there is nothing configured
+ requested_technologies = active_tech_report.get("config").get("default").get("app") or ["ALL"]
if request.args.get("tech"):
requested_technologies = request.args.get("tech").split(",")
- if isinstance(requested_technologies, str):
- requested_technologies = [requested_technologies]
+ if isinstance(requested_technologies, str):
+ requested_technologies = [requested_technologies]
# Get the filters
requested_geo = request.args.get("geo") or "ALL"
@@ -95,7 +95,6 @@ def techreport(page_id):
"geo": requested_geo,
"rank": requested_rank,
"app": requested_technologies,
- "app_defaults": default_technologies,
}
active_tech_report["filters"] = filters
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index d90a8add..5859901f 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -103,7 +103,7 @@ class TechReport {
// TODO: Will be moved to the section level with new APIs
getAllData() {
const data = {};
- const fetch_app = this.filters.app.concat(this.filters.app_defaults);
+ const fetch_app = this.filters.app;
/* Make a request for each of the technologies and return them in an object.
* Once we port this over to the new APIs, this should be moved to the section level.
@@ -221,6 +221,14 @@ class TechReport {
updateComparisonComponents(data) {
if(data && Object.keys(data).length > 0) {
+ // TODO: this doesn't have to be diff for landing / comp / drilldown
+ // Update sections
+ Object.values(this.sections).forEach(section => {
+ section.data = data;
+ section.updateSection();
+ });
+
+
const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
allDataComponents.forEach((component) => {
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index ca6a3e36..3a197afc 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -1,9 +1,85 @@
-// TODO: expected data format: rows[{column:...}]
-function structureData() {
+function formatData(tableConfig, data) {
+ const { id, config, apps } = tableConfig;
+ // Get the selected subcategory
+ const subcategory = getSubcategory(config);
+
+ // Create empty array
+ const table = [];
+
+ // Loop through all of the dates
+ // Populate array of data rows with it
+ const dates = Object.values(data)[0];
+ const component = document.getElementById(`table-${id}`);
+ const client = component.dataset.client || 'mobile';
+ const _dates = dates?.filter(entry => entry.client === client);
+
+ for(let i = 0; i < _dates?.length; i++) {
+ const row = [];
+
+ // Loop through each of the column configs
+ config.columns?.forEach(column => {
+ // Create object with necessary info to find the value
+ const columnConfig = {
+ config,
+ column,
+ client
+ };
+
+ // Add column cell for each of the apps
+ // Filter by app name and then metric (key) to find the value
+ if(column.breakdown === 'app') {
+ apps.forEach(app => {
+ row.push(getColumnCell({...columnConfig, app}, data, i));
+ });
+ }
+
+ // Add column cell with the data for the first app
+ else {
+ const app = apps[0];
+ row.push(getColumnCell({...columnConfig, app}, data, i));
+ }
+ });
+
+ // Add row to the table
+ table.push(row);
+ }
+
+ console.log(table);
+
+ return table;
+}
+
+function getColumnCell(columnConfig, data, rowNr) {
+ const { config, column, client, app } = columnConfig;
+
+ // Get the selected subcategory
+ const subcategory = getSubcategory(config);
+
+ const _data = data[app]?.filter(entry => entry.client === client);
+ const key = column?.key?.replaceAll('*subcategory*', subcategory);
+
+ const cell = {
+ ...column,
+ formattedKey: key,
+ value: _data[rowNr][key],
+ app: app
+ };
+
+ return cell;
}
-function updateTable(id, config, app, data) {
+// Get the selected subcategory based on url
+function getSubcategory(config) {
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+ const subcategory = urlSubcategory || config.default || '';
+
+ return subcategory;
+}
+
+// Update the table
+function updateTable(id, config, apps, data) {
// Select a table based on the passed in id
const component = document.getElementById(`table-${id}`)
const tbody = component.querySelector('tbody');
@@ -11,69 +87,77 @@ function updateTable(id, config, app, data) {
// Reset what's in the table before adding new content
tbody.innerHTML = '';
- // Get the selected subcategory
- const urlParams = new URLSearchParams(window.location.search);
- const urlSubcategory = urlParams.get(config.param);
- const subcategory = urlSubcategory || config.default || '';
+ // console.log('update table', id, data);
- // Filter data by selected client
- const client = component.dataset.client || 'mobile';
- const _data = data[app]?.filter(entry => entry.client === client);
+ const tableConfig = {
+ id,
+ config,
+ apps
+ };
+
+ const rows = formatData(tableConfig, data);
+
+ console.log('rows', rows);
+
+ rows?.forEach(row => {
+ const entry = row;
- // Create a new row for each entry in the data
- _data?.forEach(entry => {
const tr = document.createElement('tr');
- // Add a (regular or heading) cell based on configured columns
- config.columns?.forEach(column => {
+ console.log('row', row);
+
+ row?.forEach(column => {
const cellType = column.type === "heading" ? 'th' : 'td';
let cell = document.createElement(cellType);
- let label = '';
+ let text = '';
let className = column.className;
- const key = column.key.replaceAll("*subcategory*", subcategory);
- const value = entry[key];
+ const value = column.value;
// Fill in the data if it exists
if(value && value !== '') {
const suffix = column.suffix || '';
- label = `${value}${suffix}`;
+ text = `${value}${suffix}`;
} else {
- label = 'N/A';
+ text = 'N/A';
className += ' no-data'
}
- // Wrap the label in a span for styling
+ // Wrap the text in a span for styling
const wrapper = document.createElement('span');
- wrapper.innerHTML = label;
+ wrapper.innerHTML = text;
cell.append(wrapper);
- // For stylized columns (eg out of )
+ // Stylized column groups (eg format ` / `)
if(column.hiddenSuffix) {
+ /* In this case applying aria-hidden because otherwise
+ * assistive tech would announce "/" at the end of col 1
+ * or as part of the heading, which may be announced weirdly.
+ * So since it's mainly decorative, we hide it as a precaution.
+ */
const hiddenSuffix = document.createElement('span');
hiddenSuffix.setAttribute('aria-hidden', 'true');
hiddenSuffix.innerHTML = column.hiddenSuffix;
- const labelWrapper = document.createElement('span');
- const cellWrapper = document.createElement(cellType);
+ const textWrapper = document.createElement('span');
+ textWrapper.innerHTML = text;
- labelWrapper.innerHTML = label;
-
- cellWrapper.appendChild(labelWrapper);
+ const cellWrapper = document.createElement(cellType);
+ cellWrapper.appendChild(textWrapper);
cellWrapper.appendChild(hiddenSuffix);
cell = cellWrapper;
}
// Expose percentages to css to use for styling
- if(label.includes('%')) {
+ if(text.includes('%')) {
cell.setAttribute('style', `--cell-value: ${value}%`);
cell.dataset.value = value;
}
// Add classnames from the config
- if(column.className) {
+ if(className) {
cell.className = className;
}
@@ -81,7 +165,7 @@ function updateTable(id, config, app, data) {
tr.appendChild(cell);
});
- // Update the table
+ // Add row to the body
tbody.appendChild(tr);
});
}
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index c18bae15..aaa690c5 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -75,7 +75,7 @@ class Timeseries {
this.updateSummary();
}
this.updateViz();
- Table.updateTable(this.id, this.pageConfig[this.id]?.table, this.pageFilters.app[0], this.data);
+ Table.updateTable(this.id, this.pageConfig[this.id]?.table, this.pageFilters.app, this.data);
}
// Update the summary with the latest data for all categories
@@ -142,8 +142,8 @@ class Timeseries {
const timeseries = this.defaults(config);
// Accessibility settings
- if(config.caption) {
- timeseries.caption = {
+ if(config && config.caption) {
+ timeseries['caption'] = {
text: config.caption,
};
}
@@ -158,18 +158,18 @@ class Timeseries {
// General styling
timeseries.chart = {
...timeseries.chart,
- height: config.height,
+ height: config?.height,
};
// Axis settings
timeseries.yAxis = {
...timeseries.yAxis,
- tickAmount: config.yAxis.tickAmount,
+ tickAmount: config?.yAxis?.tickAmount,
}
timeseries.xAxis = {
...timeseries.xAxis,
- tickAmount: config.xAxis.tickAmount,
+ tickAmount: config?.xAxis?.tickAmount,
}
// Update the data
@@ -183,7 +183,22 @@ class Timeseries {
// Format the data in the format Highcharts needs it to be
formatSeries() {
- return this.formatDataByClient();
+ const breakdown = this.pageConfig?.config?.default?.series?.breakdown;
+ switch(breakdown) {
+ case 'client':
+ this.formatDataByClient();
+ break;
+ case 'app':
+ this.formatDataByApp();
+ break;
+ default:
+ console.log('unknown breakdown');
+ break;
+ }
+ }
+
+ // Format the data broken down by app
+ formatDataByApp() {
}
// Format the data broken down by client
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index ccf6bc89..6ef0c88d 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -18,146 +18,94 @@
-
-
- Client
-
- Mobile
- Desktop
-
-
+
+ Client
+
+ Mobile
+ Desktop
+
+
-
-
-
Comparing {{ technologies | length }} technologies
-
Description
-
-
-
+
+
+
+
Summary ({{ technologies | length }} technologies)
+
+ Todo
+ {% include "techreport/components/filter_meta.html" %}
-
-
Adoption
+
+
+
Core Web Vitals
Description
+
-
Origins
-
Explanation
-
-
- The origins over time, compared for the selected technologies.
-
-
+ {% set timeseries = tech_report_page.config.good_cwv_timeseries %}
+ {% if timeseries %}
+ {% set subcategory = request.args.get('good-cwv-over-time', '') or 'cwv' %}
+ {% include "techreport/components/timeseries.html" %}
+ {% endif %}
-
-
Core Web Vitals
+
+
+
Lighthouse
Description
+
-
Good Core Web Vitals
-
Explanation
-
-
- The amount of good core web vitals over time, compared for the selected technologies.
-
-
- Subcategory
-
- Overall CWVs
- LCP
- FID
- CLS
- FCP
- TTFB
- INP
-
-
-
+
-
-
Lighthouse
+
+
+
Page weight
Description
+
-
Median Lighthouse Performance
-
Explanation
-
-
- The lighthouse scores over time, compared for the selected technologies.
-
-
- Subcategory
-
- Performance
- Accessibility
- PWA
- SEO
- Best practices
-
-
-
+
-
-
Page weight
+
+
+
Adoption
Description
+
-
Median bytes total
-
Explanation
-
-
- The page weight over time, compared for the selected technologies.
-
- Subcategory
-
- Subcategory
-
- Image weight
- Javascript transfer size
- Total page weight
-
-
-
+
diff --git a/templates/techreport/comparison_backup.html b/templates/techreport/comparison_backup.html
new file mode 100644
index 00000000..ccf6bc89
--- /dev/null
+++ b/templates/techreport/comparison_backup.html
@@ -0,0 +1,165 @@
+{% extends "techreport/report.html" %}
+
+{% block section %}
+ {{ super() }}
+
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% set technologies_str = ','.join(technologies) %}
+
+
+
+
+ Tech Report
+ Comparison
+
+
+
+ {% include "techreport/templates/filters.html" %}
+
+
+
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
+
+
+
+
Comparing {{ technologies | length }} technologies
+
Description
+
+
+
+
+
+
+
+
Adoption
+
Description
+
+
+
Origins
+
Explanation
+
+
+ The origins over time, compared for the selected technologies.
+
+
+
+
+
+
+
Core Web Vitals
+
Description
+
+
+
Good Core Web Vitals
+
Explanation
+
+
+ The amount of good core web vitals over time, compared for the selected technologies.
+
+
+ Subcategory
+
+ Overall CWVs
+ LCP
+ FID
+ CLS
+ FCP
+ TTFB
+ INP
+
+
+
+
+
+
+
+
Lighthouse
+
Description
+
+
+
Median Lighthouse Performance
+
Explanation
+
+
+ The lighthouse scores over time, compared for the selected technologies.
+
+
+ Subcategory
+
+ Performance
+ Accessibility
+ PWA
+ SEO
+ Best practices
+
+
+
+
+
+
+
+
Page weight
+
Description
+
+
+
Median bytes total
+
Explanation
+
+
+ The page weight over time, compared for the selected technologies.
+
+ Subcategory
+
+ Subcategory
+
+ Image weight
+ Javascript transfer size
+ Total page weight
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/templates/techreport/components/table.html b/templates/techreport/components/table.html
index b42fb07f..1ff45857 100644
--- a/templates/techreport/components/table.html
+++ b/templates/techreport/components/table.html
@@ -5,22 +5,41 @@
id="table-{{ id }}"
class="table-ui"
data-client="{{ client }}"
+ data-breakdown="{{ tech_report_page.config.default.series.breakdown }}"
>
{{ table.caption }}
{% for column in table.columns %}
-
- {{ column.name }}
- {% if column.hiddenSuffix %}
-
- {{ column.hiddenSuffix }}
-
- {% endif %}
-
+ {% if column.breakdown == 'app' %}
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% for app in technologies %}
+
+ {{ app }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
+ {% endfor %}
+ {% else %}
+
+ {{ column.name }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
+ {% endif %}
{% endfor %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index f2120cd0..3ba9fb53 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -117,7 +117,7 @@
{{ tech_report_page.config.weight_summary.title }}
{% endif %}
-
+
{% set timeseries = tech_report_page.config.weight_timeseries %}
{% include "techreport/components/timeseries.html" %}
From d457499bdbc0e7474ecb0d350aae029fde9a4d8d Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 30 Sep 2023 02:25:33 +0200
Subject: [PATCH 078/155] add comparison tables to all metrics
---
config/techreport.json | 130 +++++++++++++-
src/js/techreport/table.js | 8 -
templates/techreport/comparison.html | 23 ++-
templates/techreport/comparison_backup.html | 165 ------------------
.../techreport/components/timeseries.html | 36 ++--
5 files changed, 165 insertions(+), 197 deletions(-)
delete mode 100644 templates/techreport/comparison_backup.html
diff --git a/config/techreport.json b/config/techreport.json
index 6481b532..7ef8c503 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -714,7 +714,7 @@
},
{
"key": "pct_good_*subcategory*",
- "name": "App",
+ "name": "Good scores",
"breakdown": "app",
"suffix": "%",
"className": "main-cell pct-value"
@@ -726,6 +726,134 @@
}
]
}
+ },
+ "lighthouse_timeseries": {
+ "title": "Lighthouse over time",
+ "description": "Placeholder text",
+ "id": "lighthouse_timeseries",
+ "subcategory": {
+ "base": "median_lighthouse_score_",
+ "param": "median-lighthouse-over-time",
+ "default": "performance",
+ "options": [
+ {
+ "label": "Performance",
+ "value": "performance"
+ },
+ {
+ "label": "Accessibility",
+ "value": "accessibility"
+ },
+ {
+ "label": "SEO (Search Engine Optimisation)",
+ "value": "seo"
+ },
+ {
+ "label": "PWA (Progressive Web Apps)",
+ "value": "pwa"
+ },
+ {
+ "label": "Best practices",
+ "value": "best_practices"
+ }
+ ]
+ },
+ "table": {
+ "param": "median-lighthouse-over-time",
+ "default": "performance",
+ "caption": "Lighthouse placeholder",
+ "columns": [
+ {
+ "key": "date",
+ "name": "Date",
+ "type": "heading"
+ },
+ {
+ "key": "median_lighthouse_score_*subcategory*",
+ "name": "Median lighthouse score",
+ "breakdown": "app",
+ "className": "main-cell"
+ },
+ {
+ "key": "client",
+ "name": "Client",
+ "className": "client"
+ }
+ ]
+ }
+ },
+ "weight_timeseries": {
+ "title": "Page weight over time",
+ "description": "Placeholder text",
+ "id": "weight_timeseries",
+ "subcategory": {
+ "base": "median_bytes_",
+ "param": "median-weight-over-time",
+ "default": "performance",
+ "options": [
+ {
+ "label": "Image weight",
+ "value": "image"
+ },
+ {
+ "label": "JavaScript transfer size",
+ "value": "js"
+ },
+ {
+ "label": "Total page weight",
+ "value": "total"
+ }
+ ]
+ },
+ "table": {
+ "param":"median-weight-over-time",
+ "default": "image",
+ "caption": "Weight",
+ "columns": [
+ {
+ "name": "Date",
+ "key": "date"
+ },
+ {
+ "name": "Median Bytes",
+ "key": "median_bytes_*subcategory*",
+ "suffix": "kB",
+ "className": "main-cell",
+ "breakdown": "app"
+ },
+ {
+ "name": "Client",
+ "key": "client",
+ "className": "client"
+ }
+ ]
+ }
+ },
+ "adoption_timeseries": {
+ "title": "Origins over time",
+ "description": "Placeholder text",
+ "id": "adoption_timeseries",
+ "table": {
+ "param":"",
+ "caption": "Adoption",
+ "columns": [
+ {
+ "name": "Date",
+ "key": "date"
+ },
+ {
+ "name": "Usage",
+ "key": "origins",
+ "className": "main-cell",
+ "breakdown": "app"
+ },
+ {
+ "name": "Client",
+ "key": "client",
+ "className": "client"
+ }
+ ]
+ }
}
},
"description": "Comparison placeholder"
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index 3a197afc..b3bcd3dd 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -45,8 +45,6 @@ function formatData(tableConfig, data) {
table.push(row);
}
- console.log(table);
-
return table;
}
@@ -87,8 +85,6 @@ function updateTable(id, config, apps, data) {
// Reset what's in the table before adding new content
tbody.innerHTML = '';
- // console.log('update table', id, data);
-
const tableConfig = {
id,
config,
@@ -97,15 +93,11 @@ function updateTable(id, config, apps, data) {
const rows = formatData(tableConfig, data);
- console.log('rows', rows);
-
rows?.forEach(row => {
const entry = row;
const tr = document.createElement('tr');
- console.log('row', row);
-
row?.forEach(column => {
const cellType = column.type === "heading" ? 'th' : 'td';
let cell = document.createElement(cellType);
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 6ef0c88d..8706c52d 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -73,7 +73,11 @@ Lighthouse
-
+ {% set timeseries = tech_report_page.config.lighthouse_timeseries %}
+ {% if timeseries %}
+ {% set subcategory = request.args.get('median-lighthouse-over-time', '') or 'performance' %}
+ {% include "techreport/components/timeseries.html" %}
+ {% endif %}
@@ -89,7 +93,11 @@
Page weight
-
+ {% set timeseries = tech_report_page.config.weight_timeseries %}
+ {% if timeseries %}
+ {% set subcategory = request.args.get('median-weight-over-time', '') or 'image' %}
+ {% include "techreport/components/timeseries.html" %}
+ {% endif %}
@@ -103,10 +111,13 @@
Page weight
Adoption
Description
-
-
-
-
+
+
+ {% set timeseries = tech_report_page.config.adoption_timeseries %}
+ {% if timeseries %}
+ {% include "techreport/components/timeseries.html" %}
+ {% endif %}
+
diff --git a/templates/techreport/comparison_backup.html b/templates/techreport/comparison_backup.html
deleted file mode 100644
index ccf6bc89..00000000
--- a/templates/techreport/comparison_backup.html
+++ /dev/null
@@ -1,165 +0,0 @@
-{% extends "techreport/report.html" %}
-
-{% block section %}
- {{ super() }}
-
- {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
- {% set technologies_str = ','.join(technologies) %}
-
-
-
-
- Tech Report
- Comparison
-
-
-
- {% include "techreport/templates/filters.html" %}
-
-
-
-
-
- Client
-
- Mobile
- Desktop
-
-
-
-
-
-
Comparing {{ technologies | length }} technologies
-
Description
-
-
-
-
-
-
-
-
Adoption
-
Description
-
-
-
Origins
-
Explanation
-
-
- The origins over time, compared for the selected technologies.
-
-
-
-
-
-
-
Core Web Vitals
-
Description
-
-
-
Good Core Web Vitals
-
Explanation
-
-
- The amount of good core web vitals over time, compared for the selected technologies.
-
-
- Subcategory
-
- Overall CWVs
- LCP
- FID
- CLS
- FCP
- TTFB
- INP
-
-
-
-
-
-
-
-
Lighthouse
-
Description
-
-
-
Median Lighthouse Performance
-
Explanation
-
-
- The lighthouse scores over time, compared for the selected technologies.
-
-
- Subcategory
-
- Performance
- Accessibility
- PWA
- SEO
- Best practices
-
-
-
-
-
-
-
-
Page weight
-
Description
-
-
-
Median bytes total
-
Explanation
-
-
- The page weight over time, compared for the selected technologies.
-
- Subcategory
-
- Subcategory
-
- Image weight
- Javascript transfer size
- Total page weight
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index e73e4cf6..b0c3e7dc 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -23,24 +23,26 @@
{{ title }}
- {% if timeseries.summary %}
-
-
-
- Latest data:
-
+ {% if timeseries.viz %}
+ {% if timeseries.summary %}
+
+
+
+ Latest data:
+
+
+
+ {% if timeseries.viz.series.breakdown == 'client' %}
+ {% for breakdown in timeseries.viz.series["values"] %}
+
+
{{ breakdown.name }}
+
00{% if breakdown.suffix == "%" %}.00{% endif %}{{ breakdown.suffix }}
+
+ {% endfor %}
+ {% endif %}
+
-
- {% if timeseries.viz.series.breakdown == 'client' %}
- {% for breakdown in timeseries.viz.series["values"] %}
-
-
{{ breakdown.name }}
-
00{% if breakdown.suffix == "%" %}.00{% endif %}{{ breakdown.suffix }}
-
- {% endfor %}
- {% endif %}
-
-
+ {% endif %}
{% endif %}
From a88d90115d3e2b98464fc96ce4388b5bd5904faa Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 30 Sep 2023 02:39:14 +0200
Subject: [PATCH 079/155] readd line charts on drilldown
---
src/js/techreport/timeseries.js | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index aaa690c5..57673e5d 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -71,6 +71,7 @@ class Timeseries {
// Re-render the contents of the component
updateContent() {
+ console.log('update content');
if(this.pageConfig[this.id]?.summary) {
this.updateSummary();
}
@@ -138,6 +139,7 @@ class Timeseries {
// Update the highcharts timeseries
updateViz() {
+ console.log('update the viz');
const config = this.pageConfig[this.id]?.viz;
const timeseries = this.defaults(config);
@@ -177,20 +179,24 @@ class Timeseries {
timeseries.series = this.formatSeries();
}
+ console.log('this.data', this.data);
+ console.log('formatSeries', this.formatSeries());
+
// Render the chart
Highcharts.chart(`${this.id}-timeseries`, timeseries);
}
// Format the data in the format Highcharts needs it to be
formatSeries() {
- const breakdown = this.pageConfig?.config?.default?.series?.breakdown;
+ const breakdown = this.pageConfig?.default?.series?.breakdown;
+ let series;
switch(breakdown) {
case 'client':
- this.formatDataByClient();
- break;
+ series = this.formatDataByClient();
+ return series;
case 'app':
- this.formatDataByApp();
- break;
+ series = this.formatDataByApp();
+ return series;
default:
console.log('unknown breakdown');
break;
From a7a8261583059f83ef5da71464fc69699b4b7c6c Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 30 Sep 2023 23:33:45 +0200
Subject: [PATCH 080/155] WIP: add possibility for timeseries broken down by
app
---
src/js/techreport/timeseries.js | 46 +++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 5 deletions(-)
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 57673e5d..e7aa3f58 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -71,7 +71,6 @@ class Timeseries {
// Re-render the contents of the component
updateContent() {
- console.log('update content');
if(this.pageConfig[this.id]?.summary) {
this.updateSummary();
}
@@ -139,7 +138,6 @@ class Timeseries {
// Update the highcharts timeseries
updateViz() {
- console.log('update the viz');
const config = this.pageConfig[this.id]?.viz;
const timeseries = this.defaults(config);
@@ -179,9 +177,6 @@ class Timeseries {
timeseries.series = this.formatSeries();
}
- console.log('this.data', this.data);
- console.log('formatSeries', this.formatSeries());
-
// Render the chart
Highcharts.chart(`${this.id}-timeseries`, timeseries);
}
@@ -205,6 +200,47 @@ class Timeseries {
// Format the data broken down by app
formatDataByApp() {
+ console.log(this.id, 'we will format by app here', this.data);
+ const series = [];
+
+ // Get the viz settings
+ const config = this.pageConfig[this.id]?.viz;
+
+ // The default metric from the settings
+ const defaultMetric = config?.metric;
+
+ // Get the submetric from the URL
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config?.param);
+
+ // By default, we use the metric from the settings
+ let metric = defaultMetric;
+
+ // If the subcategory is set, take it from the url
+ if(urlSubcategory) {
+ metric = `${config?.base}${urlSubcategory}`;
+ }
+
+ console.log(this.pageConfig);
+ console.log(this.pageFilters);
+
+ Object.values(this.data).forEach(app => {
+ const data = app.filter(row => row.client === 'mobile').map(row => {
+ return {
+ x: new Date(row.date),
+ y: Number(row['origins']),
+ };
+ });
+
+ series.push({
+ name: app[0].app,
+ data: data
+ });
+ });
+ console.log(series);
+
+ return series;
+
}
// Format the data broken down by client
From 0396e1d9fdaec026e2e5274b6bec91f794d519ee Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 1 Oct 2023 01:41:58 +0200
Subject: [PATCH 081/155] update metric/client in timeseries (code cleanup
needed)
---
config/techreport.json | 77 +++++++++++++++++++
src/js/techreport/timeseries.js | 10 +--
.../techreport/components/timeseries.html | 2 +-
3 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 7ef8c503..865db17d 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -725,6 +725,26 @@
"className": "client"
}
]
+ },
+ "viz": {
+ "title": "Origins with good core web vitals over time",
+ "base": "pct_good_",
+ "param": "good-cwv-over-time",
+ "default": "cwv",
+ "metric": "pct_good_cwv",
+ "series": {
+ "breakdown": "app",
+ "defaults": [
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
+ }
}
},
"lighthouse_timeseries": {
@@ -780,6 +800,26 @@
"className": "client"
}
]
+ },
+ "viz": {
+ "title": "Lighthouse scores over time",
+ "base": "median_lighthouse_score_",
+ "param": "median-lighthouse-over-time",
+ "default": "performance",
+ "metric": "median_lighthouse_score_performance",
+ "series": {
+ "breakdown": "app",
+ "defaults": [
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
+ }
}
},
"weight_timeseries": {
@@ -827,6 +867,26 @@
"className": "client"
}
]
+ },
+ "viz": {
+ "title": "Median page weight over time",
+ "base": "median_bytes",
+ "param": "median-weight-over-time",
+ "default": "image",
+ "metric": "median_bytes_image",
+ "series": {
+ "breakdown": "app",
+ "defaults": [
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
+ }
}
},
"adoption_timeseries": {
@@ -853,6 +913,23 @@
"className": "client"
}
]
+ },
+ "viz": {
+ "title": "Origins over time",
+ "metric": "origins",
+ "series": {
+ "breakdown": "app",
+ "defaults": [
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ },
+ {
+ "name": "App",
+ "data": [0,0,0,0,0,0,0,0,0,0,0,0]
+ }
+ ]
+ }
}
}
},
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index e7aa3f58..6671e891 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -200,7 +200,6 @@ class Timeseries {
// Format the data broken down by app
formatDataByApp() {
- console.log(this.id, 'we will format by app here', this.data);
const series = [];
// Get the viz settings
@@ -221,14 +220,14 @@ class Timeseries {
metric = `${config?.base}${urlSubcategory}`;
}
- console.log(this.pageConfig);
- console.log(this.pageFilters);
+ const component = document.querySelector(`[data-id="${this.id}"]`);
+ const client = component.dataset.client;
Object.values(this.data).forEach(app => {
- const data = app.filter(row => row.client === 'mobile').map(row => {
+ const data = app.filter(row => row.client === client).map(row => {
return {
x: new Date(row.date),
- y: Number(row['origins']),
+ y: Number(row[metric]),
};
});
@@ -237,7 +236,6 @@ class Timeseries {
data: data
});
});
- console.log(series);
return series;
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index b0c3e7dc..e28cbc7d 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -1,4 +1,4 @@
-
+
{% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
From 3ff8d01f21162fa0320ee2d2d7821bf5ba7865a7 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 1 Oct 2023 03:00:41 +0200
Subject: [PATCH 082/155] add support for timeseries summary in comparison mode
(wip)
---
config/techreport.json | 2 +
src/js/techreport/timeseries.js | 97 +++++++++++++------
static/css/techreport/techreport.css | 3 +
.../techreport/components/timeseries.html | 7 ++
4 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 865db17d..7bff5664 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -726,6 +726,7 @@
}
]
},
+ "summary": true,
"viz": {
"title": "Origins with good core web vitals over time",
"base": "pct_good_",
@@ -734,6 +735,7 @@
"metric": "pct_good_cwv",
"series": {
"breakdown": "app",
+ "suffix": "%",
"defaults": [
{
"name": "App",
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 6671e891..cfd735e2 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -81,6 +81,19 @@ class Timeseries {
// Update the summary with the latest data for all categories
// TODO: only works this way in the single tech, for comparison we need to do this differently
updateSummary() {
+ console.log(this.pageConfig);
+ console.log(this.data);
+ switch(this.pageConfig.default.series.breakdown) {
+ case 'client':
+ this.updateClientSummary();
+ break;
+ case 'app':
+ this.updateAppSummary();
+ break;
+ }
+ }
+
+ updateClientSummary() {
const config = this.pageConfig[this.id]?.viz;
const data = this.data;
const id = this.id;
@@ -133,6 +146,42 @@ class Timeseries {
container.appendChild(itemWrapper);
});
}
+ }
+
+ updateAppSummary() {
+ console.log('app summary');
+ const config = this.pageConfig[this.id]?.viz;
+ const data = this.data;
+ const id = this.id;
+ const pageFilters = this.pageFilters;
+
+ const metric = this.getMetric(config);
+ const component = document.querySelector(`[data-id="${this.id}"]`);
+ const client = component.dataset.client;
+ const container = component.querySelector('.breakdown-list');
+
+ // console.log(this.data);
+
+ pageFilters.app.forEach(app => {
+ const sorted = data?.[app]?.sort((a, b) => new Date(b.date) - new Date(a.date));
+
+ if(sorted && sorted.length > 0) {
+ const filtered = sorted?.filter(row => row.client === client);
+ const latest = filtered[0];
+
+ /* Select the container to which we'll add elements. */
+ const card = container.querySelector(`[data-app="${app}"]`);
+ const timestamp = component.querySelector('[data-slot="timestamp"]');
+ const label = card.getElementsByClassName('breakdown-label')[0];
+ const value = card.getElementsByClassName('breakdown-value')[0];
+
+ /* Update text */
+ label.innerHTML = latest.app;
+ value.innerHTML = `${latest[metric]}${config.series.suffix || ''}`;
+ timestamp.innerHTML = latest.date;
+
+ }
+ })
}
@@ -194,7 +243,7 @@ class Timeseries {
return series;
default:
console.log('unknown breakdown');
- break;
+ return;
}
}
@@ -204,22 +253,9 @@ class Timeseries {
// Get the viz settings
const config = this.pageConfig[this.id]?.viz;
+ const metric = this.getMetric(config);
- // The default metric from the settings
- const defaultMetric = config?.metric;
-
- // Get the submetric from the URL
- const urlParams = new URLSearchParams(window.location.search);
- const urlSubcategory = urlParams.get(config?.param);
-
- // By default, we use the metric from the settings
- let metric = defaultMetric;
-
- // If the subcategory is set, take it from the url
- if(urlSubcategory) {
- metric = `${config?.base}${urlSubcategory}`;
- }
-
+ // Get the selected client
const component = document.querySelector(`[data-id="${this.id}"]`);
const client = component.dataset.client;
@@ -233,12 +269,11 @@ class Timeseries {
series.push({
name: app[0].app,
- data: data
+ data: data,
});
});
return series;
-
}
// Format the data broken down by client
@@ -250,20 +285,7 @@ class Timeseries {
const config = this.pageConfig[this.id]?.viz;
const app = this.pageFilters.app[0];
- // The default metric from the settings
- const defaultMetric = config.metric;
-
- // Get the submetric from the URL
- const urlParams = new URLSearchParams(window.location.search);
- const urlSubcategory = urlParams.get(config.param);
-
- // By default, we use the metric from the settings
- let metric = defaultMetric;
-
- // If the subcategory is set, take it from the url
- if(urlSubcategory) {
- metric = `${config.base}${urlSubcategory}`;
- }
+ const metric = this.getMetric(config);
// Breakdown data by categories defined in config
config?.series?.values?.forEach((value, index) => {
@@ -295,6 +317,17 @@ class Timeseries {
return series;
}
+ getMetric(config) {
+ // The default metric from the settings
+ const defaultMetric = config.metric;
+
+ // Get the submetric from the URL
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+
+ return urlSubcategory ? `${config.base}${urlSubcategory}` : defaultMetric;
+ }
+
// Get the default settings
defaults(config) {
const defaults = {
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index fa6329d3..f11530aa 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -32,6 +32,9 @@
--graph-color-primary-darker: var(--color-teal-darker);
--graph-color-line: #A6BBBE;
--graph-color-labels: #62777B;
+
+ /* Defaults */
+ --breakdown-color: var(--color-text);
}
/* ------------------------- */
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index e28cbc7d..21428cc7 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -39,6 +39,13 @@
00{% if breakdown.suffix == "%" %}.00{% endif %}{{ breakdown.suffix }}
{% endfor %}
+ {% elif timeseries.viz.series.breakdown == 'app' %}
+ {% for app in tech_report_page.filters.app %}
+
+
{{ app }}
+
00{{ timeseries.viz.series.suffix }}
+
+ {% endfor %}
{% endif %}
From 600addb99af3bfc3014994f0ed7edacd7625c2c6 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 1 Oct 2023 03:02:52 +0200
Subject: [PATCH 083/155] add summary to all metrics (code cleanup needed)
---
config/techreport.json | 4 ++++
src/js/techreport/timeseries.js | 5 -----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 7bff5664..19eba485 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -803,6 +803,7 @@
}
]
},
+ "summary": true,
"viz": {
"title": "Lighthouse scores over time",
"base": "median_lighthouse_score_",
@@ -870,6 +871,7 @@
}
]
},
+ "summary": true,
"viz": {
"title": "Median page weight over time",
"base": "median_bytes",
@@ -878,6 +880,7 @@
"metric": "median_bytes_image",
"series": {
"breakdown": "app",
+ "suffix": " kB",
"defaults": [
{
"name": "App",
@@ -916,6 +919,7 @@
}
]
},
+ "summary": true,
"viz": {
"title": "Origins over time",
"metric": "origins",
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index cfd735e2..e2f1bbe4 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -81,8 +81,6 @@ class Timeseries {
// Update the summary with the latest data for all categories
// TODO: only works this way in the single tech, for comparison we need to do this differently
updateSummary() {
- console.log(this.pageConfig);
- console.log(this.data);
switch(this.pageConfig.default.series.breakdown) {
case 'client':
this.updateClientSummary();
@@ -149,7 +147,6 @@ class Timeseries {
}
updateAppSummary() {
- console.log('app summary');
const config = this.pageConfig[this.id]?.viz;
const data = this.data;
const id = this.id;
@@ -160,8 +157,6 @@ class Timeseries {
const client = component.dataset.client;
const container = component.querySelector('.breakdown-list');
- // console.log(this.data);
-
pageFilters.app.forEach(app => {
const sorted = data?.[app]?.sort((a, b) => new Date(b.date) - new Date(a.date));
From 4afc0260bc1da9f876ffb83317d19544d3b9b3f7 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 1 Oct 2023 03:54:33 +0200
Subject: [PATCH 084/155] add color to comparison timeseries and summary
(bugfixes/cleanup needed)
---
src/js/techreport/table.js | 2 +-
src/js/techreport/timeseries.js | 15 +++++++++++----
templates/techreport/comparison.html | 4 ++--
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index b3bcd3dd..06405d4a 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -60,7 +60,7 @@ function getColumnCell(columnConfig, data, rowNr) {
const cell = {
...column,
formattedKey: key,
- value: _data[rowNr][key],
+ value: _data?.[rowNr]?.[key],
app: app
};
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index e2f1bbe4..8bf11cf6 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -157,7 +157,9 @@ class Timeseries {
const client = component.dataset.client;
const container = component.querySelector('.breakdown-list');
- pageFilters.app.forEach(app => {
+ const colors = this.defaults(config)?.chart?.colors;
+
+ pageFilters.app.forEach((app, index) => {
const sorted = data?.[app]?.sort((a, b) => new Date(b.date) - new Date(a.date));
if(sorted && sorted.length > 0) {
@@ -174,7 +176,7 @@ class Timeseries {
label.innerHTML = latest.app;
value.innerHTML = `${latest[metric]}${config.series.suffix || ''}`;
timestamp.innerHTML = latest.date;
-
+ card.style.setProperty('--breakdown-color', colors[index]);
}
})
@@ -254,7 +256,9 @@ class Timeseries {
const component = document.querySelector(`[data-id="${this.id}"]`);
const client = component.dataset.client;
- Object.values(this.data).forEach(app => {
+ const colors = this.defaults(config)?.chart?.colors;
+
+ Object.values(this.data).forEach((app, index) => {
const data = app.filter(row => row.client === client).map(row => {
return {
x: new Date(row.date),
@@ -265,6 +269,7 @@ class Timeseries {
series.push({
name: app[0].app,
data: data,
+ color: colors[index]
});
});
@@ -298,6 +303,8 @@ class Timeseries {
});
});
+ const colors = this.defaults(config)?.chart?.colors;
+
// Push the configurations and formatted data to the series array
series.push(
{
@@ -328,7 +335,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: ['#070746', '#157F56', '#C9200D', '#AA0DC9'],
+ colors: ['#070746', '#157F56', 'orange', 'pink', 'gray', 'teal', '#C9200D', '#AA0DC9'],
},
title: {
text: config?.title,
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 8706c52d..d49ec0cf 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -28,7 +28,7 @@
-
Summary ({{ technologies | length }} technologies)
Todo
{% include "techreport/components/filter_meta.html" %}
-
+ -->
Date: Wed, 4 Oct 2023 03:26:49 +0200
Subject: [PATCH 085/155] update color codes
---
config/techreport.json | 4 ++--
src/js/techreport/timeseries.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 19eba485..2942f29f 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -76,12 +76,12 @@
"breakdown_values": [
{
"name": "desktop",
- "color": "#449BC6",
+ "color": "#41807D",
"suffix": "%"
},
{
"name": "mobile",
- "color": "#AF5AB6",
+ "color": "#B5307F",
"suffix": "%"
}
]
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 8bf11cf6..c48143e0 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -335,7 +335,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: ['#070746', '#157F56', 'orange', 'pink', 'gray', 'teal', '#C9200D', '#AA0DC9'],
+ colors: ['#DC267F', '#785EF0', '#FE6100', '#309C87', '#4E2C8E', '#AB8938', '#CC79A7', '#AA4499', '#C48236'],
},
title: {
text: config?.title,
From 0e33b153d8708c6df5e116c8aeebba46348035ec Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 4 Oct 2023 03:30:35 +0200
Subject: [PATCH 086/155] removed unused code
---
server/techreport.py | 88 --------------------------------------------
1 file changed, 88 deletions(-)
diff --git a/server/techreport.py b/server/techreport.py
index 22174f50..6730d0c9 100644
--- a/server/techreport.py
+++ b/server/techreport.py
@@ -1,5 +1,4 @@
import json
-import requests
def update_report():
@@ -8,44 +7,6 @@ def update_report():
tech_report_json = json.load(tech_report_file)
-def get_technologies():
- try:
- response = requests.get(
- "https://cdn.httparchive.org/reports/cwvtech/technologies.json"
- )
- technologies = response.json()
- return technologies
-
- except Exception as error:
- # In the future: we could expand this to have a local fallback list of allowed technologies
- print(error)
- return []
-
-
-def get_geos():
- try:
- response = requests.get(
- "https://cdn.httparchive.org/reports/cwvtech/geos.json"
- )
- geos = response.json()
- return geos
- except Exception as error:
- print(error)
- return []
-
-
-def get_ranks():
- try:
- response = requests.get(
- "https://cdn.httparchive.org/reports/cwvtech/ranks.json"
- )
- ranks = response.json()
- return ranks
- except Exception as error:
- print(error)
- return []
-
-
def get_report():
global tech_report_json
update_report()
@@ -53,53 +14,4 @@ def get_report():
return tech_report_json
-def get_metrics(technology, filters):
- global report_data
-
- try:
- response = requests.get(
- "https://cdn.httparchive.org/reports/cwvtech/%s/%s/%s.json"
- % (filters["rank"], filters["geo"], technology)
- )
- report_data = response.json()
- for entry in report_data:
- entry["pct_good_cwv"] = round(int(entry["origins_with_good_cwv"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_fid"] = round(int(entry["origins_with_good_fid"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_cls"] = round(int(entry["origins_with_good_cls"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_lcp"] = round(int(entry["origins_with_good_lcp"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_fcp"] = round(int(entry["origins_with_good_fcp"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_ttfb"] = round(int(entry["origins_with_good_lcp"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
- entry["pct_good_inp"] = round(int(entry["origins_with_good_inp"]) / int(entry["origins_eligible_for_cwv"]) * 100.0, 2)
-
- return report_data
-
- except Exception as error:
- print(error)
- return []
-
-
-def get_request_values(request, key, allowed_values):
- request_value = request.args.get(key) or "ALL"
- if allowed_values and len(allowed_values) > 0:
- _value = request_value.replace(" ", "-").lower()
- updated_value = [
- option
- for option in allowed_values
- if option[key].replace(" ", "-").lower() == _value
- ]
- if updated_value:
- updated_value = updated_value[0][key]
- updated_value = updated_value.replace(" ", "-")
-
- return updated_value or request_value
-
-
-def get_requested_technologies(request, allowed_values):
- tech_arr = []
- requested_tech = get_request_values(request, "app", allowed_values)
- if requested_tech:
- tech_arr = requested_tech.split(",")
- return tech_arr
-
-
update_report()
From fdb8718308709469cb5771330889d647b58ccaab Mon Sep 17 00:00:00 2001
From: Rick Viscomi
Date: Tue, 10 Oct 2023 14:59:11 -0400
Subject: [PATCH 087/155] staging script
---
config/last_updated.json | 95 ++++++++++++++++++++++++++++++++++++++++
package.json | 2 +-
2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/config/last_updated.json b/config/last_updated.json
index 75d622c1..4ef4d9b6 100644
--- a/config/last_updated.json
+++ b/config/last_updated.json
@@ -1,4 +1,14 @@
{
+ "/static/components/summary.css": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "304aa7ab9c39f9eb730f4f9de0261652"
+ },
+ "/static/components/table.css": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "56bd14f21cf53b601d86be0061ae7baa"
+ },
"/static/css/bootstrap.min.css": {
"date_published": "2018-05-08T00:00:00.000Z",
"date_modified": "2021-04-23T00:00:00.000Z",
@@ -29,6 +39,36 @@
"date_modified": "2023-04-26T00:00:00.000Z",
"hash": "1d22c6afc3a451844da89684d7ad84ef"
},
+ "/static/css/techreport/general.css": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "53dd766b1d280387b36a2c3ead47e68c"
+ },
+ "/static/css/techreport/landing.css": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "804dc15c1ed6962ae75a2b189de56148"
+ },
+ "/static/css/techreport/techreport.css": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "82ad10c0e3231f9a2e44f54007b1bda7"
+ },
+ "/static/js/accessibility.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "cf1af15492a3443d875cffaf34cd97fe"
+ },
+ "/static/js/accessibility.js.map": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "c2cbce2ba7a3898335fde135b24e301d"
+ },
+ "/static/js/export-data.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "7f994d8425277b2e3e05f062c8c497c1"
+ },
"/static/js/exporting.js": {
"date_published": "2021-05-19T00:00:00.000Z",
"date_modified": "2023-04-26T00:00:00.000Z",
@@ -54,6 +94,11 @@
"date_modified": "2023-04-26T00:00:00.000Z",
"hash": "8d31b26d9fd75b9f2749cf0fc652fb34"
},
+ "/static/js/highcharts.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "7517a72a4be7d8cb449462dfd7c3cf34"
+ },
"/static/js/highstock.js": {
"date_published": "2021-04-26T00:00:00.000Z",
"date_modified": "2023-04-26T00:00:00.000Z",
@@ -89,6 +134,51 @@
"date_modified": "2022-08-25T00:00:00.000Z",
"hash": "8326eed37a5ccead13f6d58ea19716fc"
},
+ "/static/js/summaryLinked.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "b00f52e619f9aa6b965ebe2a49b6fd23"
+ },
+ "/static/js/tableCWVOverviewMulti.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "ab2994dc074ff02e055c5fb5c8df988b"
+ },
+ "/static/js/tableGeneral.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "d2317a0b43a4c04a86723b178dfedf2c"
+ },
+ "/static/js/tableGeneralMulti.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "62b2c943393389849758cc3d7ff7be5b"
+ },
+ "/static/js/tableOverview.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "0a9bf98ecfeeb9594fde313ae8ab8edb"
+ },
+ "/static/js/tableOverviewMulti.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "6d90ac2a5081aebcf8377f37dc2d98dc"
+ },
+ "/static/js/techreport.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "41063b92eb8850bde7a49af891037f22"
+ },
+ "/static/js/techreport/section.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "fa7b58407c44adfc374711c767522ff4"
+ },
+ "/static/js/techreport/timeseries.js": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "85a82b40a1082f03dda77c5956c57d8e"
+ },
"/static/js/timeseries.js": {
"date_published": "2018-05-08T00:00:00.000Z",
"date_modified": "2023-04-26T00:00:00.000Z",
@@ -134,6 +224,11 @@
"date_modified": "2021-09-20T00:00:00.000Z",
"hash": "f063ced5899d6334168c77ddd407afd8"
},
+ "reports/cwv-tech-new": {
+ "date_published": "2023-10-09T00:00:00.000Z",
+ "date_modified": "2023-10-09T00:00:00.000Z",
+ "hash": "1c32b48207473a10ad996bb6fa245144"
+ },
"reports/loading-speed": {
"date_published": "2018-05-08T00:00:00.000Z",
"date_modified": "2021-12-05T00:00:00.000Z",
diff --git a/package.json b/package.json
index 8aaa87a3..caf80f49 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"start": "run-script-os",
"start:darwin:linux": "./tools/scripts/run_and_test_website.sh -d",
"start:win32": "call tools/scripts/run_and_test_website.bat",
- "stage": "npm run build && npm run timestamps && npm run generate && echo \"Y\" | gcloud app deploy --project httparchive-staging",
+ "stage": "npm run build && npm run timestamps && npm run generate && echo \"Y\" | gcloud app deploy --project httparchive --no-promote --version=technology-report",
"testdeploy": "npm run build && npm run timestamps && npm run generate && echo \"Y\" | gcloud app deploy --project httparchive --no-promote",
"deploy": "./tools/scripts/deploy.sh",
"timestamps": "node ./tools/generate/generate_timestamps",
From e1d91c951b58373703eb2b711841e95a0b990123 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 24 Oct 2023 01:53:23 +0200
Subject: [PATCH 088/155] update colors
---
src/js/techreport/timeseries.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index c48143e0..48120f1a 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -335,7 +335,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: ['#DC267F', '#785EF0', '#FE6100', '#309C87', '#4E2C8E', '#AB8938', '#CC79A7', '#AA4499', '#C48236'],
+ colors: ['#5980EB', '#8E3496', '#D55316', '#6AA26F', '#2C2F70', '#B979A7', '#449DB1', '#CB377C', '#AC8D1C', '#742F53'],
},
title: {
text: config?.title,
From 116154b0baeedb3ee0996b029038b781f52a9a4b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 24 Oct 2023 02:04:05 +0200
Subject: [PATCH 089/155] only show markers on hover
---
src/js/techreport/timeseries.js | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 48120f1a..8db74222 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -353,6 +353,17 @@ class Timeseries {
text: config?.yAxis?.title,
},
},
+ plotOptions: {
+ series: {
+ lineWidth: 2,
+ marker: {
+ enabled: false,
+ fillColor: '#ffffff',
+ lineWidth: 2,
+ lineColor: null // inherit from series
+ },
+ },
+ },
};
return defaults;
From a2266d6ff28936d87027fa85f3aa75af185eee87 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 25 Oct 2023 04:12:10 +0200
Subject: [PATCH 090/155] bugfix: show categories correctly when adding more
techs
---
src/js/components/filters.js | 27 +++++++++++++++++--
src/js/techreport/timeseries.js | 2 +-
.../techreport/templates/selector_tech.html | 2 +-
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 454c212c..f34bd983 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -125,9 +125,11 @@ function updateRank(ranks, filters) {
/* Update the list with categories */
function updateCategories(categories, filters) {
+ console.log('try to update categories', categories);
const select = document.querySelector('select#categories');
if(categories) {
+ console.log(categories, 'categories exist, set select stuff', select)
select.innerHTML = '';
const all = document.createElement('option');
@@ -142,16 +144,21 @@ function updateCategories(categories, filters) {
option.dataset.technologies = categories[category].join(',');
select.append(option);
});
+
+ console.log('select when we are done', select);
}
}
/* Set the selected category */
function updateCategory(event) {
+ console.log('update category');
const selectedOption = document.querySelector(`option[value="${event.target.value}"]`);
const selectedTechs = selectedOption.dataset.technologies.split(",");
const techSelector = document.getElementById(event.target.dataset.tech);
techSelector.innerHTML = '';
+ console.log(selectedOption, selectedTechs, techSelector);
+
selectedTechs.forEach((technology) => {
const option = document.createElement('option');
const formattedTech = technology.replaceAll(" ", "-");
@@ -169,18 +176,31 @@ function updateCategory(event) {
function addTechnologySelector(event) {
event.preventDefault();
+ console.log('add a tech selector');
+
const selectorTemplate = document.getElementById('tech-selector').content.cloneNode(true);
- const selectElement = selectorTemplate.querySelector('select');
- const labelElement = selectorTemplate.querySelector('label');
+ const selectElement = selectorTemplate.querySelector('select.tech');
+ const labelElement = selectorTemplate.querySelector('label.tech');
const removeButton = selectorTemplate.querySelector('.remove-tech');
+ const categorySelect = selectorTemplate.querySelector('select.categories-selector');
+ const categoryLabel = selectorTemplate.querySelector('label[for="categories"]');
+ categorySelect.innerHTML = document.querySelector('select.categories-selector').innerHTML;
+ categorySelect.addEventListener('change', updateCategory);
+
+ console.log(selectElement, labelElement);
+
/* Set a unique name on the new element (based on the amount of techs) */
const techId = `tech-${document.querySelectorAll('select.tech[name="tech"]').length + 1}`;
selectElement.setAttribute('id', techId);
labelElement.setAttribute('for', techId);
removeButton.dataset.tech = techId;
+ categorySelect.setAttribute('id', `${techId}-category`);
+ categoryLabel.setAttribute('for', `${techId}-category`);
+ categorySelect.setAttribute('data-tech', techId);
+
removeButton.classList.remove('hidden');
/* Bind functionality to the button */
@@ -190,6 +210,9 @@ function addTechnologySelector(event) {
selectElement.innerHTML = document.querySelector('select.tech').innerHTML;
selectElement.getElementsByTagName('option')[0].selected = true;
+ categorySelect.innerHTML = document.querySelector('select.categories-selector')?.innerHTML;
+ categorySelect.getElementsByTagName('option')[0].selected = true;
+
/* Add the new tech to the end of the list */
const techs = document.getElementsByClassName('tech-selector-group');
const last = techs[techs.length - 1];
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 8db74222..fb4fc05a 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -267,7 +267,7 @@ class Timeseries {
});
series.push({
- name: app[0].app,
+ name: app[0]?.app,
data: data,
color: colors[index]
});
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index 0e413aec..ca942769 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -8,7 +8,7 @@
- Technology
+ Technology
From 19f546f5a76e965aa20f2abe551baf69c0d570c3 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 25 Oct 2023 12:48:36 +0200
Subject: [PATCH 091/155] fill in all category dropdowns
---
src/js/components/filters.js | 38 +++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index f34bd983..68a75c2c 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -126,26 +126,28 @@ function updateRank(ranks, filters) {
/* Update the list with categories */
function updateCategories(categories, filters) {
console.log('try to update categories', categories);
- const select = document.querySelector('select#categories');
+ const selects = document.querySelectorAll('select[name="categories"]');
if(categories) {
- console.log(categories, 'categories exist, set select stuff', select)
- select.innerHTML = '';
-
- const all = document.createElement('option');
- all.value = 'ALL';
- all.innerHTML = 'ALL';
- select.append(all);
-
- Object.keys(categories).forEach((category) => {
- const option = document.createElement('option');
- option.value = category;
- option.innerHTML = category;
- option.dataset.technologies = categories[category].join(',');
- select.append(option);
- });
-
- console.log('select when we are done', select);
+ selects.forEach(select => {
+ console.log(categories, 'categories exist, set select stuff', select)
+ select.innerHTML = '';
+
+ const all = document.createElement('option');
+ all.value = 'ALL';
+ all.innerHTML = 'ALL';
+ select.append(all);
+
+ Object.keys(categories).forEach((category) => {
+ const option = document.createElement('option');
+ option.value = category;
+ option.innerHTML = category;
+ option.dataset.technologies = categories[category].join(',');
+ select.append(option);
+ });
+
+ console.log('select when we are done', select);
+ })
}
}
From 0b3e06366612b7920ef710db1c13a51f96fce050 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 25 Oct 2023 13:36:26 +0200
Subject: [PATCH 092/155] prototype indicator icons on line charts
---
src/js/techreport/index.js | 20 ++++++++++++++++++++
src/js/techreport/timeseries.js | 7 ++++++-
templates/techreport/techreport.html | 3 +++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 5859901f..63522241 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -23,6 +23,7 @@ class TechReport {
// Load the page
this.initializePage();
this.getAllData();
+ this.bindSettingsListeners();
}
// Initialize the sections for the different pages
@@ -75,6 +76,25 @@ class TechReport {
}
}
+ bindSettingsListeners() {
+ const indicatorSetting = document.querySelector('input[name="indicators-check"]');
+ if(indicatorSetting) {
+ indicatorSetting.onchange = (event) => {
+ console.log('change the thing', event, event.target.checked);
+ document.querySelector('main').dataset.showIndicators = event.target.checked;
+
+ console.log('and now here update the charts again');
+
+ Object.values(this.sections).forEach(section => {
+ console.log('loop is working');
+ section.updateSection();
+ });
+
+ console.log('no issues after loop');
+ }
+ }
+ }
+
updateClient(event) {
const client = event.target.value;
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index fb4fc05a..7c3aded8 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -332,6 +332,9 @@ class Timeseries {
// Get the default settings
defaults(config) {
+ console.log('UPDATE', document.querySelector('main').dataset.showIndicators);
+ const showIndicators = document.querySelector('main').dataset.showIndicators === true
+ || document.querySelector('main').dataset.showIndicators === "true";
const defaults = {
type: 'timeseries',
chart: {
@@ -357,7 +360,7 @@ class Timeseries {
series: {
lineWidth: 2,
marker: {
- enabled: false,
+ enabled: showIndicators,
fillColor: '#ffffff',
lineWidth: 2,
lineColor: null // inherit from series
@@ -366,6 +369,8 @@ class Timeseries {
},
};
+ console.log(defaults);
+
return defaults;
}
}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 3b93a441..5e3772c3 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -68,6 +68,9 @@
{% include "techreport/templates/table_overview.html" %}
{% include "techreport/templates/table_cwv_overview_multitech.html" %}
+ Show indicators
+
+
{% endblock %}
From db2acf766ed9cd8fca7b43c944809a98fdc71c6e Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 25 Oct 2023 15:09:58 +0200
Subject: [PATCH 093/155] add colors
---
config/techreport.json | 20 ++++++++++----------
src/js/techreport/timeseries.js | 2 +-
templates/techreport/techreport.html | 2 +-
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 2942f29f..461e239e 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -76,12 +76,12 @@
"breakdown_values": [
{
"name": "desktop",
- "color": "#41807D",
+ "color": "#669E8E",
"suffix": "%"
},
{
"name": "mobile",
- "color": "#B5307F",
+ "color": "#BD6EBE",
"suffix": "%"
}
]
@@ -147,11 +147,11 @@
"values": [
{
"name": "desktop",
- "color": "#449BC6"
+ "color": "#669E8E"
},
{
"name": "mobile",
- "color": "#AF5AB6"
+ "color": "#BD6EBE"
}
],
"defaults": [
@@ -330,12 +330,12 @@
"values": [
{
"name": "desktop",
- "color": "#449BC6",
+ "color": "#669E8E",
"suffix": "%"
},
{
"name": "mobile",
- "color": "#AF5AB6",
+ "color": "#BD6EBE",
"suffix": "%"
}
],
@@ -469,11 +469,11 @@
"values": [
{
"name": "desktop",
- "color": "#449BC6"
+ "color": "#669E8E"
},
{
"name": "mobile",
- "color": "#AF5AB6"
+ "color": "#BD6EBE"
}
],
"defaults": [
@@ -592,12 +592,12 @@
"values": [
{
"name": "desktop",
- "color": "#449BC6",
+ "color": "#669E8E",
"suffix": " kB"
},
{
"name": "mobile",
- "color": "#AF5AB6",
+ "color": "#BD6EBE",
"suffix": " kB"
}
],
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 7c3aded8..ef145b61 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -338,7 +338,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: ['#5980EB', '#8E3496', '#D55316', '#6AA26F', '#2C2F70', '#B979A7', '#449DB1', '#CB377C', '#AC8D1C', '#742F53'],
+ colors: ['#5980EB', '#D55316', '#2C2F70', '#68A16D', '#B979A7', '#AC8D1C', '#742F53', '#449DB1', '#8E3496', '#CB377C'],
},
title: {
text: config?.title,
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 5e3772c3..aba8a0ea 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -68,7 +68,7 @@
{% include "techreport/templates/table_overview.html" %}
{% include "techreport/templates/table_cwv_overview_multitech.html" %}
- Show indicators
+ Show markers
{% endblock %}
From 880de49dc847ae3136e15156b8b8198a7888542d Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 29 Oct 2023 00:54:32 +0200
Subject: [PATCH 094/155] style filters
---
static/css/techreport/techreport.css | 42 +++++++++++++++++++--
templates/techreport/templates/filters.html | 33 +++++++++-------
2 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index f11530aa..51925643 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -153,15 +153,25 @@
}
/* Filters */
-#filter-bar > div {
- display: flex;
- flex-wrap: wrap;
+#filter-bar {
+ padding: 1.5rem;
+ background: var(--color-card-background);
+ border-radius: var(--card-radius);
+ border: 1px solid var(--color-card-border);
+ box-shadow: var(--card-shadow);
}
#filter-bar > div > *:not(:last-child) {
margin-right: 1.5rem;
}
+#filter-bar .tech-selector-group {
+ border-radius: var(--card-radius);
+ border: 1px solid var(--color-card-border);
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+}
+
#filter-bar label {
margin-bottom: 0.25rem;
display: block;
@@ -176,6 +186,26 @@
color: var(--color-text);
}
+
+#filter-bar .metadata {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ margin: 0;
+ column-gap: 2rem;
+}
+
+#filter-bar .metadata label,
+#filter-bar .metadata select {
+ color: var(--color-text-lighter);
+ font-size: 0.8rem;
+ width: 100%;
+}
+
+#filter-bar .metadata select {
+ border-color: var(--color-text-lighter);
+}
+
+
#filter-bar button {
background-color: var(--color-teal-darker);
border-radius: 3px;
@@ -189,6 +219,12 @@ button#add-tech {
margin-bottom: 3rem;
}
+#filter-bar button#submit-form {
+ font-size: 1.25rem;
+ padding: 0.5rem;
+ width: 100%;
+}
+
/* Table */
.table-ui-wrapper {
overflow-x: scroll;
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 76cb9a19..d549dc7b 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,5 +1,24 @@
+
+
{% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
{% if active_page == "drilldown" %}
@@ -18,20 +37,6 @@
{% endif %}
-
- Geo
-
-
- ALL
-
-
- Rank
-
-
- ALL
-
-
-
Update
From d543395b0857ea04b39a1fa4095eadb33f4a2e9b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 31 Oct 2023 02:20:14 +0100
Subject: [PATCH 095/155] style select
---
static/css/techreport/techreport.css | 153 +++++++++++++++++-
templates/techreport/templates/filters.html | 44 ++---
.../techreport/templates/selector_tech.html | 31 ++--
3 files changed, 186 insertions(+), 42 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 51925643..add6dd7f 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -160,10 +160,10 @@
border: 1px solid var(--color-card-border);
box-shadow: var(--card-shadow);
}
-
+/*
#filter-bar > div > *:not(:last-child) {
margin-right: 1.5rem;
-}
+} */
#filter-bar .tech-selector-group {
border-radius: var(--card-radius);
@@ -186,12 +186,14 @@
color: var(--color-text);
}
-
#filter-bar .metadata {
display: grid;
- grid-template-columns: 1fr 1fr;
+ grid-template-columns: repeat(auto-fit, minmax(4rem, 1fr));
margin: 0;
- column-gap: 2rem;
+ column-gap: 0.5rem;
+ row-gap: 0.5rem;
+ margin-bottom: 0.5rem;
+ margin-right: 0;
}
#filter-bar .metadata label,
@@ -225,6 +227,147 @@ button#add-tech {
width: 100%;
}
+.select-label {
+ border: 1px solid #959494;
+ padding: 0;
+ line-height: 100%;
+ position: relative;
+ border-radius: 5px;
+}
+
+#filter-bar .select-label label {
+ margin-bottom: 0;
+ padding: 0;
+ position: absolute;
+ top: 0.5rem;
+ left: 0.75rem;
+ font-size: 0.825rem;
+ z-index: 0;
+ color: #767474;
+}
+
+#filter-bar .select-label select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background-color: transparent;
+ z-index: 1;
+
+ position: relative;
+
+ padding: 0;
+ border: none;
+ border-radius: 0;
+ margin-bottom: 0;
+ padding: 1.75rem 0.5rem 0.5rem 0.75rem;
+
+ font-size: 1rem;
+ line-height: 100%;
+
+ color: #1E1E1E;
+ border-radius: 3px;
+ outline-offset: 2px;
+}
+
+.select-label:before {
+ content: "";
+ display: block;
+ width: 2.5rem;
+ height: 100%;
+ position: absolute;
+ right: 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.select-label:after {
+ content: "";
+ display: block;
+
+ width: 0.5rem;
+ height: 0.5rem;
+
+ position: absolute;
+ right: 1rem;
+ top: 50%;
+ top: calc(50% - 0.25rem);
+
+ border-bottom: 1.5px solid #1E1E1E;
+ border-left: 1.5px solid #1E1E1E;
+ border-radius: 1px;
+
+ transform: rotate(-45deg);
+}
+
+.select-label:has(select:is(:focus-visible, :hover)):before {
+ background-color: #1E1E1E;
+ border-left: 1px solid #1E1E1E;
+}
+
+.select-label:has(select:is(:focus-visible, :hover)):after {
+ border-color: #E1F1FF;
+}
+
+.select-label:has(select:focus-visible) {
+ background-color: #E1F1FF;
+}
+
+#filter-bar fieldset.technologies .tech {
+ font-size: 1.5rem;
+ font-weight: normal;
+}
+
+#filter-bar fieldset.technologies select.tech {
+ width: 100%;
+}
+
+
+#filter-bar > div {
+ position: relative;
+}
+
+#filter-bar .cell-selector {
+ position: absolute;
+ right: 1.5rem;
+ margin-top: -0.25rem;
+}
+
+#filter-bar .cell-selector label {
+ position: absolute;
+ z-index: 2;
+ top: 0.5rem;
+ left: 1rem;
+
+ font-size: 0.825rem;
+}
+
+#filter-bar .cell-selector select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background-color: transparent;
+ z-index: 1;
+
+ position: relative;
+
+ padding: 0;
+ border: none;
+ border-radius: 0;
+ margin-bottom: 0;
+
+ background-color: #E1F1FF;
+ border-radius: 3rem;
+ width: 30ch;
+ min-width: 0;
+ max-width: 100%;
+
+ padding: 0.5rem 1rem;
+ padding-left: calc(0.5rem + 10ch);
+
+ font-size: 0.825rem;
+}
+
/* Table */
.table-ui-wrapper {
overflow-x: scroll;
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index d549dc7b..45e7108f 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,25 +1,7 @@
-
-
-
+
+ Select data
{% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
{% if active_page == "drilldown" %}
{% set technologies = [technologies[0]] %}
@@ -35,8 +17,26 @@
{% if active_page == "comparison" %}
Add
{% endif %}
-
-
+
+
+ Lens
+
+ Geo
+
+
+ ALL
+
+
+
+
+ Rank
+
+
+ ALL
+
+
+
+
Update
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index ca942769..41aa268b 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -1,20 +1,21 @@
-
Category
+
+ Category
+
+
+ ALL
+
+
+
-
-
- ALL
-
-
-
-
-
Technology
-
-
-
- {{ technology }}
-
-
+
+ Technology
+
+
+ {{ technology }}
+
+
+
{% if active_page == "comparison" %}
Remove
{% endif %}
From 602842da7d5edca4602528a6796f11ca4b0ce40d Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 2 Nov 2023 01:43:56 +0100
Subject: [PATCH 096/155] style filters
---
static/css/techreport/techreport.css | 224 ++++++++++++------
static/img/icon-delete.svg | 5 +
templates/techreport/templates/filters.html | 11 +-
.../techreport/templates/selector_tech.html | 41 ++--
4 files changed, 182 insertions(+), 99 deletions(-)
create mode 100644 static/img/icon-delete.svg
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index add6dd7f..66c07e64 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -152,41 +152,57 @@
border-bottom: 3px solid var(--color-teal-faded);
}
-/* Filters */
-#filter-bar {
+/* Page Filters */
+#page-filters {
padding: 1.5rem;
- background: var(--color-card-background);
- border-radius: var(--card-radius);
- border: 1px solid var(--color-card-border);
- box-shadow: var(--card-shadow);
-}
-/*
-#filter-bar > div > *:not(:last-child) {
- margin-right: 1.5rem;
-} */
-
-#filter-bar .tech-selector-group {
- border-radius: var(--card-radius);
- border: 1px solid var(--color-card-border);
- padding: 1.5rem;
- margin-bottom: 1.5rem;
}
-#filter-bar label {
- margin-bottom: 0.25rem;
- display: block;
+#page-filters button:not(.remove-tech) {
+ background-color: var(--color-teal-darker);
+ border-radius: 3px;
+ color: var(--color-blue-100);
+ font-weight: 600;
+ border: none;
+ padding: 0.25rem 0.5rem;
}
-#filter-bar select {
- width: 20rem;
- max-width: 100%;
- margin-bottom: 1rem;
- border-radius: 4px;
- border: 1px solid var(--color-teal-medium);
- color: var(--color-text);
+.remove-tech {
+ background: none;
+ border: none;
+ border-radius: 10rem;
+ width: 44px;
+ height: 44px;
+ position: relative;
+ top: -0.15rem;
+}
+
+.remove-tech:is(:hover, :focus) img {
+ background: #E1F1FF;
+ border-radius: 3rem;
+}
+
+.remove-tech img {
+ width: 100%;
+ max-width: 1.75rem;
}
-#filter-bar .metadata {
+#page-filters button[type="submit"] {
+ font-size: 1.25rem;
+ padding: 0.5rem;
+ width: 100%;
+ margin-top: 1rem;
+}
+
+#page-filters legend {
+ font-size: 1rem;
+ border: none;
+ color: var(--color-text-lighter);
+ margin-bottom: 0.5rem;
+ font-weight: 600;
+}
+
+/* Page filters: Geo and rank */
+#page-filters .lens {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(4rem, 1fr));
margin: 0;
@@ -194,39 +210,21 @@
row-gap: 0.5rem;
margin-bottom: 0.5rem;
margin-right: 0;
+ margin-top: 2rem;
}
-#filter-bar .metadata label,
-#filter-bar .metadata select {
+#page-filters .lens label,
+#page-filters .lens select {
color: var(--color-text-lighter);
font-size: 0.8rem;
width: 100%;
}
-#filter-bar .metadata select {
+#page-filters .lens select {
border-color: var(--color-text-lighter);
}
-#filter-bar button {
- background-color: var(--color-teal-darker);
- border-radius: 3px;
- color: var(--color-blue-100);
- font-weight: 600;
- border: none;
- padding: 0.25rem 0.5rem;
-}
-
-button#add-tech {
- margin-bottom: 3rem;
-}
-
-#filter-bar button#submit-form {
- font-size: 1.25rem;
- padding: 0.5rem;
- width: 100%;
-}
-
.select-label {
border: 1px solid #959494;
padding: 0;
@@ -235,7 +233,7 @@ button#add-tech {
border-radius: 5px;
}
-#filter-bar .select-label label {
+#page-filters .select-label label {
margin-bottom: 0;
padding: 0;
position: absolute;
@@ -246,7 +244,7 @@ button#add-tech {
color: #767474;
}
-#filter-bar .select-label select {
+#page-filters .select-label select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@@ -312,60 +310,130 @@ button#add-tech {
background-color: #E1F1FF;
}
-#filter-bar fieldset.technologies .tech {
- font-size: 1.5rem;
+.technology-filters label.tech {
+ font-size: 1.15rem;
font-weight: normal;
+ margin-bottom: 0.5rem;
+ width: 100%;
}
-#filter-bar fieldset.technologies select.tech {
+.technology-filters select.tech {
+ font-size: 1.25rem;
width: 100%;
+ margin-bottom: 0;
+
+ border: 1px solid #959494;
+
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background-color: transparent;
+
+ padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
+.technology-filters .tech-selector-group:not(:last-child) {
+ margin-bottom: 1.5rem;
+ border-bottom: 1px solid #eee;
+ padding-bottom: 2rem;
+}
-#filter-bar > div {
+.tech-selector-group {
+ display: flex;
+ column-gap: 1rem;
+ align-items: end;
+}
+
+.tech-input-wrapper {
position: relative;
}
-#filter-bar .cell-selector {
+.tech-input-wrapper:before {
+ content: "";
+ display: block;
+ width: 2.5rem;
+ height: 100%;
position: absolute;
- right: 1.5rem;
- margin-top: -0.25rem;
+ right: 0;
+ border-radius: 0 4px 4px 0;
+ z-index: 0;
}
-#filter-bar .cell-selector label {
+.tech-input-wrapper:after {
+ content: "";
+ display: block;
+
+ width: 0.5rem;
+ height: 0.5rem;
+
position: absolute;
- z-index: 2;
- top: 0.5rem;
- left: 1rem;
+ right: 1rem;
+ top: 50%;
+ top: calc(50% - 0.25rem);
+
+ border-bottom: 1.5px solid #1E1E1E;
+ border-left: 1.5px solid #1E1E1E;
+ border-radius: 1px;
+
+ transform: rotate(-45deg);
+ z-index: 0;
+}
+
+.tech-input-wrapper select {
+ z-index: 1;
+ position: relative;
+}
+
+.tech-input-wrapper:has(select:is(:focus-visible, :hover)):before {
+ background-color: #1E1E1E;
+ border-left: 1px solid #1E1E1E;
+}
+.tech-input-wrapper:has(select:is(:focus-visible, :hover)):after {
+ border-color: #E1F1FF;
+}
+
+.tech-selector-group .content {
+ position: relative;
+ width: 100%;
+}
+
+.categories-selector-group {
+ display: flex;
+ align-items: center;
+ column-gap: 0.5rem;
+ position: absolute;
+ right: 0;
+ top: 0.4rem;
+ text-align: right;
+}
+
+.categories-selector-group label {
+ font-weight: 400;
font-size: 0.825rem;
+
+ margin-bottom: 0;
}
-#filter-bar .cell-selector select {
+.categories-selector-group select {
+ margin-bottom: 0;
+
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: transparent;
- z-index: 1;
-
- position: relative;
- padding: 0;
border: none;
- border-radius: 0;
- margin-bottom: 0;
+ font-size: 0.825rem;
- background-color: #E1F1FF;
- border-radius: 3rem;
- width: 30ch;
- min-width: 0;
- max-width: 100%;
+ padding: 0;
- padding: 0.5rem 1rem;
- padding-left: calc(0.5rem + 10ch);
+ border-radius: 0;
+ width: 15ch;
- font-size: 0.825rem;
+ border-bottom: 1px solid #959494;
}
/* Table */
diff --git a/static/img/icon-delete.svg b/static/img/icon-delete.svg
new file mode 100644
index 00000000..6a39e7b3
--- /dev/null
+++ b/static/img/icon-delete.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/templates/techreport/templates/filters.html b/templates/techreport/templates/filters.html
index 45e7108f..bfbdd0a1 100644
--- a/templates/techreport/templates/filters.html
+++ b/templates/techreport/templates/filters.html
@@ -1,7 +1,8 @@
-
+
-
- Select data
+
+ Technologies
+
{% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
{% if active_page == "drilldown" %}
{% set technologies = [technologies[0]] %}
@@ -15,10 +16,10 @@
{% endfor %}
{% if active_page == "comparison" %}
- Add
+ Add another technology
{% endif %}
-
+
Lens
Geo
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index 41aa268b..2d40c431 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -1,22 +1,31 @@
-
- Category
-
-
- ALL
-
-
-
+
+
+ Category
+
+
+ ALL
+
+
+
-
-
Technology
-
-
- {{ technology }}
-
-
+
+
Technology
+
+
+
+ {{ technology }}
+
+
+
+
+
{% if active_page == "comparison" %}
-
Remove
+
+
+
+
+
{% endif %}
From 8b757ffc104621ea1db80d5a8d4c9686bb9e572e Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 2 Nov 2023 02:38:19 +0100
Subject: [PATCH 097/155] fix bug deleting techs
---
src/js/components/filters.js | 5 ++++-
templates/techreport/templates/selector_tech.html | 4 ++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 68a75c2c..e6eb7b85 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -230,8 +230,11 @@ function addTechnologySelector(event) {
function removeTechnology(event) {
event.preventDefault();
+ console.log(event.target.dataset);
+
/* Remove the tech selector group from the DOM */
- event.target.parentElement.remove();
+ const tech = document.querySelector(`.tech-selector-group[data-tech="${event.target.dataset.tech}"]`);
+ tech.remove();
/* Don't show any remove buttons if there is only one element left */
hideRemoveButton();
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index 2d40c431..5459764d 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -1,4 +1,4 @@
-
+
Category
@@ -24,7 +24,7 @@
{% if active_page == "comparison" %}
-
+
{% endif %}
From d046799ecf609047fa554cfc7dc4664a78a8731c Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Thu, 2 Nov 2023 14:39:52 +0100
Subject: [PATCH 098/155] restructure heading
---
src/js/components/filters.js | 6 ++----
static/css/techreport/techreport.css | 11 ++++++++++-
templates/techreport/drilldown.html | 16 +++++++++++++---
templates/techreport/techreport.html | 4 ++--
4 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index e6eb7b85..13a75944 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -187,11 +187,11 @@ function addTechnologySelector(event) {
const removeButton = selectorTemplate.querySelector('.remove-tech');
const categorySelect = selectorTemplate.querySelector('select.categories-selector');
- const categoryLabel = selectorTemplate.querySelector('label[for="categories"]');
+ const categoryLabel = selectorTemplate.querySelector('label[for="categories-tech-new"]');
categorySelect.innerHTML = document.querySelector('select.categories-selector').innerHTML;
categorySelect.addEventListener('change', updateCategory);
- console.log(selectElement, labelElement);
+ console.log(categoryLabel);
/* Set a unique name on the new element (based on the amount of techs) */
const techId = `tech-${document.querySelectorAll('select.tech[name="tech"]').length + 1}`;
@@ -230,8 +230,6 @@ function addTechnologySelector(event) {
function removeTechnology(event) {
event.preventDefault();
- console.log(event.target.dataset);
-
/* Remove the tech selector group from the DOM */
const tech = document.querySelector(`.tech-selector-group[data-tech="${event.target.dataset.tech}"]`);
tech.remove();
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 66c07e64..6fdc5150 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -720,7 +720,11 @@
margin-top: 0;
}
-.intro h1 span.subtitle {
+.intro h2 {
+ font-size: var(--font-size-xlarge);
+}
+
+.intro span.subtitle {
font-size: 1.15rem;
display: block;
margin-bottom: 0.5rem;
@@ -762,6 +766,11 @@
padding-top: 3rem;
}
+.report-content .intro {
+ padding: 0;
+ margin-bottom: 4rem;
+}
+
.report-section {
margin-bottom: 6rem;
}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 3ba9fb53..b3faf995 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -7,11 +7,11 @@
Tech Report
- Drilldown
+ Drilldown
-
{% include "techreport/templates/filters.html" %}
@@ -27,6 +27,16 @@
+
+
+ Results for
+ ALL
+
+
+
+
+
{% set filters = "" %}
From b7ebafab15b03e6af273f4b8e27613932fa198a6 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 3 Nov 2023 01:44:16 +0100
Subject: [PATCH 099/155] add filter info to page header
---
src/js/components/drilldownHeader.js | 2 +-
static/css/techreport/techreport.css | 28 +++++++++++++++++++++++++++-
templates/techreport/comparison.html | 14 ++++++++------
templates/techreport/drilldown.html | 23 +++++++++++++++++------
4 files changed, 53 insertions(+), 14 deletions(-)
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index 7086637a..fe390b2b 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -1,5 +1,5 @@
function setTitle(title) {
- const mainTitle = document.querySelector('h1 span.main-title');
+ const mainTitle = document.querySelector('h2 span.main-title');
mainTitle.textContent = title;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 6fdc5150..00571f88 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -436,6 +436,33 @@
border-bottom: 1px solid #959494;
}
+/* Results header */
+.client-selector {
+ position: sticky;
+ top: 0;
+ padding: 0.5rem 0;
+ background-color: var(--color-page-background);
+ z-index: 2;
+ border-bottom: 1px solid #6A797C;
+
+}
+
+.client-selector :is(label, select) {
+ margin: 0;
+}
+
+.client-selector .wrapper {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.result-info > div {
+ display: flex;
+ column-gap: 1rem;
+ font-size: 0.825rem;
+}
+
/* Table */
.table-ui-wrapper {
overflow-x: scroll;
@@ -760,7 +787,6 @@
.report-content {
background-image: linear-gradient(#C0CED0, rgba(238,238,238,0));
- border-top: 1px solid #6A797C;
background-size: 100% 50rem;
background-repeat: no-repeat;
padding-top: 3rem;
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index d49ec0cf..c7bd9ca8 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -18,12 +18,14 @@
-
-
Client
-
- Mobile
- Desktop
-
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index b3faf995..e3be255d 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -18,12 +18,23 @@
-
-
Client
-
- Mobile
- Desktop
-
+
+
+
+
{{ tech_report_page.filters.app[0] or 'ALL' }}
+
+
Geo: {{ request.args.get('geo', '') or 'ALL' }}
+
Rank: {{ request.args.get('rank', '') or 'ALL' }}
+
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
+
From 7ab60bdc3c089f7aa6e71087a823c1839eaea70f Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 3 Nov 2023 02:26:22 +0100
Subject: [PATCH 100/155] remember marker status in localstorage
---
src/js/techreport/index.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 63522241..86d85303 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -51,6 +51,10 @@ class TechReport {
initializeReport() {
Filters.bindFilterListener();
+ const showIndicators = localStorage.getItem('showIndicators');
+ document.querySelector('main').dataset.showIndicators = showIndicators;
+ document.querySelector('#indicators-check').checked = showIndicators === 'true';
+
const sections = document.querySelectorAll('[data-type="section"]');
// TODO: add general config too
sections.forEach(section => {
@@ -80,17 +84,13 @@ class TechReport {
const indicatorSetting = document.querySelector('input[name="indicators-check"]');
if(indicatorSetting) {
indicatorSetting.onchange = (event) => {
- console.log('change the thing', event, event.target.checked);
document.querySelector('main').dataset.showIndicators = event.target.checked;
-
- console.log('and now here update the charts again');
+ localStorage.setItem('showIndicators', event.target.checked);
Object.values(this.sections).forEach(section => {
- console.log('loop is working');
section.updateSection();
});
- console.log('no issues after loop');
}
}
}
From 9b644a3e1aeca212999af9e53c353c2f7d5f44a0 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 6 Nov 2023 22:39:35 +0100
Subject: [PATCH 101/155] responsiveness improvements
---
static/css/techreport/general.css | 1 +
static/css/techreport/techreport.css | 76 +++++++++++++++++++++++-----
static/img/icon-delete.svg | 6 +--
3 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index e3e4e0db..f3eab7e3 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -55,6 +55,7 @@ p {
border-radius: var(--card-radius);
border: 1px solid var(--color-card-border);
box-shadow: var(--card-shadow);
+ transition: padding 0.35s;
}
.card > :is(h2, h3, h4) {
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 00571f88..e2272a72 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -115,9 +115,6 @@
background-color: var(--color-card-background);
border-top: 1px solid var(--color-page-background);
border-bottom: 1px solid var(--color-page-background);
- /* position: sticky;
- top: 0;
- z-index: 2; */
}
.report-navigation-content {
@@ -177,7 +174,7 @@
}
.remove-tech:is(:hover, :focus) img {
- background: #E1F1FF;
+ background: #FCC9C4;
border-radius: 3rem;
}
@@ -303,11 +300,15 @@
}
.select-label:has(select:is(:focus-visible, :hover)):after {
- border-color: #E1F1FF;
+ border-color: #F2F9FF;
}
.select-label:has(select:focus-visible) {
- background-color: #E1F1FF;
+ background-color: #F2F9FF;
+}
+
+.select-label:has(select:focus-visible) label {
+ color: var(--color-text) !important;
}
.technology-filters label.tech {
@@ -333,10 +334,18 @@
padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
-.technology-filters .tech-selector-group:not(:last-child) {
- margin-bottom: 1.5rem;
+.technology-filters .tech-selector-group {
border-bottom: 1px solid #eee;
padding-bottom: 2rem;
+ padding-top: 1.5rem;
+}
+
+.technology-filters .tech-selector-group:first-of-type {
+ margin-top: -1.5rem;
+}
+
+.tech-selector-group:has(.remove-tech:is(:focus, :hover)) {
+ background-color: #F2F9FF;
}
.tech-selector-group {
@@ -391,7 +400,16 @@
}
.tech-input-wrapper:has(select:is(:focus-visible, :hover)):after {
- border-color: #E1F1FF;
+ border-color: #F2F9FF;
+}
+
+.tech-input-wrapper:has(select:focus-visible) {
+ background-color: #F2F9FF;
+ color: var(--color-text);
+}
+
+.tech-input-wrapper:has(select:focus-visible) select {
+ color: var(--color-text);
}
.tech-selector-group .content {
@@ -436,6 +454,14 @@
border-bottom: 1px solid #959494;
}
+select {
+ max-width: 100%;
+}
+
+#add-tech {
+ margin-top: 1.5rem;
+}
+
/* Results header */
.client-selector {
position: sticky;
@@ -705,6 +731,7 @@
.component-heading-wrapper > * {
flex: 1;
+ max-width: 100%;
}
.component-heading {
@@ -928,13 +955,34 @@ path.highcharts-tick {
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
-@media screen and (max-height: 25rem) {
- .report-navigation {
+@media screen and (max-height: 30rem) {
+ .client-selector {
position: static;
}
}
/* Smaller screens */
+@media screen and (max-width: 40rem) {
+ .tech-selector-group .content {
+ display: flex;
+ flex-direction: column-reverse;
+ row-gap: 0.75rem;
+ }
+
+ .categories-selector-group {
+ position: static;
+ }
+
+ .tech-selector-group {
+ align-items: start;
+ }
+
+ .tech-selector-group .actions {
+ position: relative;
+ top: 2.25rem;
+ }
+}
+
@media screen and (max-width: 50rem) {
.table-ui td.pct-value[data-value] span {
width: 100%;
@@ -955,9 +1003,13 @@ path.highcharts-tick {
.table-ui .good-scores span[aria-hidden] {
display: none;
}
+
+ .card {
+ padding: 0.75rem;
+ }
}
-@media screen and (max-width: 46rem) {
+@media screen and (max-width: 60rem) {
.summary-grid {
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
diff --git a/static/img/icon-delete.svg b/static/img/icon-delete.svg
index 6a39e7b3..043085dc 100644
--- a/static/img/icon-delete.svg
+++ b/static/img/icon-delete.svg
@@ -1,5 +1,5 @@
-
-
-
+
+
+
From 40e2dc5b86021f2be0a38cef4c12e33d5e6cc9fe Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 6 Nov 2023 22:49:36 +0100
Subject: [PATCH 102/155] add basic styling to highcharts tables
---
static/css/techreport/techreport.css | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index e2272a72..87f72d57 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -949,6 +949,33 @@ path.highcharts-tick {
display: none;
}
+.highcharts-data-table {
+}
+
+.highcharts-data-table table {
+ width: 100%;
+ color: var(--color-text);
+}
+
+.highcharts-data-table thead th {
+ font-weight: 600;
+}
+
+.highcharts-data-table thead {
+ border-bottom: 1px solid var(--color-text);
+}
+
+.highcharts-data-table :is(td, th) {
+ padding: 0.5rem 0.15rem;
+ min-width: 7rem;
+ text-overflow: ellipsis;
+}
+
+.highcharts-data-table tbody th {
+ font-weight: normal;
+}
+
+
/* ----------------------- */
/* ---- Media queries ---- */
/* ----------------------- */
From a5da0a2ae9452af91986dadf8ffa172b803ebaf5 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 7 Nov 2023 03:01:16 +0100
Subject: [PATCH 103/155] style filter info header
---
static/css/techreport/techreport.css | 136 +++++++++++++++++-
templates/techreport/comparison.html | 11 +-
.../components/filter_info_header.html | 32 +++++
templates/techreport/drilldown.html | 20 +--
templates/techreport/techreport.html | 16 ++-
5 files changed, 183 insertions(+), 32 deletions(-)
create mode 100644 templates/techreport/components/filter_info_header.html
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 87f72d57..d54b313f 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -483,6 +483,59 @@ select {
align-items: center;
}
+.client-breakdown-wrapper label {
+ display: block;
+ font-size: 0.825rem;
+ font-weight: 600;
+ color: var(--color-text-lighter);
+ width: 100%;
+ margin-bottom: 0;
+}
+
+.client-breakdown-wrapper select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background-color: transparent;
+ z-index: 1;
+ border-radius: 0;
+ border: none;
+
+ color: var(--color-text);
+
+ padding: 0;
+
+ width: 5rem;
+
+ border-bottom: 1px solid var(--color-text-lighter);
+
+ display: block;
+
+ font-size: 1rem;
+}
+
+.client-breakdown-wrapper:has(select:focus) {
+ border: 1px solid var(--color-teal-darker);
+ border-radius: 3px;
+}
+
+/* So that the outline only gets removed if :has is supported */
+.client-breakdown-wrapper:has(select:focus) select {
+ outline: none;
+ border: none;
+ position: relative;
+ left: 1px;
+ top: -1px;
+ margin-bottom: -1px;
+}
+
+.client-breakdown-wrapper:has(select:focus) label {
+ position: relative;
+ left: 1px;
+ top: -1px;
+}
+
.result-info > div {
display: flex;
column-gap: 1rem;
@@ -949,9 +1002,6 @@ path.highcharts-tick {
display: none;
}
-.highcharts-data-table {
-}
-
.highcharts-data-table table {
width: 100%;
color: var(--color-text);
@@ -976,6 +1026,86 @@ path.highcharts-tick {
}
+/* ----------------------- */
+/* ---- Accessibility ---- */
+/* ----------------------- */
+
+.accessibility-options {
+ background-color: var(--color-card-background);
+ border-top: 1px solid var(--color-card-border);
+ border-bottom: 1px solid var(--color-card-border);
+ padding: 2rem 0;
+}
+
+.accessibility-options h2 {
+ margin: 0;
+ margin-bottom: 1rem;
+}
+
+.accessibility-options p {
+ margin-bottom: 1rem;
+}
+
+.check-wrapper {
+ border: 1px solid var(--color-text-lighter);
+ display: inline-block;
+ margin-top: 1rem;
+ margin-bottom: 0.25rem;
+ padding: 0.5rem 1rem;
+ border-radius: 3px;
+ position: relative;
+}
+
+.check-wrapper label {
+ margin-bottom: 0;
+ padding-left: 1.5rem;
+}
+
+.check-wrapper input {
+ width: 0;
+ height: 0;
+}
+
+.check-wrapper input:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ content: "";
+ display: block;
+ width: 100%;
+ height: 100%;
+}
+
+.check-wrapper:before {
+ content: "";
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ border-radius: 0.3rem;
+ position: absolute;
+ left: 1rem;
+ top: 0.75rem;
+ border: 1px solid var(--color-blue-dark);
+}
+
+.check-wrapper:has(input:checked) {
+ background-color: #E1F1FF;
+}
+
+.check-wrapper:has(input:checked):before {
+ background-color: var(--color-blue-dark);
+ box-shadow: 0 0 0 1.5px #E1F1FF inset;
+}
+
+.check-descr {
+ font-size: 0.85rem;
+ font-style: italic;
+}
+
+.check-descr .check-state {
+ font-weight: 600;
+}
+
/* ----------------------- */
/* ---- Media queries ---- */
/* ----------------------- */
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index c7bd9ca8..e12451eb 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -18,15 +18,8 @@
-
-
- Client
-
- Mobile
- Desktop
-
-
-
+ {% set filter_tech_title = technologies_str or tech_report_page.filters.app[0] or 'ALL' %}
+ {% include "techreport/components/filter_info_header.html" %}
diff --git a/templates/techreport/components/filter_info_header.html b/templates/techreport/components/filter_info_header.html
new file mode 100644
index 00000000..9593f2e3
--- /dev/null
+++ b/templates/techreport/components/filter_info_header.html
@@ -0,0 +1,32 @@
+
+
+
+
+ Client
+
+ Mobile
+ Desktop
+
+
+
+
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index e3be255d..042d28ce 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -18,24 +18,8 @@
-
-
-
-
{{ tech_report_page.filters.app[0] or 'ALL' }}
-
-
Geo: {{ request.args.get('geo', '') or 'ALL' }}
-
Rank: {{ request.args.get('rank', '') or 'ALL' }}
-
-
-
- Client
-
- Mobile
- Desktop
-
-
-
-
+ {% set filter_tech_title = tech_report_page.filters.app[0] or 'ALL' %}
+ {% include "techreport/components/filter_info_header.html" %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 176b8da3..49f925cb 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -68,8 +68,20 @@
{% include "techreport/templates/table_overview.html" %}
{% include "techreport/templates/table_cwv_overview_multitech.html" %}
-
Show markers
-
+
+
+
Accessibility
+
Change settings related to accessibility here
+
+
+
+
+
{% endblock %}
From 1fe74688a195265a6da77a3ec96e2da63107de58 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 7 Nov 2023 03:38:36 +0100
Subject: [PATCH 104/155] style metric selector
---
static/css/techreport/techreport.css | 109 +++++++++++++++---
.../components/filter_info_header.html | 2 +-
.../techreport/components/subcategory.html | 32 ++---
3 files changed, 114 insertions(+), 29 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index d54b313f..34b078b3 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -241,7 +241,7 @@
color: #767474;
}
-#page-filters .select-label select {
+#page-filters .select-label select{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@@ -463,21 +463,20 @@ select {
}
/* Results header */
-.client-selector {
+.results-header {
position: sticky;
top: 0;
padding: 0.5rem 0;
background-color: var(--color-page-background);
- z-index: 2;
+ z-index: 3;
border-bottom: 1px solid #6A797C;
-
}
-.client-selector :is(label, select) {
+.results-header :is(label, select) {
margin: 0;
}
-.client-selector .wrapper {
+.results-header .wrapper {
display: flex;
justify-content: space-between;
align-items: center;
@@ -569,6 +568,96 @@ select {
margin-top: 1rem;
}
+/* Submetric selector */
+.subcategory-selector-wrapper {
+ border: 1px solid #959494;
+ padding: 0.5rem 1rem;
+ line-height: 100%;
+ position: relative;
+ border-radius: 5px;
+ display: inline-block;
+ padding-right: 0;
+}
+
+.subcategory-selector-wrapper label {
+ color: var(--color-text-lighter);
+}
+
+.subcategory-selector-wrapper select {
+ margin-bottom: 0;
+ border: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ background-color: transparent;
+
+ color: var(--color-text);
+
+ padding-right: 3rem;
+
+ z-index: 2;
+ position: relative;
+}
+
+.subcategory-selector-wrapper:has(select:focus) select {
+ outline: none;
+}
+
+.subcategory-selector-wrapper:has(select:focus) {
+ outline: 1px solid var(--color-text);
+ outline-offset: 1.5px;
+}
+
+
+.subcategory-selector-wrapper:after {
+ content: "";
+ display: block;
+
+ width: 0.5rem;
+ height: 0.5rem;
+
+ position: absolute;
+ right: 1rem;
+ top: 50%;
+ top: calc(50% - 0.25rem);
+
+ border-bottom: 1.5px solid #1E1E1E;
+ border-left: 1.5px solid #1E1E1E;
+ border-radius: 1px;
+
+ transform: rotate(-45deg);
+
+ z-index: 1;
+}
+
+.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover)):before {
+ content: "";
+ display: block;
+ height: 100%;
+ width: 2.5rem;
+ background-color: #1E1E1E;
+ border-left: 1px solid #1E1E1E;
+ position: absolute;
+ right: 0;
+ top: 0;
+ z-index: 0;
+}
+
+.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover)):after {
+ border-color: #F2F9FF;
+}
+
+.subcategory-selector-wrapper:has(select:focus-visible) {
+ background-color: #F2F9FF;
+}
+
+.subcategory-selector-wrapper:has(select:focus-visible) label {
+ color: var(--color-text) !important;
+}
+
+
+
/* Timeseries cards */
.timeseries-container {
margin-top: 2rem;
@@ -799,12 +888,6 @@ select {
text-align: right;
}
-.component-filters label {
- display: block;
- font-weight: normal;
- font-size: 0.875rem;
-}
-
.component-filters select {
font-size: 1rem;
}
@@ -1113,7 +1196,7 @@ path.highcharts-tick {
/* Re-arrange when viewport becomes too narrow in height */
/* ± 200% zoom on a 13" screen */
@media screen and (max-height: 30rem) {
- .client-selector {
+ .results-header {
position: static;
}
}
diff --git a/templates/techreport/components/filter_info_header.html b/templates/techreport/components/filter_info_header.html
index 9593f2e3..335212e2 100644
--- a/templates/techreport/components/filter_info_header.html
+++ b/templates/techreport/components/filter_info_header.html
@@ -1,4 +1,4 @@
-
+
+
+
+ 🌚 Switch to dark mode
+
From 63feb107d4589a9c54ccd128f384b579e3591d3a Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 20 Nov 2023 02:49:13 +0100
Subject: [PATCH 112/155] format multiple tech data
---
src/js/techreport/index.js | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 22bb5396..5abd9104 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -247,9 +247,10 @@ class TechReport {
const base = 'https://dev-gw-2vzgiib6.ue.gateway.dev/v1';
- const technology = technologies[0];
+ const technology = technologies.join('%2C');
- let allResults = [];
+ let allResults = {};
+ technologies.forEach(tech => allResults[tech] = []);
Promise.all(apis.map(api => {
const url = `${base}/${api.endpoint}?technology=${technology}&geo=${this.filters.geo}&rank=${this.filters.rank}`;
@@ -266,23 +267,20 @@ class TechReport {
parsedRow[api.metric] = api.parse(parsedRow[api.metric]);
}
- const resIndex = allResults.findIndex(res => res.date === row.date);
+ const resIndex = allResults[row.technology].findIndex(res => res.date === row.date);
if(resIndex > -1) {
- allResults[resIndex] = {
- ...allResults[resIndex],
+ allResults[row.technology][resIndex] = {
+ ...allResults[row.technology][resIndex],
...parsedRow
}
} else {
- allResults.push(parsedRow);
+ allResults[row.technology].push(parsedRow);
}
});
})
.catch(error => console.log('Something went wrong', error));
})).then(() => {
- const results = {};
- results[technology] = allResults;
-
- this.updateComponents(results);
+ this.updateComponents(allResults);
});
}
@@ -391,7 +389,6 @@ class TechReport {
section.updateSection();
});
-
const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
allDataComponents.forEach((component) => {
From 4409b4f14ef350526f0f05f35327698076231a02 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 21 Nov 2023 02:32:50 +0100
Subject: [PATCH 113/155] use new apis in multi tech
---
config/techreport.json | 12 +++++-
src/js/techreport/timeseries.js | 58 ++++++++++++++++++++--------
static/css/techreport/techreport.css | 5 +++
3 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 57c663a7..ae6ebf1d 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -688,6 +688,8 @@
"title": "Good Core Web Vitals over time",
"description": "Placeholder - combination of several metrics",
"id": "good_cwv_timeseries",
+ "endpoint": "vitals",
+ "metric": "good_pct",
"subcategory": {
"base": "pct_good_",
"param": "good-cwv-over-time",
@@ -767,7 +769,8 @@
"base": "pct_good_",
"param": "good-cwv-over-time",
"default": "cwv",
- "metric": "pct_good_cwv",
+ "metric": "good_pct",
+ "height": 600,
"series": {
"breakdown": "app",
"suffix": "%",
@@ -788,6 +791,8 @@
"title": "Lighthouse over time",
"description": "Placeholder text",
"id": "lighthouse_timeseries",
+ "endpoint": "lighthouse",
+ "metric": "median_score_pct",
"subcategory": {
"base": "median_lighthouse_score_",
"param": "median-lighthouse-over-time",
@@ -844,7 +849,7 @@
"base": "median_lighthouse_score_",
"param": "median-lighthouse-over-time",
"default": "performance",
- "metric": "median_lighthouse_score_performance",
+ "metric": "median_score_pct",
"series": {
"breakdown": "app",
"defaults": [
@@ -933,6 +938,8 @@
"title": "Origins over time",
"description": "Placeholder text",
"id": "adoption_timeseries",
+ "endpoint": "adoption",
+ "metric": "origins",
"table": {
"param":"",
"caption": "Adoption",
@@ -958,6 +965,7 @@
"viz": {
"title": "Origins over time",
"metric": "origins",
+ "default": "adoption",
"series": {
"breakdown": "app",
"defaults": [
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 40facb01..185e8732 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -156,19 +156,32 @@ class Timeseries {
const id = this.id;
const pageFilters = this.pageFilters;
- const metric = this.getMetric(config);
const component = document.querySelector(`[data-id="${this.id}"]`);
- const client = component.dataset.client;
const container = component.querySelector('.breakdown-list');
+ /* Get the currently selected subcategory based on the URL */
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+ const subcategory = urlSubcategory || config.default;
+
+ /* Get settings */
+ const metric = component.dataset.metric;
+ const endpoint = component.dataset.endpoint;
+ const client = component.dataset.client;
+
const colors = this.defaults(config)?.chart?.colors;
pageFilters.app.forEach((app, index) => {
- const sorted = data?.[app]?.sort((a, b) => new Date(b.date) - new Date(a.date));
- if(sorted && sorted.length > 0) {
- const filtered = sorted?.filter(row => row.client === client);
- const latest = filtered[0];
+ if(data[app] && data[app].length > 0) {
+ const sorted = data[app].sort((a, b) => new Date(b.date) - new Date(a.date));
+ const latest = sorted[0];
+
+ /* Select value */
+ const latestEndpoint = latest[endpoint];
+ const latestSubcategory = latestEndpoint?.find(row => row.name === subcategory);
+ const latestClient = latestSubcategory?.[client];
+ const latestValue = latestClient?.[metric];
/* Select the container to which we'll add elements. */
const card = container.querySelector(`[data-app="${app}"]`);
@@ -177,13 +190,17 @@ class Timeseries {
const value = card.getElementsByClassName('breakdown-value')[0];
/* Update text */
- label.innerHTML = latest.app;
- value.innerHTML = `${latest[metric]}${config.series.suffix || ''}`;
+ label.innerHTML = latest.technology;
+ if(latestValue) {
+ value.innerHTML = `${latestValue}${config.series.suffix || ''}`;
+ } else {
+ value.classList.add('undefined');
+ value.innerHTML = 'No data';
+ }
timestamp.innerHTML = latest.date;
card.style.setProperty('--breakdown-color', colors[index]);
}
- })
-
+ });
}
// Update the highcharts timeseries
@@ -252,26 +269,33 @@ class Timeseries {
formatDataByApp() {
const series = [];
- // Get the viz settings
- const config = this.pageConfig[this.id]?.viz;
- const metric = this.getMetric(config);
-
// Get the selected client
const component = document.querySelector(`[data-id="${this.id}"]`);
+
+ // Get the viz settings
+ const metric = component.dataset.metric;
+ const endpoint = component.dataset.endpoint;
const client = component.dataset.client;
+ // Get the currently selected subcategory based on the URL
+ const config = this.pageConfig[this.id]?.viz;
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+ const subcategory = urlSubcategory || config.default;
+
const colors = this.defaults(config)?.chart?.colors;
Object.values(this.data).forEach((app, index) => {
- const data = app.filter(row => row.client === client).map(row => {
+ const data = app.map(row => {
+ const value = row?.[endpoint]?.find(row => row.name === subcategory)?.[client]?.[metric];
return {
x: new Date(row.date),
- y: Number(row[metric]),
+ y: value || 0,
};
});
series.push({
- name: app[0]?.app,
+ name: app[0]?.technology,
data: data,
color: colors[index]
});
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index e0e4c537..a884e925 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -1065,6 +1065,11 @@ select {
font-size: var(--font-size-medium);
}
+.breakdown-value.undefined {
+ color: var(--color-text-lighter);
+ font-style: italic;
+}
+
/* -------------------- */
/* ---- Highcharts ---- */
/* -------------------- */
From 1de15f8f822004caeabdf89e15e0dc72c8d2a5f4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 27 Nov 2023 02:33:41 +0100
Subject: [PATCH 114/155] make tables work with new api
---
config/techreport.json | 21 ++++++----
src/js/techreport/index.js | 20 +++++++--
src/js/techreport/table.js | 49 ++++++++++++++--------
templates/techreport/components/table.html | 5 +++
4 files changed, 66 insertions(+), 29 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index ae6ebf1d..7f3b22a4 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -130,9 +130,11 @@
"description": "Placeholder",
"id": "adoption_timeseries",
"endpoint": "adoption",
+ "default": "adoption",
"metric": "origins",
"table": {
- "param":"",
+ "param": "",
+ "default": "adoption",
"caption": "Usage placeholder",
"columns": [
{
@@ -308,7 +310,7 @@
},
"table": {
"param":"good-cwv-over-time",
- "default": "cwv",
+ "default": "overall",
"caption": "Good Core Web Vitals placeholder",
"columns": [
{
@@ -317,19 +319,19 @@
"type": "heading"
},
{
- "key": "pct_good_*subcategory*",
+ "key": "good_pct",
"name": "% Good scores",
"suffix": "%",
"className": "main-cell pct-value"
},
{
- "key": "origins_with_good_*subcategory*",
+ "key": "good_number",
"name": "Good scores",
"className": "good-scores",
"hiddenSuffix": "/"
},
{
- "key": "origins_eligible_for_*subcategory*",
+ "key": "tested",
"name": "Eligible",
"className": "eligible"
},
@@ -481,7 +483,7 @@
"name": "Date"
},
{
- "key": "median_lighthouse_score_*subcategory*",
+ "key": "median_score_pct",
"name": "Median score",
"className": "main-cell"
},
@@ -690,6 +692,7 @@
"id": "good_cwv_timeseries",
"endpoint": "vitals",
"metric": "good_pct",
+ "default": "overall",
"subcategory": {
"base": "pct_good_",
"param": "good-cwv-over-time",
@@ -750,7 +753,7 @@
"type": "heading"
},
{
- "key": "pct_good_*subcategory*",
+ "key": "good_pct",
"name": "Good scores",
"breakdown": "app",
"suffix": "%",
@@ -831,7 +834,7 @@
"type": "heading"
},
{
- "key": "median_lighthouse_score_*subcategory*",
+ "key": "median_score_pct",
"name": "Median lighthouse score",
"breakdown": "app",
"className": "main-cell"
@@ -940,9 +943,11 @@
"id": "adoption_timeseries",
"endpoint": "adoption",
"metric": "origins",
+ "default": "adoption",
"table": {
"param":"",
"caption": "Adoption",
+ "default": "adoption",
"columns": [
{
"name": "Date",
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 5abd9104..341df88f 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -148,46 +148,58 @@ class TechReport {
});
}
- parseVitalsData(metric) {
+ parseVitalsData(metric, date) {
return metric.map(submetric => {
return {
...submetric,
desktop: {
...submetric.desktop,
good_pct: submetric.desktop.tested > 0 ? parseInt(submetric.desktop.good_number / submetric.desktop.tested * 100) : 0,
+ client: 'desktop',
+ date: date,
},
mobile: {
...submetric.mobile,
good_pct: submetric.mobile.tested > 0 ? parseInt(submetric.mobile.good_number / submetric.mobile.tested * 100) : 0,
+ client: 'mobile',
+ date: date,
},
};
});
}
- parseLighthouseData(metric) {
+ parseLighthouseData(metric, date) {
return metric.map(submetric => {
return {
...submetric,
desktop: {
...submetric.desktop,
median_score_pct: parseInt(submetric.desktop.median_score * 100),
+ client: 'desktop',
+ date: date,
},
mobile: {
...submetric.mobile,
median_score_pct: parseInt(submetric.mobile.median_score * 100),
+ client: 'mobile',
+ date: date,
},
};
});
}
- parseAdoptionData(submetric) {
+ parseAdoptionData(submetric, date) {
return [
{
desktop: {
origins: submetric.desktop,
+ client: 'desktop',
+ date: date,
},
mobile: {
origins: submetric.mobile,
+ client: 'mobile',
+ date: date,
},
name: 'adoption',
},
@@ -264,7 +276,7 @@ class TechReport {
}
if(api.parse) {
- parsedRow[api.metric] = api.parse(parsedRow[api.metric]);
+ parsedRow[api.metric] = api.parse(parsedRow[api.metric], parsedRow?.date);
}
const resIndex = allResults[row.technology].findIndex(res => res.date === row.date);
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index 06405d4a..764b5072 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -1,8 +1,12 @@
function formatData(tableConfig, data) {
const { id, config, apps } = tableConfig;
+ const component = document.getElementById(`table-${id}`);
+
// Get the selected subcategory
const subcategory = getSubcategory(config);
+ const metric = component.dataset.metric;
+ const endpoint = component.dataset.endpoint;
// Create empty array
const table = [];
@@ -10,9 +14,15 @@ function formatData(tableConfig, data) {
// Loop through all of the dates
// Populate array of data rows with it
const dates = Object.values(data)[0];
- const component = document.getElementById(`table-${id}`);
const client = component.dataset.client || 'mobile';
- const _dates = dates?.filter(entry => entry.client === client);
+
+ let _dates = [];
+
+ Object.keys(data).forEach(app => {
+ const date = data[app]?.map(entry => entry.date);
+ _dates = [...new Set([..._dates, ...date])];
+ });
+
for(let i = 0; i < _dates?.length; i++) {
const row = [];
@@ -23,21 +33,25 @@ function formatData(tableConfig, data) {
const columnConfig = {
config,
column,
- client
+ client,
+ subcategory,
+ metric,
+ endpoint,
};
+
// Add column cell for each of the apps
// Filter by app name and then metric (key) to find the value
if(column.breakdown === 'app') {
apps.forEach(app => {
- row.push(getColumnCell({...columnConfig, app}, data, i));
+ row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
});
}
// Add column cell with the data for the first app
else {
const app = apps[0];
- row.push(getColumnCell({...columnConfig, app}, data, i));
+ row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
}
});
@@ -48,19 +62,18 @@ function formatData(tableConfig, data) {
return table;
}
-function getColumnCell(columnConfig, data, rowNr) {
- const { config, column, client, app } = columnConfig;
-
- // Get the selected subcategory
- const subcategory = getSubcategory(config);
+function getColumnCell(columnConfig, data, date) {
+ const { config, column, client, app, subcategory, metric, endpoint } = columnConfig;
- const _data = data[app]?.filter(entry => entry.client === client);
- const key = column?.key?.replaceAll('*subcategory*', subcategory);
+ const _data = data[app]?.find(entry => entry.date === date);
+ const endpointData = _data?.[endpoint];
+ const subcategoryData = endpointData?.find(row => row.name === subcategory);
+ const value = subcategoryData?.[client]?.[column.key];
const cell = {
...column,
- formattedKey: key,
- value: _data?.[rowNr]?.[key],
+ formattedKey: column.key,
+ value: value,
app: app
};
@@ -85,21 +98,23 @@ function updateTable(id, config, apps, data) {
// Reset what's in the table before adding new content
tbody.innerHTML = '';
+ // Collect the settings in an object
const tableConfig = {
id,
config,
apps
};
+ // Format the data per row
const rows = formatData(tableConfig, data);
+ // Add rows to the table
rows?.forEach(row => {
- const entry = row;
-
const tr = document.createElement('tr');
+ // Add columns to each row
row?.forEach(column => {
- const cellType = column.type === "heading" ? 'th' : 'td';
+ const cellType = column?.type === "heading" ? 'th' : 'td';
let cell = document.createElement(cellType);
let text = '';
diff --git a/templates/techreport/components/table.html b/templates/techreport/components/table.html
index 1ff45857..dec130a6 100644
--- a/templates/techreport/components/table.html
+++ b/templates/techreport/components/table.html
@@ -6,6 +6,9 @@
class="table-ui"
data-client="{{ client }}"
data-breakdown="{{ tech_report_page.config.default.series.breakdown }}"
+ data-endpoint="{{timeseries.endpoint}}"
+ data-category="{{category}}"
+ data-metric="{{timeseries.metric}}"
>
{{ table.caption }}
@@ -17,6 +20,7 @@
{{ app }}
@@ -30,6 +34,7 @@
{% else %}
{{ column.name }}
From bdebf1a7f99ef62719e4c2260fbd412a33173903 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 29 Nov 2023 02:36:42 +0100
Subject: [PATCH 115/155] bugfix cwv
---
config/techreport.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/techreport.json b/config/techreport.json
index 7f3b22a4..c285cd38 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -771,7 +771,7 @@
"title": "Origins with good core web vitals over time",
"base": "pct_good_",
"param": "good-cwv-over-time",
- "default": "cwv",
+ "default": "overall",
"metric": "good_pct",
"height": 600,
"series": {
From 8cc8e7bd585378af5cfe8538a7eee40f8d1e23f0 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 1 Dec 2023 01:21:43 +0100
Subject: [PATCH 116/155] draw pageweight data and months with missing values
---
config/techreport.json | 91 ++++++++++++++++++++++++++-------
src/js/techreport/index.js | 21 +++++++-
src/js/techreport/timeseries.js | 21 ++++----
3 files changed, 104 insertions(+), 29 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index c285cd38..1e521abf 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -576,28 +576,30 @@
"description": "Placeholder text",
"id": "weight_timeseries",
"summary": true,
+ "endpoint": "pageWeight",
+ "metric": "median_bytes",
"subcategory": {
"base": "median_bytes_",
"param": "weight-over-time",
- "default": "image",
+ "default": "total",
"options": [
+ {
+ "label": "Total page weight",
+ "value": "total"
+ },
{
"label": "Image weight",
- "value": "image"
+ "value": "images"
},
{
"label": "JavaScript transfer size",
"value": "js"
- },
- {
- "label": "Total page weight",
- "value": "total"
}
]
},
"table": {
"param":"weight-over-time",
- "default": "image",
+ "default": "images",
"caption": "Weight",
"columns": [
{
@@ -606,7 +608,7 @@
},
{
"name": "Median Bytes",
- "key": "median_bytes_*subcategory*",
+ "key": "median_bytes",
"suffix": "kB",
"className": "main-cell"
},
@@ -620,9 +622,9 @@
"viz": {
"base": "median_bytes_",
"param": "weight-over-time",
- "default": "image",
+ "default": "images",
"title": "Image weight over time",
- "metric": "median_bytes_image",
+ "metric": "median_bytes",
"height": 600,
"series": {
"breakdown": "client",
@@ -686,6 +688,54 @@
"breakdown": "app"
}
},
+ "overall_summary": {
+ "table": {
+ "caption": "Summary",
+ "columns": [
+ {
+ "key": "technology",
+ "name": "Tech",
+ "type": "heading"
+ },
+ {
+ "key": "origins",
+ "name": "Origins",
+ "breakdown": "subcategory",
+ "subcategory": "adoption",
+ "endpoint": "adoption"
+ },
+ {
+ "key": "good_pct",
+ "name": "Overall good CWV",
+ "breakdown": "subcategory",
+ "subcategory": "overall",
+ "suffix": "%",
+ "className": "main-cell pct-value",
+ "endpoint": "vitals"
+ },
+ {
+ "key": "good_pct",
+ "name": "FID",
+ "breakdown": "subcategory",
+ "subcategory": "fid",
+ "suffix": "%",
+ "endpoint": "vitals"
+ },
+ {
+ "key": "medium_score_pct",
+ "name": "Accessibility",
+ "breakdown": "subcategory",
+ "subcategory": "accessibility",
+ "endpoint": "lighthouse"
+ },
+ {
+ "key": "client",
+ "name": "Client",
+ "className": "client"
+ }
+ ]
+ }
+ },
"good_cwv_timeseries": {
"title": "Good Core Web Vitals over time",
"description": "Placeholder - combination of several metrics",
@@ -872,28 +922,31 @@
"title": "Page weight over time",
"description": "Placeholder text",
"id": "weight_timeseries",
+ "endpoint": "page-weight",
+ "metric": "median_bytes",
+ "default": "total",
"subcategory": {
"base": "median_bytes_",
"param": "median-weight-over-time",
"default": "performance",
"options": [
+ {
+ "label": "Total page weight",
+ "value": "total"
+ },
{
"label": "Image weight",
- "value": "image"
+ "value": "images"
},
{
"label": "JavaScript transfer size",
"value": "js"
- },
- {
- "label": "Total page weight",
- "value": "total"
}
]
},
"table": {
"param":"median-weight-over-time",
- "default": "image",
+ "default": "total",
"caption": "Weight",
"columns": [
{
@@ -902,7 +955,7 @@
},
{
"name": "Median Bytes",
- "key": "median_bytes_*subcategory*",
+ "key": "median_bytes",
"suffix": "kB",
"className": "main-cell",
"breakdown": "app"
@@ -919,8 +972,8 @@
"title": "Median page weight over time",
"base": "median_bytes",
"param": "median-weight-over-time",
- "default": "image",
- "metric": "median_bytes_image",
+ "default": "total",
+ "metric": "median_bytes",
"series": {
"breakdown": "app",
"suffix": " kB",
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 341df88f..0979cc89 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -206,6 +206,24 @@ class TechReport {
];
}
+ parsePageWeightData(metric, date) {
+ return metric.map(submetric => {
+ return {
+ ...submetric,
+ desktop: {
+ ...submetric.desktop,
+ client: 'desktop',
+ date: date,
+ },
+ mobile: {
+ ...submetric.mobile,
+ client: 'mobile',
+ date: date,
+ },
+ };
+ });
+ }
+
// Fetch all the data based on search criteria and config
// TODO: Will be moved to the section level with new APIs
getAllData() {
@@ -253,7 +271,8 @@ class TechReport {
},
{
endpoint: 'page-weight',
- metric: 'page-weight'
+ metric: 'pageWeight',
+ parse: this.parsePageWeightData,
},
];
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 185e8732..1ffc4f7c 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -97,23 +97,24 @@ class Timeseries {
const id = this.id;
const pageFilters = this.pageFilters;
+ /* Select the container to which we'll add elements. */
+ const viz = document.querySelector(`[data-id="${id}"]`);
+ const container = viz.querySelector('.breakdown-list');
+
+ /* Get settings */
+ const metric = viz.dataset.metric;
+ const endpoint = viz.dataset.endpoint;
+
const app = pageFilters.app[0];
- const sorted = data?.[app]?.sort((a, b) => new Date(b.date) - new Date(a.date));
+ const filtered = data?.[app]?.filter(entry => entry[endpoint]);
+ const sorted = filtered?.sort((a, b) => new Date(b.date) - new Date(a.date));
if(sorted) {
- /* Select the container to which we'll add elements. */
- const viz = document.querySelector(`[data-id="${id}"]`);
- const container = viz.querySelector('.breakdown-list');
-
/* Get the currently selected subcategory based on the URL */
const urlParams = new URLSearchParams(window.location.search);
const urlSubcategory = urlParams.get(config.param);
const subcategory = urlSubcategory || config.default;
- /* Get settings */
- const metric = viz.dataset.metric;
- const endpoint = viz.dataset.endpoint;
-
/* Remove the previous content */
container.innerHTML = '';
@@ -337,6 +338,8 @@ class Timeseries {
});
});
+ const sortedData = formattedData.sort((a, b) => new Date(b.x) - new Date(a.x));
+
const colors = this.defaults(config)?.chart?.colors;
// Push the configurations and formatted data to the series array
From 3e7bbe8b2fa083b942e49ef7ad581bb6b73f649b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 1 Dec 2023 01:51:33 +0100
Subject: [PATCH 117/155] start re-adding comparison table
---
src/js/techreport/section.js | 15 ++
src/js/techreport/tableLinked.js | 186 ++++++++++++++++++
templates/techreport/comparison.html | 10 +-
templates/techreport/components/table.html | 4 +-
.../techreport/components/table_linked.html | 64 ++++++
.../techreport/components/timeseries.html | 2 +
6 files changed, 276 insertions(+), 5 deletions(-)
create mode 100644 src/js/techreport/tableLinked.js
create mode 100644 templates/techreport/components/table_linked.html
diff --git a/src/js/techreport/section.js b/src/js/techreport/section.js
index 46e82900..1356c8b7 100644
--- a/src/js/techreport/section.js
+++ b/src/js/techreport/section.js
@@ -1,4 +1,5 @@
import SummaryCard from "./summaryCards";
+import { TableLinked } from "./tableLinked";
class Section {
constructor(id, config, filters, data) {
@@ -25,12 +26,26 @@ class Section {
this.initializeSummaryCards(component);
break;
+ case "table":
+ this.initializeTable(component);
+ break;
+
default:
break;
}
});
}
+ initializeTable(component) {
+ console.log(this.initializeTable);
+ TableLinked.updateTable(
+ component.id,
+ this.pageConfig,
+ this.pageFilters.app,
+ this.data,
+ );
+ }
+
initializeSummaryCards(component) {
this.components[component.dataset.id] = new SummaryCard(
component.dataset.id,
diff --git a/src/js/techreport/tableLinked.js b/src/js/techreport/tableLinked.js
new file mode 100644
index 00000000..1b5257a2
--- /dev/null
+++ b/src/js/techreport/tableLinked.js
@@ -0,0 +1,186 @@
+function formatData(tableConfig, data) {
+ const { id, config, apps } = tableConfig;
+
+ const component = document.getElementById(`${id}`);
+
+ // Get the selected subcategory
+ const subcategory = getSubcategory(config);
+ const metric = component.dataset.metric;
+ const endpoint = component.dataset.endpoint;
+
+ // Create empty array
+ const table = [];
+
+ // Loop through all of the dates
+ // Populate array of data rows with it
+ const dates = Object.values(data)[0];
+ const client = component.dataset.client || 'mobile';
+
+ let _dates = [];
+
+ Object.keys(data).forEach(app => {
+ const date = data[app]?.map(entry => entry.date);
+ _dates = [...new Set([..._dates, ...date])];
+ });
+
+
+ for(let i = 0; i < _dates?.length; i++) {
+ const row = [];
+
+ // Loop through each of the column configs
+ config.columns?.forEach(column => {
+ // Create object with necessary info to find the value
+ const columnConfig = {
+ config,
+ column,
+ client,
+ subcategory,
+ metric,
+ endpoint,
+ };
+
+
+ // Add column cell for each of the apps
+ // Filter by app name and then metric (key) to find the value
+ if(column.breakdown === 'app') {
+ apps.forEach(app => {
+ row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
+ });
+ }
+
+ // Add column cell with the data for the first app
+ else {
+ const app = apps[0];
+ row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
+ }
+ });
+
+ // Add row to the table
+ table.push(row);
+ }
+
+ return table;
+}
+
+function getColumnCell(columnConfig, data, date) {
+ const { config, column, client, app, subcategory, metric, endpoint } = columnConfig;
+
+ const _data = data[app]?.find(entry => entry.date === date);
+ const endpointData = _data?.[endpoint];
+ const subcategoryData = endpointData?.find(row => row.name === subcategory);
+ const value = subcategoryData?.[client]?.[column.key];
+
+ const cell = {
+ ...column,
+ formattedKey: column.key,
+ value: value,
+ app: app
+ };
+
+ return cell;
+}
+
+// Get the selected subcategory based on url
+function getSubcategory(config) {
+ const urlParams = new URLSearchParams(window.location.search);
+ const urlSubcategory = urlParams.get(config.param);
+ const subcategory = urlSubcategory || config.default || '';
+
+ return subcategory;
+}
+
+// Update the table
+function updateTable(id, config, apps, data) {
+ // Select a table based on the passed in id
+ const component = document.getElementById(id)
+ const tbody = component?.querySelector('tbody');
+
+ // Reset what's in the table before adding new content
+ if(tbody) {
+ tbody.innerHTML = '';
+ }
+
+ // Collect the settings in an object
+ const tableConfig = {
+ id,
+ config,
+ apps
+ };
+
+ // Format the data per row
+ const rows = formatData(tableConfig, data);
+
+ console.log('rows', rows, 'tableConfig', tableConfig, 'data', data);
+
+ // Add rows to the table
+ rows?.forEach(row => {
+ const tr = document.createElement('tr');
+
+ // Add columns to each row
+ row?.forEach(column => {
+ const cellType = column?.type === "heading" ? 'th' : 'td';
+ let cell = document.createElement(cellType);
+
+ let text = '';
+ let className = column.className;
+
+ const value = column.value;
+
+ // Fill in the data if it exists
+ if(value && value !== '') {
+ const suffix = column.suffix || '';
+ text = `${value}${suffix}`;
+ } else {
+ text = 'N/A';
+ className += ' no-data'
+ }
+
+ // Wrap the text in a span for styling
+ const wrapper = document.createElement('span');
+ wrapper.innerHTML = text;
+ cell.append(wrapper);
+
+ // Stylized column groups (eg format ` / `)
+ if(column.hiddenSuffix) {
+ /* In this case applying aria-hidden because otherwise
+ * assistive tech would announce "/" at the end of col 1
+ * or as part of the heading, which may be announced weirdly.
+ * So since it's mainly decorative, we hide it as a precaution.
+ */
+ const hiddenSuffix = document.createElement('span');
+ hiddenSuffix.setAttribute('aria-hidden', 'true');
+ hiddenSuffix.innerHTML = column.hiddenSuffix;
+
+ const textWrapper = document.createElement('span');
+ textWrapper.innerHTML = text;
+
+ const cellWrapper = document.createElement(cellType);
+ cellWrapper.appendChild(textWrapper);
+ cellWrapper.appendChild(hiddenSuffix);
+
+ cell = cellWrapper;
+ }
+
+ // Expose percentages to css to use for styling
+ if(text.includes('%')) {
+ cell.setAttribute('style', `--cell-value: ${value}%`);
+ cell.dataset.value = value;
+ }
+
+ // Add classnames from the config
+ if(className) {
+ cell.className = className;
+ }
+
+ // Add cell to the row
+ tr.appendChild(cell);
+ });
+
+ // Add row to the body
+ tbody.appendChild(tr);
+ });
+}
+
+export const TableLinked = {
+ updateTable,
+}
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index e12451eb..0724dc23 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -23,7 +23,7 @@
-
+
{{ table.caption }}
diff --git a/templates/techreport/components/table_linked.html b/templates/techreport/components/table_linked.html
new file mode 100644
index 00000000..9a4d709c
--- /dev/null
+++ b/templates/techreport/components/table_linked.html
@@ -0,0 +1,64 @@
+
+
+
+
+ {{ table.caption }}
+
+
+ {% for column in table.columns %}
+ {% if column.breakdown == 'app' %}
+ {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
+ {% for app in technologies %}
+
+ {{ app }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
+ {% endfor %}
+ {% else %}
+
+ {{ column.name }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+ {% if table.rows %}
+ {% for row in table.rows %}
+ {% if row.header == "true" %}
+ {{ row.name }}
+ {% else %}
+ {{ row.name }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+
+
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index c25140a5..fe3fa594 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -61,6 +61,8 @@
{% set table = timeseries.table %}
{% set id = timeseries.id %}
+ {% set endpoint = timeseries.endpoint %}
+ {% set metric = timeseries.metric %}
{% set client = request.args.get('client', '') or 'mobile' %}
{% include "techreport/components/table.html" %}
From 537e9b4a147d08f7c0121e7bf245e3c01f183871 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 2 Dec 2023 01:46:48 +0100
Subject: [PATCH 118/155] prototype comparison summary (wip)
---
config/techreport.json | 21 +-
src/js/techreport/section.js | 11 +-
src/js/techreport/tableLinked.js | 242 +++++-------------
src/js/techreport/timeseries.js | 1 -
templates/techreport/comparison.html | 12 +-
.../techreport/components/table_linked.html | 52 ++--
6 files changed, 108 insertions(+), 231 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 1e521abf..8a412b56 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -688,7 +688,8 @@
"breakdown": "app"
}
},
- "overall_summary": {
+ "tech_comparison_summary": {
+ "id": "tech_comparison_summary",
"table": {
"caption": "Summary",
"columns": [
@@ -702,7 +703,8 @@
"name": "Origins",
"breakdown": "subcategory",
"subcategory": "adoption",
- "endpoint": "adoption"
+ "endpoint": "adoption",
+ "metric": "origins"
},
{
"key": "good_pct",
@@ -711,22 +713,25 @@
"subcategory": "overall",
"suffix": "%",
"className": "main-cell pct-value",
- "endpoint": "vitals"
+ "endpoint": "vitals",
+ "metric": "good_pct"
},
{
"key": "good_pct",
"name": "FID",
"breakdown": "subcategory",
- "subcategory": "fid",
+ "subcategory": "FID",
"suffix": "%",
- "endpoint": "vitals"
+ "endpoint": "vitals",
+ "metric": "good_pct"
},
{
"key": "medium_score_pct",
- "name": "Accessibility",
+ "name": "accessibility",
"breakdown": "subcategory",
- "subcategory": "accessibility",
- "endpoint": "lighthouse"
+ "subcategory": "Accessibility",
+ "endpoint": "lighthouse",
+ "metric": "median_score_pct"
},
{
"key": "client",
diff --git a/src/js/techreport/section.js b/src/js/techreport/section.js
index 1356c8b7..dc5a2619 100644
--- a/src/js/techreport/section.js
+++ b/src/js/techreport/section.js
@@ -1,5 +1,5 @@
import SummaryCard from "./summaryCards";
-import { TableLinked } from "./tableLinked";
+import TableLinked from "./tableLinked";
class Section {
constructor(id, config, filters, data) {
@@ -37,12 +37,11 @@ class Section {
}
initializeTable(component) {
- console.log(this.initializeTable);
- TableLinked.updateTable(
- component.id,
+ this.components[component.dataset.id] = new TableLinked(
+ component.dataset.id,
this.pageConfig,
- this.pageFilters.app,
- this.data,
+ this.pageFilters,
+ this.data
);
}
diff --git a/src/js/techreport/tableLinked.js b/src/js/techreport/tableLinked.js
index 1b5257a2..6a7b4821 100644
--- a/src/js/techreport/tableLinked.js
+++ b/src/js/techreport/tableLinked.js
@@ -1,186 +1,78 @@
-function formatData(tableConfig, data) {
- const { id, config, apps } = tableConfig;
-
- const component = document.getElementById(`${id}`);
-
- // Get the selected subcategory
- const subcategory = getSubcategory(config);
- const metric = component.dataset.metric;
- const endpoint = component.dataset.endpoint;
-
- // Create empty array
- const table = [];
-
- // Loop through all of the dates
- // Populate array of data rows with it
- const dates = Object.values(data)[0];
- const client = component.dataset.client || 'mobile';
-
- let _dates = [];
-
- Object.keys(data).forEach(app => {
- const date = data[app]?.map(entry => entry.date);
- _dates = [...new Set([..._dates, ...date])];
- });
-
+class TableLinked {
+ constructor(id, config, filters, data) {
+ this.id = id;
+ this.pageConfig = config;
+ this.pageFilters = filters;
+ this.submetric = ''; // TODO: Fetch the default one from somewhere
+ this.data = data;
+
+ this.updateContent();
+ }
- for(let i = 0; i < _dates?.length; i++) {
- const row = [];
+ // Format the data to fit in the table structure
+ formatData(tableConfig, data) {
+ const { apps, id, config } = tableConfig;
- // Loop through each of the column configs
- config.columns?.forEach(column => {
- // Create object with necessary info to find the value
- const columnConfig = {
- config,
- column,
- client,
- subcategory,
- metric,
- endpoint,
- };
+ const rows = [];
+ apps.forEach(app => {
- // Add column cell for each of the apps
- // Filter by app name and then metric (key) to find the value
- if(column.breakdown === 'app') {
- apps.forEach(app => {
- row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
- });
- }
-
- // Add column cell with the data for the first app
- else {
- const app = apps[0];
- row.push(getColumnCell({...columnConfig, app}, data, _dates[i]));
- }
});
-
- // Add row to the table
- table.push(row);
}
- return table;
-}
-
-function getColumnCell(columnConfig, data, date) {
- const { config, column, client, app, subcategory, metric, endpoint } = columnConfig;
-
- const _data = data[app]?.find(entry => entry.date === date);
- const endpointData = _data?.[endpoint];
- const subcategoryData = endpointData?.find(row => row.name === subcategory);
- const value = subcategoryData?.[client]?.[column.key];
-
- const cell = {
- ...column,
- formattedKey: column.key,
- value: value,
- app: app
- };
-
- return cell;
-}
-
-// Get the selected subcategory based on url
-function getSubcategory(config) {
- const urlParams = new URLSearchParams(window.location.search);
- const urlSubcategory = urlParams.get(config.param);
- const subcategory = urlSubcategory || config.default || '';
-
- return subcategory;
-}
-
-// Update the table
-function updateTable(id, config, apps, data) {
- // Select a table based on the passed in id
- const component = document.getElementById(id)
- const tbody = component?.querySelector('tbody');
+ // Update content in the table
+ updateContent() {
+ // Select a table based on the passed in id
+ const component = document.getElementById(`table-${this.id}`);
+ const tbody = component?.querySelector('tbody');
+
+ if(tbody) {
+ // Reset what's in the table before adding new content
+ tbody.innerHTML = '';
+
+ // Collect the settings in an object
+ const tableConfig = {
+ apps: this.pageFilters.app,
+ config: this.pageConfig?.[this.id]?.table,
+ id: this.id,
+ };
- // Reset what's in the table before adding new content
- if(tbody) {
- tbody.innerHTML = '';
+ tableConfig.apps.forEach(app => {
+ const data = this.data[app];
+ const sorted = data?.sort((a, b) => new Date(b.date) - new Date(a.date));
+ const latest = sorted?.[0];
+
+ if(latest) {
+ const tr = document.createElement('tr');
+
+ tableConfig.config?.columns?.forEach(column => {
+ let cell;
+ if(column.type === 'heading') {
+ cell = document.createElement('th');
+ const link = document.createElement('a');
+ link.setAttribute('href', `?tech=${app}`);
+ link.innerHTML = app;
+ cell.append(link);
+ } else if(column.key === 'client') {
+ cell = document.createElement('td');
+ cell.innerHTML = component.dataset.client;
+ } else {
+ cell = document.createElement('td');
+ const dataset = latest?.[column?.endpoint];
+ let value = dataset?.find(entry => entry.name === column.subcategory);
+ value = value?.[component.dataset.client]?.[column?.metric];
+ cell.innerHTML = value;
+ }
+
+
+
+ tr.append(cell);
+ });
+ tbody.append(tr);
+ }
+ });
+ }
}
-
- // Collect the settings in an object
- const tableConfig = {
- id,
- config,
- apps
- };
-
- // Format the data per row
- const rows = formatData(tableConfig, data);
-
- console.log('rows', rows, 'tableConfig', tableConfig, 'data', data);
-
- // Add rows to the table
- rows?.forEach(row => {
- const tr = document.createElement('tr');
-
- // Add columns to each row
- row?.forEach(column => {
- const cellType = column?.type === "heading" ? 'th' : 'td';
- let cell = document.createElement(cellType);
-
- let text = '';
- let className = column.className;
-
- const value = column.value;
-
- // Fill in the data if it exists
- if(value && value !== '') {
- const suffix = column.suffix || '';
- text = `${value}${suffix}`;
- } else {
- text = 'N/A';
- className += ' no-data'
- }
-
- // Wrap the text in a span for styling
- const wrapper = document.createElement('span');
- wrapper.innerHTML = text;
- cell.append(wrapper);
-
- // Stylized column groups (eg format ` / `)
- if(column.hiddenSuffix) {
- /* In this case applying aria-hidden because otherwise
- * assistive tech would announce "/" at the end of col 1
- * or as part of the heading, which may be announced weirdly.
- * So since it's mainly decorative, we hide it as a precaution.
- */
- const hiddenSuffix = document.createElement('span');
- hiddenSuffix.setAttribute('aria-hidden', 'true');
- hiddenSuffix.innerHTML = column.hiddenSuffix;
-
- const textWrapper = document.createElement('span');
- textWrapper.innerHTML = text;
-
- const cellWrapper = document.createElement(cellType);
- cellWrapper.appendChild(textWrapper);
- cellWrapper.appendChild(hiddenSuffix);
-
- cell = cellWrapper;
- }
-
- // Expose percentages to css to use for styling
- if(text.includes('%')) {
- cell.setAttribute('style', `--cell-value: ${value}%`);
- cell.dataset.value = value;
- }
-
- // Add classnames from the config
- if(className) {
- cell.className = className;
- }
-
- // Add cell to the row
- tr.appendChild(cell);
- });
-
- // Add row to the body
- tbody.appendChild(tr);
- });
}
-export const TableLinked = {
- updateTable,
-}
+export default TableLinked;
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 1ffc4f7c..c3f6571e 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -1,5 +1,4 @@
import { Table } from "./table";
-
class Timeseries {
// Create the component
constructor(id, config, filters, data) {
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index 0724dc23..dd8bf632 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -30,13 +30,13 @@
data-api="cwv,lighthouse,page-weight"
>
Summary ({{ technologies | length }} technologies)
-
- {% set id = 'summary-grid-table' %}
- {% set client = request.args.get('client', '') or 'mobile' %}
- {% set table = tech_report_page.config.overall_summary.table %}
+ {% set component = tech_report_page.config.tech_comparison_summary %}
+ {% set id = component.id %}
+ {% set client = request.args.get('client', '') or 'mobile' %}
+
+ {% set table = component.table %}
+ {% include "techreport/components/table_linked.html" %}
- {% include "techreport/components/table_linked.html" %}
-
{% include "techreport/components/filter_meta.html" %}
diff --git a/templates/techreport/components/table_linked.html b/templates/techreport/components/table_linked.html
index 9a4d709c..ffc95406 100644
--- a/templates/techreport/components/table_linked.html
+++ b/templates/techreport/components/table_linked.html
@@ -2,50 +2,32 @@
{{ table.caption }}
{% for column in table.columns %}
- {% if column.breakdown == 'app' %}
- {% set technologies = tech_report_page.filters.app or tech_report_page.config.default.app %}
- {% for app in technologies %}
-
- {{ app }}
- {% if column.hiddenSuffix %}
-
- {{ column.hiddenSuffix }}
-
- {% endif %}
-
- {% endfor %}
- {% else %}
-
- {{ column.name }}
- {% if column.hiddenSuffix %}
-
- {{ column.hiddenSuffix }}
-
- {% endif %}
-
- {% endif %}
+
+ {{ column.name }}
+ {% if column.hiddenSuffix %}
+
+ {{ column.hiddenSuffix }}
+
+ {% endif %}
+
{% endfor %}
From f688950595bce9d610b5ad65eb9e809bafaa21d2 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 3 Dec 2023 02:02:55 +0100
Subject: [PATCH 119/155] bugfix table
---
config/techreport.json | 32 ++++++++++++++++----------------
src/js/techreport/tableLinked.js | 6 +++++-
2 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 8a412b56..75fad8da 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -4,12 +4,12 @@
"summary": "The Core Web Vitals Technology Report is a dashboard combining the powers of real-user experiences in the [Chrome User Experience Report (CrUX)](https://developers.google.com/web/tools/chrome-user-experience-report/) dataset with web technology detections available in HTTP Archive, to allow analysis of the way websites are both built and experienced.",
"config": {
"cwv_subcategories": [
- "fid",
- "cls",
- "lcp",
- "fcp",
- "inp",
- "ttfb"
+ "FID",
+ "CLS",
+ "LCP",
+ "FCP",
+ "INP",
+ "TTFB"
],
"lighthouse_subcategories": [
"accessibility",
@@ -727,9 +727,9 @@
},
{
"key": "medium_score_pct",
- "name": "accessibility",
+ "name": "Accessibility",
"breakdown": "subcategory",
- "subcategory": "Accessibility",
+ "subcategory": "accessibility",
"endpoint": "lighthouse",
"metric": "median_score_pct"
},
@@ -751,47 +751,47 @@
"subcategory": {
"base": "pct_good_",
"param": "good-cwv-over-time",
- "default": "cwv",
+ "default": "overall",
"options": [
{
"label": "Overall good CWVs",
- "value": "cwv",
+ "value": "overall",
"title": "Origins with overall good Core Web Vitals",
"description": "overall todo"
},
{
"label": "LCP",
- "value": "lcp",
+ "value": "LCP",
"title": "Origins with good LCP",
"description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
},
{
"label": "FID",
- "value": "fid",
+ "value": "FID",
"title": "Origins with good FID",
"description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
},
{
"label": "CLS",
- "value": "cls",
+ "value": "CLS",
"title": "Origins with good CLS",
"description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
},
{
"label": "FCP",
- "value": "fcp",
+ "value": "FCP",
"title": "Origins with good FCP",
"description": "todo find fcp description"
},
{
"label": "TTFB",
- "value": "ttfb",
+ "value": "TTFB",
"title": "Origins with good TTFB",
"description": "todo find fcp description"
},
{
"label": "INP",
- "value": "inp",
+ "value": "INP",
"title": "Origins with good LCP",
"description": "todo find fcp description"
}
diff --git a/src/js/techreport/tableLinked.js b/src/js/techreport/tableLinked.js
index 6a7b4821..2cfc041c 100644
--- a/src/js/techreport/tableLinked.js
+++ b/src/js/techreport/tableLinked.js
@@ -61,7 +61,11 @@ class TableLinked {
const dataset = latest?.[column?.endpoint];
let value = dataset?.find(entry => entry.name === column.subcategory);
value = value?.[component.dataset.client]?.[column?.metric];
- cell.innerHTML = value;
+ cell.innerHTML = `${value}`;
+ }
+
+ if(column.className) {
+ cell.className = column.className;
}
From 097b123efc16cdc5871510d3c753c72fb49ef4a8 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 3 Dec 2023 02:13:25 +0100
Subject: [PATCH 120/155] fix page weight bug
---
config/techreport.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/techreport.json b/config/techreport.json
index 75fad8da..7db4aba3 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -927,7 +927,7 @@
"title": "Page weight over time",
"description": "Placeholder text",
"id": "weight_timeseries",
- "endpoint": "page-weight",
+ "endpoint": "pageWeight",
"metric": "median_bytes",
"default": "total",
"subcategory": {
From 3d83b931ce19d18b71e3b9c7676124b6b2b555b0 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 3 Dec 2023 18:17:30 +0100
Subject: [PATCH 121/155] remove web components
---
src/js/components/drilldownHeader.js | 10 +-
src/js/components/summaryLinked.js | 63 --------
src/js/components/tableCWVOverviewMulti.js | 131 -----------------
src/js/components/tableGeneral.js | 88 -----------
src/js/components/tableGeneralMulti.js | 137 ------------------
src/js/components/tableOverview.js | 98 -------------
src/js/techreport/timeseries.js | 1 -
templates/techreport/landing.html | 18 ---
templates/techreport/techreport.html | 14 --
.../templates/drilldown_header.html | 3 -
.../table_cwv_overview_multitech.html | 28 ----
.../techreport/templates/table_general.html | 37 -----
.../templates/table_general_multi.html | 22 ---
.../techreport/templates/table_overview.html | 38 -----
webpack.config.js | 7 -
15 files changed, 6 insertions(+), 689 deletions(-)
delete mode 100644 src/js/components/summaryLinked.js
delete mode 100644 src/js/components/tableCWVOverviewMulti.js
delete mode 100644 src/js/components/tableGeneral.js
delete mode 100644 src/js/components/tableGeneralMulti.js
delete mode 100644 src/js/components/tableOverview.js
delete mode 100644 templates/techreport/templates/drilldown_header.html
delete mode 100644 templates/techreport/templates/table_cwv_overview_multitech.html
delete mode 100644 templates/techreport/templates/table_general.html
delete mode 100644 templates/techreport/templates/table_general_multi.html
delete mode 100644 templates/techreport/templates/table_overview.html
diff --git a/src/js/components/drilldownHeader.js b/src/js/components/drilldownHeader.js
index 55f0f8a5..c31b9c8c 100644
--- a/src/js/components/drilldownHeader.js
+++ b/src/js/components/drilldownHeader.js
@@ -12,16 +12,18 @@ function setCategories(categories) {
/* Get the first 5 elements of the array */
const _categories = categories.slice(0,5);
_categories.forEach((category) => {
- const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
- cellTemplate.querySelector('li.cell').textContent = category;
+ const cellTemplate = document.createElement('li');
+ cellTemplate.className('cell');
+ cellTemplate.textContent = category;
list.appendChild(cellTemplate);
});
/* If there are more than 5 categories, show a message */
if(categories.length > 5) {
const more = categories.length - 5;
- const cellTemplate = document.getElementById('category-cell').content.cloneNode(true);
- cellTemplate.querySelector('li.cell').textContent = `+ ${more} more`;
+ const cellTemplate = document.createElement('li');
+ cellTemplate.className('cell');
+ cellTemplate.textContent = `+ ${more} more`;
list.appendChild(cellTemplate);
}
}
diff --git a/src/js/components/summaryLinked.js b/src/js/components/summaryLinked.js
deleted file mode 100644
index e8fbc674..00000000
--- a/src/js/components/summaryLinked.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { getLatestEntry } from "../utils";
-
-class SummaryLinked extends HTMLElement {
- constructor() {
- super();
-
- this.latest = {};
- this.allData = [];
- this.placeholder = '000';
- this.client = 'mobile';
- this.link = "#";
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('summary-linked').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
-
- connectedCallback() {
- this.renderComponent();
- }
-
- static get observedAttributes() {
- return ['key', 'title', 'client', 'loaded', 'link'];
- }
-
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- this.renderComponent();
- }
-
- setTitle() {
- this.shadowRoot.querySelectorAll('.summary-linked-label a')
- .forEach( (node) => {
- node.textContent = this.title;
- node.setAttribute('href', this.link);
- } );
- }
-
- setData() {
- this.shadowRoot.querySelectorAll('.summary-linked-value')
- .forEach( (node) => {
- node.textContent = this.latest?.[this.key] || this.placeholder;
- } );
-
- this.shadowRoot.querySelectorAll('.summary-linked-description')
- .forEach( (node) => {
- node.textContent = this.latest?.client ? `For ${this.latest.client}.` : this.placeholder;
- } );
- }
-
- renderComponent() {
- if(this.allData) {
- const _filtered = this.allData?.filter(row => row.client === this.client);
- const _latest = getLatestEntry(_filtered);
- this.latest = _latest;
- this.setTitle();
- this.setData();
- }
- }
-}
-
-customElements.define('summary-linked', SummaryLinked);
diff --git a/src/js/components/tableCWVOverviewMulti.js b/src/js/components/tableCWVOverviewMulti.js
deleted file mode 100644
index 413ef2c8..00000000
--- a/src/js/components/tableCWVOverviewMulti.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { getLatestEntry } from "../utils";
-
-/*
- * Core Web Vitals overview table for multiple technologies.
- * Uses the latest data for each of the technologies.
- * Columns: Core Web Vitals breakdown
- * Rows: Selected technologies
- */
-class tableCWVOverviewMulti extends HTMLElement {
- constructor() {
- super();
-
- this.allData = [];
- this.latest = [];
- this.technologies = '';
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('table-cwv-overview-multitech').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
-
- connectedCallback() {
- this.renderComponent();
- }
-
- static get observedAttributes() {
- return ['loaded', 'client', 'all_data', 'technologies'];
- }
-
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- this.renderComponent();
- }
-
- setData() {
- const technologies = this.technologies?.split(",");
- const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
- tableBody.innerHTML = '';
-
- /* Define keys for the different core web vitals */
- const coreWebVitals = [
- {
- origins_with_good: "origins_with_good_cwv",
- origins_eligible: "origins_eligible_for_cwv",
- },
- {
- origins_with_good: "origins_with_good_lcp",
- origins_eligible: "origins_with_any_lcp",
- },
- {
- origins_with_good: "origins_with_good_cls",
- origins_eligible: "origins_with_any_cls",
- },
- {
- origins_with_good: "origins_with_good_fid",
- origins_eligible: "origins_with_any_fid",
- },
- {
- origins_with_good: "origins_with_good_inp",
- origins_eligible: "origins_with_any_inp",
- },
- ];
-
- this.shadowRoot.querySelector('.errorMsg').innerHTML = '';
-
- technologies.forEach(technology => {
- /* Select the data for each of the technologies */
- const _data = this.allData?.[technology];
-
- /* If the data exits, fill in the table */
- if(_data) {
- /* Get the data for the selected client, and get the latest entry */
- const _clientData = _data?.filter(entry => entry.client === this.client);
- const _clientDataSorted = [..._clientData]?.sort((a, b) => {
- return new Date(a.date) - new Date(b.date);
- });
- const _latest = getLatestEntry(_clientDataSorted);
-
- /* Get the filters from the URL */
- const url = window.location.search;
- const parameters = new URLSearchParams(url);
- const geo = parameters.get('geo') || 'ALL';
- const rank = parameters.get('rank') || 'ALL';
-
- /* Fill in the tech names as row headings */
- const row = document.createElement('tr');
- const headingCell = document.createElement('th');
- const technologyLinkEl = document.createElement('a');
- technologyLinkEl.className = 'row-link';
- technologyLinkEl.href = `/reports/techreport/drilldown/?tech=${technology}&geo=${geo}&rank=${rank}`;
- technologyLinkEl.innerHTML = technology;
- headingCell.append(technologyLinkEl);
- row.append(headingCell);
-
- /* Fill in amount of origins tech has */
- const origins = document.createElement('td');
- origins.innerHTML = _latest.origins;
- row.append(origins);
-
- /* Fill in the data for each of the core web vitals */
- coreWebVitals.forEach(cwv => {
- const dataCell = document.createElement('td');
- const percentageGood = parseInt(_latest[cwv?.origins_with_good] / _latest[cwv?.origins_eligible] * 10000) / 100;
- dataCell.innerHTML = `${percentageGood}%`;
- row.append(dataCell);
- })
-
- /* Add the row to the table body */
- tableBody.append(row);
-
- /* Show the latest timestamp */
- this.shadowRoot.querySelector('.timestamp').innerHTML = _latest.date;
- }
-
- /* Else show a mesage that this tech doesn't have data */
- else {
- const errorMsg = document.createElement('p');
- errorMsg.textContent = `No data found for ${technology}.`;
- this.shadowRoot.querySelector('.errorMsg').append(errorMsg);
- }
- });
-
- }
-
- renderComponent() {
- this.setData();
- }
-}
-
-customElements.define('table-cwv-overview-multitech', tableCWVOverviewMulti);
diff --git a/src/js/components/tableGeneral.js b/src/js/components/tableGeneral.js
deleted file mode 100644
index b445eda4..00000000
--- a/src/js/components/tableGeneral.js
+++ /dev/null
@@ -1,88 +0,0 @@
-class TableGeneral extends HTMLElement {
- constructor() {
- super();
-
- this.allData = [];
- this.subcategory = '';
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('table-general').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
-
- connectedCallback() {
- this.renderComponent();
- this.renderSubcategorySelector();
- }
-
- static get observedAttributes() {
- return ['loaded', 'labels', 'columns', 'client', 'subcategory', 'id'];
- }
-
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- this.renderComponent();
- }
-
- renderSubcategorySelector() {
- /* Get the subcategory slot content. */
- const subcategorySelector = this.shadowRoot.querySelector('slot[name="subcategory-selector"]');
-
- /* Only add event listener if subcategory slots were added. */
- if(subcategorySelector) {
- subcategorySelector.addEventListener('change', (event) => {
- this.setAttribute('subcategory', event.target.value);
- const url = new URL(window.location.href);
- url.searchParams.set(this.id, event.target.value);
- window.history.replaceState(null, null, url);
- });
- }
- }
-
- setTitle() {
- const columnHeading = this.shadowRoot.querySelector('table.table-ui thead tr');
- const _columns = this.columns?.replaceAll("*subcategory*", this.subcategory);
- const columns = _columns?.split(",");
-
- columnHeading.innerHTML = '';
- columns?.forEach((column) => {
- const headingCell = document.getElementById('table-general-heading-cell').content.cloneNode(true);
- headingCell.querySelector('th').textContent = this.labels?.values?.[column];
- columnHeading.append(headingCell);
- });
- }
-
- setData() {
- /* Set the caption id and connect the wrapper to it */
- const tableWrapper = this.shadowRoot.querySelector('.table-ui-wrapper[role="region"]');
- const tableCaption = this.shadowRoot.querySelector('table.table-ui caption');
- tableCaption.setAttribute('id', this.id);
- tableWrapper.setAttribute('aria-labelledby', this.id);
-
- if(this.columns) {
- const _columns = this.columns.replaceAll("*subcategory*", this.subcategory)
- const columns = _columns.split(",");
- const body = this.shadowRoot.querySelector('tbody');
- body.innerHTML = '';
- this.allData.forEach((row) => {
- if(this.client === row.client) {
- const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true).querySelector('tr');
- columns.forEach((column) => {
- const cell = document.getElementById('table-general-cell').content.cloneNode(true);
- cell.querySelector('td').textContent = row[column];
- rowTemplate.appendChild(cell);
- });
- body.appendChild(rowTemplate);
- }
- });
- }
- }
-
- renderComponent() {
- this.setTitle();
- this.setData();
- }
-}
-
-customElements.define('table-general', TableGeneral);
diff --git a/src/js/components/tableGeneralMulti.js b/src/js/components/tableGeneralMulti.js
deleted file mode 100644
index cc91409e..00000000
--- a/src/js/components/tableGeneralMulti.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import { getLatestEntry } from "../utils";
-
-/*
- * Table comparing data between different technologies.
- * Dataset: Based on selected metric (CWV, lighthouse, etc.)
- * Columns: Selected technologies.
- * Rows: Time entries.
- * TODO:
- * - Some functionality shared with tableGeneral.js -> Merge
- * - Clean up code and naming
- */
-class tableGenralMulti extends HTMLElement {
- constructor() {
- super();
-
- this.allData = [];
- this.technologies = '';
- this.client = 'mobile';
- this.metric = 'origins';
- this.subcategory = '';
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('table-general-multitech').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
-
- connectedCallback() {
- this.renderComponent();
- this.renderSubcategorySelector();
- }
-
- static get observedAttributes() {
- return ['loaded', 'client', 'all_data', 'subcategory', 'technologies', 'metric', 'id'];
- }
-
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- this.renderComponent();
- }
-
- renderSubcategorySelector() {
- /* Get the subcategory slot content. */
- const subcategorySelector = this.shadowRoot.querySelector('slot[name="subcategory-selector"]');
-
- /* Only add event listener if subcategory slots were added. */
- if(subcategorySelector) {
- subcategorySelector.addEventListener('change', (event) => {
- this.setAttribute('subcategory', event.target.value);
- const url = new URL(window.location.href);
- url.searchParams.set(this.id, event.target.value);
- window.history.replaceState(null, null, url);
- });
- }
- }
-
- setData() {
- /* Turn the techs into an array */
- const technologies = this.technologies?.split(",");
-
- /* Select the elements within the component */
- const tableHead = this.shadowRoot.querySelector('table.table-ui thead tr');
- const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
- const tableCaption = this.shadowRoot.querySelector('table.table-ui caption');
- const tableWrapper = this.shadowRoot.querySelector('.table-ui-wrapper[role="region"]');
-
- /* Set the caption id and connect the wrapper to it */
- tableCaption.setAttribute('id', this.id);
- tableWrapper.setAttribute('aria-labelledby', this.id);
-
- /* Reset the component */
- tableBody.innerHTML = '';
- tableHead.innerHTML = '';
-
- /* Set the date heading */
- const dateHeading = document.createElement('th');
- dateHeading.innerHTML = 'Date';
- tableHead.append(dateHeading);
-
- const _dates = [];
-
- technologies.forEach(technology => {
- /* Fill in the tech names as column headings. */
- const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
- headingCellTemplate.querySelector('th').textContent = technology;
- tableHead.append(headingCellTemplate);
-
- /* TODO: This could be done in a central place after fetching the data */
- /* Add the dates to the dates array */
- const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client);
-
- _data?.forEach(entry => {
- if(!_dates.includes(entry.date)) {
- _dates.push(entry.date);
- }
- });
- });
-
- /* Add a row to the table body for each of the time entries */
- _dates.forEach(date => {
- /* Select the needed templates */
- const rowTemplate = document.getElementById('table-general-row').content.cloneNode(true).querySelector('tr');
- const headingCellTemplate = document.getElementById('table-general-heading-cell').content.cloneNode(true);
-
- /* Fill in the dates */
- headingCellTemplate.querySelector('th').textContent = date;
- rowTemplate.append(headingCellTemplate);
-
- /* For each of the technologies, select the chosen metric for the given date */
- technologies.forEach(technology => {
- const dataCellTemplate = document.getElementById('table-general-cell').content.cloneNode(true);
- const _data = this.allData?.[technology]?.filter(entry => entry.client === this.client)?.find(row => row.date === date);
- const metric = this.metric?.replaceAll("*subcategory*", this.subcategory);
-
- let cellContent;
- if(_data && _data[metric]) {
- const value = _data[metric];
- cellContent = `${value}${this.getAttribute('data-unit') || ''}`;
- } else {
- cellContent = '-';
- }
-
- dataCellTemplate.querySelector('td').textContent = cellContent;
- rowTemplate.appendChild(dataCellTemplate);
- });
-
- /* Append the row to the table */
- tableBody.appendChild(rowTemplate);
- });
- }
-
- renderComponent() {
- this.setData();
- }
-}
-
-customElements.define('table-general-multitech', tableGenralMulti);
diff --git a/src/js/components/tableOverview.js b/src/js/components/tableOverview.js
deleted file mode 100644
index b38ed23a..00000000
--- a/src/js/components/tableOverview.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { getLatestEntry } from "../utils";
-
-class TableOverview extends HTMLElement {
- constructor() {
- super();
-
- this.latest = {};
- this.allData = [];
-
- this.attachShadow({ mode: 'open' });
- const template = document.getElementById('table-overview').content.cloneNode(true);
- this.shadowRoot.appendChild(template);
- }
-
- connectedCallback() {
- this.renderComponent();
- }
-
- static get observedAttributes() {
- return ['loaded', 'client'];
- }
-
- attributeChangedCallback(property, oldValue, newValue) {
- if (oldValue === newValue) return;
- this[ property ] = newValue;
- this.renderComponent();
- }
-
- setTitle() {
-
- }
-
- setData() {
- const focusedData = this.allData.filter(entry => entry.client === this.client);
- const focusedDataSorted = [...focusedData].sort((a, b) => {
- return new Date(a.date) - new Date(b.date);
- });
-
- const latestFocus = getLatestEntry(focusedData);
-
- const tableBody = this.shadowRoot.querySelector('table.table-ui tbody');
- tableBody.innerHTML = '';
-
- const coreWebVitals = [
- {
- origins_with_good: "origins_with_good_cwv",
- origins_eligible: "origins_eligible_for_cwv",
- title: "Overall",
- },
- {
- origins_with_good: "origins_with_good_lcp",
- origins_eligible: "origins_with_any_lcp",
- title: "Largest Contentful Paint",
- },
- {
- origins_with_good: "origins_with_good_fid",
- origins_eligible: "origins_with_any_fid",
- title: "First Input Delay",
- },
- {
- origins_with_good: "origins_with_good_cls",
- origins_eligible: "origins_with_any_cls",
- title: "Cumulative Layout Shift",
- },
- {
- origins_with_good: "origins_with_good_inp",
- origins_eligible: "origins_with_any_inp",
- title: "Interaction to Next Paint",
- },
- ];
-
- coreWebVitals.forEach((cwv) => {
- if(cwv && latestFocus?.[cwv?.origins_with_good] && latestFocus[cwv?.origins_eligible]) {
- const rowTemplate = document.getElementById('table-overview-row').content.cloneNode(true);
- const latestPercentageGood = parseInt(latestFocus[cwv?.origins_with_good] / latestFocus[cwv?.origins_eligible] * 10000) / 100;
- rowTemplate.querySelector('tr th').textContent = cwv.title;
- rowTemplate.querySelectorAll('tr td')[0].textContent = `${latestPercentageGood}%`;
-
- focusedDataSorted.forEach((entry) => {
- const barTemplate = document.getElementById('table-overview-bar').content.cloneNode(true);
- const percentageGood = parseInt(entry[cwv?.origins_with_good] / entry[cwv?.origins_eligible] * 10000) / 100;
- const date = entry.date;
- barTemplate.querySelector('li.bar').style.setProperty('--height', `${percentageGood}%`);
- barTemplate.querySelector('li.bar .sr-only').textContent = `${date}: ${percentageGood}%`;
- rowTemplate.querySelector('tr td ul.table-bar-preview').append(barTemplate);
- })
- tableBody.append(rowTemplate);
- }
- });
- }
-
- renderComponent() {
- this.setTitle();
- this.setData();
- }
-}
-
-customElements.define('table-overview', TableOverview);
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index c3f6571e..26fdbd9d 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -172,7 +172,6 @@ class Timeseries {
const colors = this.defaults(config)?.chart?.colors;
pageFilters.app.forEach((app, index) => {
-
if(data[app] && data[app].length > 0) {
const sorted = data[app].sort((a, b) => new Date(b.date) - new Date(a.date));
const latest = sorted[0];
diff --git a/templates/techreport/landing.html b/templates/techreport/landing.html
index 424a8074..48585229 100644
--- a/templates/techreport/landing.html
+++ b/templates/techreport/landing.html
@@ -36,24 +36,6 @@
Explore
Placeholder
-
{% endblock %}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index dcbbbd84..9ab9b5ab 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -61,13 +61,6 @@
{% block main %}
{% block section %}{% endblock %}
-
- {% include "techreport/templates/drilldown_header.html" %}
- {% include "techreport/templates/table_general.html" %}
- {% include "techreport/templates/table_general_multi.html" %}
- {% include "techreport/templates/table_overview.html" %}
- {% include "techreport/templates/table_cwv_overview_multitech.html" %}
-
Accessibility
@@ -98,13 +91,6 @@
Accessibility
-
-
-
-
-
-
-
diff --git a/templates/techreport/templates/drilldown_header.html b/templates/techreport/templates/drilldown_header.html
deleted file mode 100644
index 36c78985..00000000
--- a/templates/techreport/templates/drilldown_header.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- Category
-
diff --git a/templates/techreport/templates/table_cwv_overview_multitech.html b/templates/techreport/templates/table_cwv_overview_multitech.html
deleted file mode 100644
index c9350d08..00000000
--- a/templates/techreport/templates/table_cwv_overview_multitech.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
- Data from
-
-
-
- The amount of origins with good Core Web Vitals of different technologies.
-
-
-
- Technology
- Origins
- % Overall Good CWVs
- Good LCP
- Good CLS
- Good FID
- Good INP
-
-
-
-
-
-
-
-
-
diff --git a/templates/techreport/templates/table_general.html b/templates/techreport/templates/table_general.html
deleted file mode 100644
index f2954aa2..00000000
--- a/templates/techreport/templates/table_general.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/templates/techreport/templates/table_general_multi.html b/templates/techreport/templates/table_general_multi.html
deleted file mode 100644
index bf2f51dd..00000000
--- a/templates/techreport/templates/table_general_multi.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Multiple technology comparison
-
-
-
-
-
-
-
-
-
-
diff --git a/templates/techreport/templates/table_overview.html b/templates/techreport/templates/table_overview.html
deleted file mode 100644
index c0578261..00000000
--- a/templates/techreport/templates/table_overview.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
- Percentage of tested origins that had good Core Web Vitals
-
-
-
- Core Web Vital
- % Good scores
- Trend
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/webpack.config.js b/webpack.config.js
index 17937b99..74d23eb8 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -15,13 +15,6 @@ module.exports = {
'techreport': './src/js/techreport/index.js',
'techreport/timeseries': './src/js/techreport/timeseries.js',
'techreport/section': './src/js/techreport/section.js',
-
- // TO UPDATE:
- 'summaryLinked': './src/js/components/summaryLinked.js',
- 'tableGeneral': './src/js/components/tableGeneral.js',
- 'tableGeneralMulti': './src/js/components/tableGeneralMulti.js',
- 'tableOverview': './src/js/components/tableOverview.js',
- 'tableCWVOverviewMulti': './src/js/components/tableCWVOverviewMulti.js',
},
output: {
path: path.resolve(__dirname, 'static/js'),
From 5ead94a409041566cd802a0faa26948fef043a03 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 4 Dec 2023 02:14:05 +0100
Subject: [PATCH 122/155] select app color based on settings and name
---
config/techreport.json | 17 +++++++++++
src/js/techreport/index.js | 54 +++------------------------------
src/js/techreport/timeseries.js | 18 ++++++-----
src/js/techreport/utils.js | 21 +++++++++++++
4 files changed, 53 insertions(+), 57 deletions(-)
create mode 100644 src/js/techreport/utils.js
diff --git a/config/techreport.json b/config/techreport.json
index 7db4aba3..9d1382dc 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -682,6 +682,23 @@
"title": "Comparison",
"subtitle": "Technology Report",
"config": {
+ "colors": {
+ "app": [
+ "#5980EB",
+ "#D55316",
+ "#2C2F70",
+ "#68A16D",
+ "#B979A7",
+ "#AC8D1C",
+ "#742F53",
+ "#449DB1",
+ "#8E3496",
+ "#CB377C"
+ ],
+ "overrides": {
+ "WordPress": "#c0ced0"
+ }
+ },
"default": {
"app": ["ALL", "WordPress", "Drupal"],
"series": {
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 0979cc89..d09ece00 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -1,6 +1,5 @@
const { DrilldownHeader } = require("../components/drilldownHeader");
const { Filters } = require("../components/filters");
-const { getPercentage } = require("../utils");
class TechReport {
constructor(pageId, page, config, labels) {
@@ -154,13 +153,13 @@ class TechReport {
...submetric,
desktop: {
...submetric.desktop,
- good_pct: submetric.desktop.tested > 0 ? parseInt(submetric.desktop.good_number / submetric.desktop.tested * 100) : 0,
+ good_pct: submetric?.desktop?.tested > 0 ? parseInt(submetric.desktop.good_number / submetric.desktop.tested * 100) : 0,
client: 'desktop',
date: date,
},
mobile: {
...submetric.mobile,
- good_pct: submetric.mobile.tested > 0 ? parseInt(submetric.mobile.good_number / submetric.mobile.tested * 100) : 0,
+ good_pct: submetric?.mobile?.tested > 0 ? parseInt(submetric.mobile.good_number / submetric.mobile.tested * 100) : 0,
client: 'mobile',
date: date,
},
@@ -174,13 +173,13 @@ class TechReport {
...submetric,
desktop: {
...submetric.desktop,
- median_score_pct: parseInt(submetric.desktop.median_score * 100),
+ median_score_pct: parseInt(submetric?.desktop?.median_score * 100),
client: 'desktop',
date: date,
},
mobile: {
...submetric.mobile,
- median_score_pct: parseInt(submetric.mobile.median_score * 100),
+ median_score_pct: parseInt(submetric?.mobile?.median_score * 100),
client: 'mobile',
date: date,
},
@@ -224,33 +223,8 @@ class TechReport {
});
}
- // Fetch all the data based on search criteria and config
- // TODO: Will be moved to the section level with new APIs
- getAllData() {
- const data = {};
- const technologies = this.filters.app;
-
- /* Make a request for each of the technologies and return them in an object.
- * Once we port this over to the new APIs, this should be moved to the section level.
- */
- Promise.all(technologies.map(technology => {
- const url = `https://cdn.httparchive.org/reports/cwvtech/${this.filters.rank}/${this.filters.geo}/${technology}.json`;
- return fetch(url)
- .then(result => result.json())
- .then(result => this.processData(result))
- .then(result => {
- data[technology] = result;
- })
- .catch(error => console.log('Something went wrong', error));
- })).then(() => {
- this.allData = data;
- this.updateComponents(data);
- });
- }
-
// New API
getAllMetricData() {
- const data = {};
const technologies = this.filters.app;
const apis = [
@@ -315,26 +289,6 @@ class TechReport {
});
}
- // Change data format from API data to what we need
- // TODO: Will be moved to the section level with new APIs
- processData(result) {
- return result.map(entry => {
- /* Calculate percentage of good core web vitals */
- entry.pct_good_cwv = getPercentage(entry.origins_with_good_cwv, entry.origins_eligible_for_cwv);
- this.config.cwv_subcategories.forEach(cwv => {
- entry[`origins_eligible_for_${cwv}`] = entry[`origins_with_any_${cwv}`];
- entry[`pct_good_${cwv}`] = getPercentage(entry[`origins_with_good_${cwv}`], entry[`origins_with_any_${cwv}`]);
- });
-
- // Turn the LH score from a decimal to an int
- this.config.lighthouse_subcategories.forEach(metric => {
- entry[`median_lighthouse_score_${metric}`] = parseInt(entry[`median_lighthouse_score_${metric}`] * 100);
- })
-
- return entry;
- });
- }
-
// Update components and sections that are relevant to the current page
// TODO: After moving to new APIs data won't have to be passed in like this anymore
updateComponents(data) {
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 26fdbd9d..b049658f 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -1,4 +1,5 @@
import { Table } from "./table";
+import { Utils } from "./utils";
class Timeseries {
// Create the component
constructor(id, config, filters, data) {
@@ -169,8 +170,6 @@ class Timeseries {
const endpoint = component.dataset.endpoint;
const client = component.dataset.client;
- const colors = this.defaults(config)?.chart?.colors;
-
pageFilters.app.forEach((app, index) => {
if(data[app] && data[app].length > 0) {
const sorted = data[app].sort((a, b) => new Date(b.date) - new Date(a.date));
@@ -197,7 +196,9 @@ class Timeseries {
value.innerHTML = 'No data';
}
timestamp.innerHTML = latest.date;
- card.style.setProperty('--breakdown-color', colors[index]);
+ const techColor = Utils.getAppColor(app, this.pageFilters.app, this.pageConfig.colors);
+ const fallback = this.pageConfig.colors.app[index];
+ card.style.setProperty('--breakdown-color', techColor || fallback);
}
});
}
@@ -282,9 +283,14 @@ class Timeseries {
const urlSubcategory = urlParams.get(config.param);
const subcategory = urlSubcategory || config.default;
+ // Get default colors
const colors = this.defaults(config)?.chart?.colors;
+ // Create series to use in Highcharts
Object.values(this.data).forEach((app, index) => {
+ const tech = app[0]?.technology;
+ const techColor = Utils.getAppColor(tech, this.pageFilters.app, this.pageConfig.colors);
+
const data = app.map(row => {
const value = row?.[endpoint]?.find(row => row.name === subcategory)?.[client]?.[metric];
return {
@@ -294,9 +300,9 @@ class Timeseries {
});
series.push({
- name: app[0]?.technology,
+ name: tech,
data: data,
- color: colors[index]
+ color: techColor || colors[index]
});
});
@@ -354,8 +360,6 @@ class Timeseries {
return series;
}
- getMetric() {}
-
getCategory(config) {
// The default metric from the settings
const defaultMetric = config.default;
diff --git a/src/js/techreport/utils.js b/src/js/techreport/utils.js
new file mode 100644
index 00000000..d2d86d71
--- /dev/null
+++ b/src/js/techreport/utils.js
@@ -0,0 +1,21 @@
+// Get the color associated with the techology
+// Based on the order of the technologies
+// To ensure the color is consistent per query
+const getAppColor = (tech, technologies, colors) => {
+ const sortedTechs = [...technologies].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
+ const techIndex = sortedTechs.indexOf(tech);
+
+ // Return custom colors if configured
+ if(colors.overrides && colors.overrides[tech]) {
+ return colors.overrides[tech];
+ }
+
+ // Otherwise reutrn based on alphabetic position
+ if(techIndex < colors.app.length) {
+ return colors.app[techIndex];
+ }
+}
+
+export const Utils = {
+ getAppColor,
+}
From aaffd3ba17e2d42c1f17e9fc82548a16a18deec6 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 4 Dec 2023 02:31:23 +0100
Subject: [PATCH 123/155] move reusable code to utils
---
src/js/techreport/index.js | 133 ++++++--------------------------
src/js/techreport/timeseries.js | 2 +-
src/js/techreport/utils.js | 80 +++++++++++++++++++
3 files changed, 104 insertions(+), 111 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index d09ece00..14155a05 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -1,5 +1,6 @@
const { DrilldownHeader } = require("../components/drilldownHeader");
const { Filters } = require("../components/filters");
+const { Utils } = require("./utils");
class TechReport {
constructor(pageId, page, config, labels) {
@@ -147,82 +148,6 @@ class TechReport {
});
}
- parseVitalsData(metric, date) {
- return metric.map(submetric => {
- return {
- ...submetric,
- desktop: {
- ...submetric.desktop,
- good_pct: submetric?.desktop?.tested > 0 ? parseInt(submetric.desktop.good_number / submetric.desktop.tested * 100) : 0,
- client: 'desktop',
- date: date,
- },
- mobile: {
- ...submetric.mobile,
- good_pct: submetric?.mobile?.tested > 0 ? parseInt(submetric.mobile.good_number / submetric.mobile.tested * 100) : 0,
- client: 'mobile',
- date: date,
- },
- };
- });
- }
-
- parseLighthouseData(metric, date) {
- return metric.map(submetric => {
- return {
- ...submetric,
- desktop: {
- ...submetric.desktop,
- median_score_pct: parseInt(submetric?.desktop?.median_score * 100),
- client: 'desktop',
- date: date,
- },
- mobile: {
- ...submetric.mobile,
- median_score_pct: parseInt(submetric?.mobile?.median_score * 100),
- client: 'mobile',
- date: date,
- },
- };
- });
- }
-
- parseAdoptionData(submetric, date) {
- return [
- {
- desktop: {
- origins: submetric.desktop,
- client: 'desktop',
- date: date,
- },
- mobile: {
- origins: submetric.mobile,
- client: 'mobile',
- date: date,
- },
- name: 'adoption',
- },
- ];
- }
-
- parsePageWeightData(metric, date) {
- return metric.map(submetric => {
- return {
- ...submetric,
- desktop: {
- ...submetric.desktop,
- client: 'desktop',
- date: date,
- },
- mobile: {
- ...submetric.mobile,
- client: 'mobile',
- date: date,
- },
- };
- });
- }
-
// New API
getAllMetricData() {
const technologies = this.filters.app;
@@ -231,22 +156,22 @@ class TechReport {
{
endpoint: 'cwv',
metric: 'vitals',
- parse: this.parseVitalsData,
+ parse: Utils.parseVitalsData,
},
{
endpoint: 'lighthouse',
metric: 'lighthouse',
- parse: this.parseLighthouseData,
+ parse: Utils.parseLighthouseData,
},
{
endpoint: 'adoption',
metric: 'adoption',
- parse: this.parseAdoptionData,
+ parse: Utils.parseAdoptionData,
},
{
endpoint: 'page-weight',
metric: 'pageWeight',
- parse: this.parsePageWeightData,
+ parse: Utils.parsePageWeightData,
},
];
@@ -346,20 +271,7 @@ class TechReport {
const app = this.filters.app[0];
if(data && data[app]) {
- // Update sections
- Object.values(this.sections).forEach(section => {
- section.data = data;
- section.updateSection();
- });
-
- // Update web components
- // TODO: Change to same system as sections/timeseries
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
- allDataComponents.forEach((component) => {
- component.allData = data[app];
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- });
+ this.updateReportComponents(this.sections, data, data[app]);
} else {
this.updateWithEmptyData();
}
@@ -367,27 +279,28 @@ class TechReport {
updateComparisonComponents(data) {
if(data && Object.keys(data).length > 0) {
- // TODO: this doesn't have to be diff for landing / comp / drilldown
- // Update sections
- Object.values(this.sections).forEach(section => {
- section.data = data;
- section.updateSection();
- });
-
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
-
- allDataComponents.forEach((component) => {
- component.allData = data;
- component.page = this.page;
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- component.setAttribute('all_data', JSON.stringify(data));
- });
+ this.updateReportComponents(this.sections, data, data);
} else {
this.updateWithEmptyData();
}
}
+ updateReportComponents(sections, data, allData) {
+ // Update sections
+ Object.values(sections).forEach(section => {
+ section.data = data;
+ section.updateSection();
+ });
+
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = allData;
+ component.page = this.page;
+ component.labels = this.labels;
+ component.setAttribute('loaded', true);
+ });
+ }
+
// Add error message if no data was found
updateWithEmptyData() {
const text = document.createElement('p');
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index b049658f..722c19a5 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -378,7 +378,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: ['#5980EB', '#D55316', '#2C2F70', '#68A16D', '#B979A7', '#AC8D1C', '#742F53', '#449DB1', '#8E3496', '#CB377C'],
+ colors: this.pageConfig.colors.app,
},
title: {
text: config?.title,
diff --git a/src/js/techreport/utils.js b/src/js/techreport/utils.js
index d2d86d71..0dbd1712 100644
--- a/src/js/techreport/utils.js
+++ b/src/js/techreport/utils.js
@@ -16,6 +16,86 @@ const getAppColor = (tech, technologies, colors) => {
}
}
+const parseVitalsData = (metric, date) => {
+ return metric.map(submetric => {
+ return {
+ ...submetric,
+ desktop: {
+ ...submetric.desktop,
+ good_pct: submetric?.desktop?.tested > 0 ? parseInt(submetric.desktop.good_number / submetric.desktop.tested * 100) : 0,
+ client: 'desktop',
+ date: date,
+ },
+ mobile: {
+ ...submetric.mobile,
+ good_pct: submetric?.mobile?.tested > 0 ? parseInt(submetric.mobile.good_number / submetric.mobile.tested * 100) : 0,
+ client: 'mobile',
+ date: date,
+ },
+ };
+ });
+}
+
+const parseLighthouseData = (metric, date) => {
+ return metric.map(submetric => {
+ return {
+ ...submetric,
+ desktop: {
+ ...submetric.desktop,
+ median_score_pct: parseInt(submetric?.desktop?.median_score * 100),
+ client: 'desktop',
+ date: date,
+ },
+ mobile: {
+ ...submetric.mobile,
+ median_score_pct: parseInt(submetric?.mobile?.median_score * 100),
+ client: 'mobile',
+ date: date,
+ },
+ };
+ });
+}
+
+const parseAdoptionData = (submetric, date) => {
+ return [
+ {
+ desktop: {
+ origins: submetric.desktop,
+ client: 'desktop',
+ date: date,
+ },
+ mobile: {
+ origins: submetric.mobile,
+ client: 'mobile',
+ date: date,
+ },
+ name: 'adoption',
+ },
+ ];
+}
+
+const parsePageWeightData = (metric, date) => {
+ return metric.map(submetric => {
+ return {
+ ...submetric,
+ desktop: {
+ ...submetric.desktop,
+ client: 'desktop',
+ date: date,
+ },
+ mobile: {
+ ...submetric.mobile,
+ client: 'mobile',
+ date: date,
+ },
+ };
+ });
+}
+
export const Utils = {
getAppColor,
+ parseVitalsData,
+ parseLighthouseData,
+ parseAdoptionData,
+ parsePageWeightData,
}
From 2c428dec8cfba1836388530c54f29798d49537c4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 4 Dec 2023 02:40:51 +0100
Subject: [PATCH 124/155] utils cleanup
---
src/js/techreport/index.js | 31 ++++----------
src/js/techreport/timeseries.js | 6 +--
src/js/techreport/{utils.js => utils/data.js} | 23 +----------
src/js/techreport/utils/ui.js | 40 +++++++++++++++++++
4 files changed, 53 insertions(+), 47 deletions(-)
rename src/js/techreport/{utils.js => utils/data.js} (73%)
create mode 100644 src/js/techreport/utils/ui.js
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 14155a05..4653323e 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -1,6 +1,7 @@
const { DrilldownHeader } = require("../components/drilldownHeader");
const { Filters } = require("../components/filters");
-const { Utils } = require("./utils");
+const { DataUtils } = require("./utils/data");
+const { UIUtils } = require("./utils/ui");
class TechReport {
constructor(pageId, page, config, labels) {
@@ -156,22 +157,22 @@ class TechReport {
{
endpoint: 'cwv',
metric: 'vitals',
- parse: Utils.parseVitalsData,
+ parse: DataUtils.parseVitalsData,
},
{
endpoint: 'lighthouse',
metric: 'lighthouse',
- parse: Utils.parseLighthouseData,
+ parse: DataUtils.parseLighthouseData,
},
{
endpoint: 'adoption',
metric: 'adoption',
- parse: Utils.parseAdoptionData,
+ parse: DataUtils.parseAdoptionData,
},
{
endpoint: 'page-weight',
metric: 'pageWeight',
- parse: Utils.parsePageWeightData,
+ parse: DataUtils.parsePageWeightData,
},
];
@@ -271,7 +272,7 @@ class TechReport {
const app = this.filters.app[0];
if(data && data[app]) {
- this.updateReportComponents(this.sections, data, data[app]);
+ UIUtils.updateReportComponents(this.sections, data, data[app], this.page, this.labels);
} else {
this.updateWithEmptyData();
}
@@ -279,28 +280,12 @@ class TechReport {
updateComparisonComponents(data) {
if(data && Object.keys(data).length > 0) {
- this.updateReportComponents(this.sections, data, data);
+ UIUtils.updateReportComponents(this.sections, data, data, this.page, this.labels);
} else {
this.updateWithEmptyData();
}
}
- updateReportComponents(sections, data, allData) {
- // Update sections
- Object.values(sections).forEach(section => {
- section.data = data;
- section.updateSection();
- });
-
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
- allDataComponents.forEach((component) => {
- component.allData = allData;
- component.page = this.page;
- component.labels = this.labels;
- component.setAttribute('loaded', true);
- });
- }
-
// Add error message if no data was found
updateWithEmptyData() {
const text = document.createElement('p');
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 722c19a5..6e857e0a 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -1,5 +1,5 @@
import { Table } from "./table";
-import { Utils } from "./utils";
+import { UIUtils } from "./utils/ui";
class Timeseries {
// Create the component
constructor(id, config, filters, data) {
@@ -196,7 +196,7 @@ class Timeseries {
value.innerHTML = 'No data';
}
timestamp.innerHTML = latest.date;
- const techColor = Utils.getAppColor(app, this.pageFilters.app, this.pageConfig.colors);
+ const techColor = UIUtils.getAppColor(app, this.pageFilters.app, this.pageConfig.colors);
const fallback = this.pageConfig.colors.app[index];
card.style.setProperty('--breakdown-color', techColor || fallback);
}
@@ -289,7 +289,7 @@ class Timeseries {
// Create series to use in Highcharts
Object.values(this.data).forEach((app, index) => {
const tech = app[0]?.technology;
- const techColor = Utils.getAppColor(tech, this.pageFilters.app, this.pageConfig.colors);
+ const techColor = UIUtils.getAppColor(tech, this.pageFilters.app, this.pageConfig.colors);
const data = app.map(row => {
const value = row?.[endpoint]?.find(row => row.name === subcategory)?.[client]?.[metric];
diff --git a/src/js/techreport/utils.js b/src/js/techreport/utils/data.js
similarity index 73%
rename from src/js/techreport/utils.js
rename to src/js/techreport/utils/data.js
index 0dbd1712..0dfe404b 100644
--- a/src/js/techreport/utils.js
+++ b/src/js/techreport/utils/data.js
@@ -1,21 +1,3 @@
-// Get the color associated with the techology
-// Based on the order of the technologies
-// To ensure the color is consistent per query
-const getAppColor = (tech, technologies, colors) => {
- const sortedTechs = [...technologies].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
- const techIndex = sortedTechs.indexOf(tech);
-
- // Return custom colors if configured
- if(colors.overrides && colors.overrides[tech]) {
- return colors.overrides[tech];
- }
-
- // Otherwise reutrn based on alphabetic position
- if(techIndex < colors.app.length) {
- return colors.app[techIndex];
- }
-}
-
const parseVitalsData = (metric, date) => {
return metric.map(submetric => {
return {
@@ -92,10 +74,9 @@ const parsePageWeightData = (metric, date) => {
});
}
-export const Utils = {
- getAppColor,
+export const DataUtils = {
parseVitalsData,
parseLighthouseData,
parseAdoptionData,
parsePageWeightData,
-}
+};
diff --git a/src/js/techreport/utils/ui.js b/src/js/techreport/utils/ui.js
new file mode 100644
index 00000000..e493d089
--- /dev/null
+++ b/src/js/techreport/utils/ui.js
@@ -0,0 +1,40 @@
+// Get the color associated with the techology
+// Based on the order of the technologies
+// To ensure the color is consistent per query
+const getAppColor = (tech, technologies, colors) => {
+ const sortedTechs = [...technologies].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
+ const techIndex = sortedTechs.indexOf(tech);
+
+ // Return custom colors if configured
+ if(colors.overrides && colors.overrides[tech]) {
+ return colors.overrides[tech];
+ }
+
+ // Otherwise reutrn based on alphabetic position
+ if(techIndex < colors.app.length) {
+ return colors.app[techIndex];
+ }
+}
+
+// Loop through all the sections in the report
+// Pass in the new data and config, and re-render
+const updateReportComponents = (sections, data, allData, page, labels) => {
+ // Update sections
+ Object.values(sections).forEach(section => {
+ section.data = data;
+ section.updateSection();
+ });
+
+ const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
+ allDataComponents.forEach((component) => {
+ component.allData = allData;
+ component.page = page;
+ component.labels = labels;
+ component.setAttribute('loaded', true);
+ });
+}
+
+export const UIUtils = {
+ getAppColor,
+ updateReportComponents,
+}
From 69ab1df975b1e04df339c75f15c0e563099e64d3 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 5 Dec 2023 11:36:44 +0100
Subject: [PATCH 125/155] update descriptions
---
config/techreport.json | 20 ++++++++++----------
templates/techreport/drilldown.html | 2 +-
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index 9d1382dc..d5ca22ee 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -1068,38 +1068,38 @@
"labels": {
"metrics": {
- "cwv": {
+ "overall": {
"label": "Overall good CWVs",
- "title": "Origins with overall good Core Web Vitals",
+ "title": "Origins with good CWVs",
"description": "overall todo"
},
- "lcp": {
+ "LCP": {
"label": "LCP",
"title": "Origins with good LCP",
"description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
},
- "fid": {
+ "FID": {
"label": "FID",
"title": "Origins with good FID",
- "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ "description": "First Input Delay (FID) measures the time from when a user first interacts with a page, to the time when the browser is actually able to begin processing event handlers in response to that interaction. Sites should strive to have a First Input Delay of 100 milliseconds or less. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
},
- "cls": {
+ "CLS": {
"label": "CLS",
"title": "Origins with good CLS",
- "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
+ "description": "The Cumulative Layout Shift (CLS) score is a unitless value based on a calculation of how much content is shifting and by how far. Sites should strive to have a CLS of 0.1 or less for at least 75% of page visits"
},
- "fcp": {
+ "FCP": {
"label": "FCP",
"value": "fcp",
"title": "Origins with good FCP",
"description": "todo find fcp description"
},
- "ttfb": {
+ "TTFB": {
"label": "TTFB",
"title": "Origins with good TTFB",
"description": "todo find fcp description"
},
- "inp": {
+ "INP": {
"label": "INP",
"title": "Origins with good LCP",
"description": "todo find fcp description"
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 4aa17229..091375c5 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -56,7 +56,7 @@ Summary
data-api="cwv"
>
Core Web Vitals
- Description
+ Each of the Core Web Vitals represents a distinct facet of the user experience, is measurable in the field, and reflects the real-world experience of a critical user-centric outcome. A good threshold to measure is the 75th percentile of page loads, segmented across mobile and desktop devices.
{% if tech_report_page.config.good_cwv_summary %}
{{ tech_report_page.config.good_cwv_summary.title }}
From e8753cafd8123f84f26058b2e088189a0d6454b4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Tue, 5 Dec 2023 11:36:50 +0100
Subject: [PATCH 126/155] cleanup
---
src/js/techreport/index.js | 1 -
src/js/techreport/timeseries.js | 3 ++-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 4653323e..5d73dbe2 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -216,7 +216,6 @@ class TechReport {
}
// Update components and sections that are relevant to the current page
- // TODO: After moving to new APIs data won't have to be passed in like this anymore
updateComponents(data) {
switch(this.pageId) {
case 'landing':
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 6e857e0a..f17c5c04 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -206,6 +206,7 @@ class Timeseries {
// Update the highcharts timeseries
updateViz() {
const config = this.pageConfig[this.id]?.viz;
+ console.log('updateViz', config);
const timeseries = this.defaults(config);
// Accessibility settings
@@ -378,7 +379,7 @@ class Timeseries {
const defaults = {
type: 'timeseries',
chart: {
- colors: this.pageConfig.colors.app,
+ colors: this.pageConfig.colors?.app,
},
title: {
text: config?.title,
From 515823243c447e788a0dc0b349c1b8f92da548b4 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 6 Dec 2023 02:50:39 +0100
Subject: [PATCH 127/155] fix bugs with text
---
config/techreport.json | 215 ++++++++----------
src/js/techreport/timeseries.js | 11 +-
.../techreport/components/subcategory.html | 2 +-
.../techreport/components/timeseries.html | 10 +-
templates/techreport/drilldown.html | 6 +-
5 files changed, 117 insertions(+), 127 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index d5ca22ee..a3e41e8e 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -266,45 +266,31 @@
"options": [
{
"label": "Overall good CWVs",
- "value": "overall",
- "title": "Origins with overall good Core Web Vitals",
- "description": "overall todo"
+ "value": "overall"
},
{
"label": "LCP",
- "value": "LCP",
- "title": "Origins with good LCP",
- "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
+ "value": "LCP"
},
{
"label": "FID",
- "value": "FID",
- "title": "Origins with good FID",
- "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ "value": "FID"
},
{
"label": "CLS",
- "value": "CLS",
- "title": "Origins with good CLS",
- "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
+ "value": "CLS"
},
{
"label": "FCP",
- "value": "FCP",
- "title": "Origins with good FCP",
- "description": "todo find fcp description"
+ "value": "FCP"
},
{
"label": "TTFB",
- "value": "TTFB",
- "title": "Origins with good TTFB",
- "description": "todo find fcp description"
+ "value": "TTFB"
},
{
"label": "INP",
- "value": "INP",
- "title": "Origins with good LCP",
- "description": "todo find fcp description"
+ "value": "INP"
}
]
},
@@ -552,19 +538,25 @@
"title": "Latest page weight",
"cards": [
{
- "metric": "median_bytes_image",
+ "endpoint": "pageWeight",
+ "category": "images",
+ "metric": "median_bytes",
"label": "Image Weight",
"url": "?weight-over-time=image#page-weight",
"suffix": " kB"
},
{
- "metric": "median_bytes_js",
+ "endpoint": "pageWeight",
+ "category": "js",
+ "metric": "median_bytes",
"label": "JavaScript Size",
"url": "?weight-over-time=js#page-weight",
"suffix": " kB"
},
{
- "metric": "median_bytes_total",
+ "endpoint": "pageWeight",
+ "category": "total",
+ "metric": "median_bytes",
"label": "Total Page Weight",
"url": "?weight-over-time=total#page-weight",
"suffix": " kB"
@@ -577,6 +569,7 @@
"id": "weight_timeseries",
"summary": true,
"endpoint": "pageWeight",
+ "default": "images",
"metric": "median_bytes",
"subcategory": {
"base": "median_bytes_",
@@ -772,45 +765,31 @@
"options": [
{
"label": "Overall good CWVs",
- "value": "overall",
- "title": "Origins with overall good Core Web Vitals",
- "description": "overall todo"
+ "value": "overall"
},
{
"label": "LCP",
- "value": "LCP",
- "title": "Origins with good LCP",
- "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
+ "value": "LCP"
},
{
"label": "FID",
- "value": "FID",
- "title": "Origins with good FID",
- "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ "value": "FID"
},
{
"label": "CLS",
- "value": "CLS",
- "title": "Origins with good CLS",
- "description": "Cumulative Layout Shift (CLS) is a stable Core Web Vital metric. It is an important, user-centric metric for measuring visual stability because it helps quantify how often users experience unexpected layout shifts—a low CLS helps ensure that the page is delightful."
+ "value": "CLS"
},
{
"label": "FCP",
- "value": "FCP",
- "title": "Origins with good FCP",
- "description": "todo find fcp description"
+ "value": "FCP"
},
{
"label": "TTFB",
- "value": "TTFB",
- "title": "Origins with good TTFB",
- "description": "todo find fcp description"
+ "value": "TTFB"
},
{
"label": "INP",
- "value": "INP",
- "title": "Origins with good LCP",
- "description": "todo find fcp description"
+ "value": "INP"
}
]
},
@@ -1068,41 +1047,85 @@
"labels": {
"metrics": {
- "overall": {
- "label": "Overall good CWVs",
- "title": "Origins with good CWVs",
- "description": "overall todo"
- },
- "LCP": {
- "label": "LCP",
- "title": "Origins with good LCP",
- "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful."
- },
- "FID": {
- "label": "FID",
- "title": "Origins with good FID",
- "description": "First Input Delay (FID) measures the time from when a user first interacts with a page, to the time when the browser is actually able to begin processing event handlers in response to that interaction. Sites should strive to have a First Input Delay of 100 milliseconds or less. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
- },
- "CLS": {
- "label": "CLS",
- "title": "Origins with good CLS",
- "description": "The Cumulative Layout Shift (CLS) score is a unitless value based on a calculation of how much content is shifting and by how far. Sites should strive to have a CLS of 0.1 or less for at least 75% of page visits"
+ "lighthouse": {
+ "performance": {
+ "title": "Performance",
+ "description": "In general, only metrics contribute to your Lighthouse Performance score, not the results of Opportunities or Diagnostics. "
+ },
+ "accessibility": {
+ "title": "Accessibility",
+ "description": "The Lighthouse Accessibility score is a weighted average of all accessibility audits. Weighting is based on axe user impact assessments. Each accessibility audit is pass or fail. Unlike the Performance audits, a page doesn't get points for partially passing an accessibility audit."
+ },
+ "seo": {
+ "title": "SEO",
+ "description": "todo"
+ },
+ "best_practices": {
+ "title": "Best Practices",
+ "description": "todo"
+ },
+ "pwa": {
+ "title": "Progressive Web Apps",
+ "description": "todo"
+ }
},
- "FCP": {
- "label": "FCP",
- "value": "fcp",
- "title": "Origins with good FCP",
- "description": "todo find fcp description"
+ "vitals": {
+ "overall": {
+ "label": "Overall Core Web Vitals",
+ "title": "Passes Core Web Vitals",
+ "description": "The percentage of origins passing all three Core Web Vitals (LCP, FID, CLS) with a good experience. Note that if an origin is missing FID data, it's assessed based on the performance of the remaining metrics."
+ },
+ "LCP": {
+ "label": "LCP",
+ "title": "Good Largest Contentful Paint",
+ "description": "Largest Contentful Paint (LCP) is an important, stable Core Web Vital metric for measuring perceived load speed because it marks the point in the page load timeline when the page's main content has likely loaded—a fast LCP helps reassure the user that the page is useful. Good experiences are less than or equal to 2.5 seconds."
+ },
+ "FID": {
+ "label": "FID",
+ "title": "Good First Input Delay",
+ "description": "First Input Delay (FID) measures the time from when a user first interacts with a page, to the time when the browser is actually able to begin processing event handlers in response to that interaction. Sites should strive to have a First Input Delay of 100 milliseconds or less. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
+ },
+ "CLS": {
+ "label": "CLS",
+ "title": "Good Cumulative Layout Shift",
+ "description": "The Cumulative Layout Shift (CLS) score is a unitless value based on a calculation of how much content is shifting and by how far. Sites should strive to have a CLS of 0.1 or less for at least 75% of page visits."
+ },
+ "FCP": {
+ "label": "FCP",
+ "value": "fcp",
+ "title": "Good First Contentful Paint",
+ "description": "The percentage of origins with good FCP experiences, less than or equal to 1.8 seconds"
+ },
+ "TTFB": {
+ "label": "TTFB",
+ "title": "Good Time To First Byte",
+ "description": "TTFB is a metric that measures the time between the request for a resource and when the first byte of a response begins to arrive. A good TTFB is less than or equal to 800ms."
+ },
+ "INP": {
+ "label": "INP",
+ "title": "Good Interaction to Next Paint",
+ "description": "INP is a metric that assesses a page's overall responsiveness to user interactions by observing the latency of all click, tap, and keyboard interactions that occur throughout the lifespan of a user's visit to a page. The final INP value is the longest interaction observed, ignoring outliers. A good experience is less than or equal to 200ms."
+ }
},
- "TTFB": {
- "label": "TTFB",
- "title": "Origins with good TTFB",
- "description": "todo find fcp description"
+ "pageWeight": {
+ "images": {
+ "title": "Image Weight",
+ "description": "todo"
+ },
+ "js": {
+ "title": "JavaScript Transfer Size",
+ "description": "todo"
+ },
+ "total": {
+ "title": "Total Page Weight",
+ "description": "todo"
+ }
},
- "INP": {
- "label": "INP",
- "title": "Origins with good LCP",
- "description": "todo find fcp description"
+ "adoption": {
+ "adoption": {
+ "title": "Adoption",
+ "description": "Todo"
+ }
}
},
"values": {
@@ -1145,44 +1168,6 @@
"median_bytes_total":"Median bytes total"
}
},
- "metrics": {
- "cwv": {
- "title": "Core Web Vitals",
- "shortened": "CWVs",
- "description": ""
- },
- "lcp": {
- "title": "Largest Contentful Paint",
- "shortened": "LCP",
- "description": ""
- },
- "fid": {
- "title": "First Input Delay",
- "shortened": "FID",
- "description": "First Input Delay (FID) is the stable Core Web Vital metric for measuring load responsiveness because it quantifies the experience users feel when trying to interact with unresponsive pages—a low FID helps ensure that the page is usable. FID will be replaced by Interaction to Next Paint (INP) as a Core Web Vital in March 2024."
- },
- "cls": {
- "title": "Cumulative Layout Shift",
- "shortened": "CLS",
- "description": ""
- },
- "fcp": {
- "title": "First Contentful Paint",
- "shortened": "FCP",
- "description": ""
- },
- "inp": {
- "title": "Interaction to Next Paint",
- "shortened": "INP",
- "description": ""
- },
- "ttfb": {
- "title": "Time to First Byte",
- "shortened": "TTFB",
- "description": ""
- }
- },
-
"graphic": {
"bgcolor": "#fff",
"primary": {
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index f17c5c04..512147fe 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -34,9 +34,13 @@ class Timeseries {
url.searchParams.set(event.target.dataset.param, event.target.value);
window.history.replaceState(null, null, url);
+ // Get the relevant endpoint and metric
+ const endpoint = event.target.dataset.endpoint;
+ const metric = event.target.value;
+
// Re-render the content
this.updateContent();
- this.updateInfo(event.target.value);
+ this.updateInfo(metric, endpoint);
}
}
@@ -54,8 +58,8 @@ class Timeseries {
}
// Re-render the title, description, and text labels
- updateInfo(value) {
- const option = this.pageConfig?.labels?.metrics[value];
+ updateInfo(metric, endpoint) {
+ const option = this.pageConfig?.labels?.metrics[endpoint][metric];
const component = document.querySelector(`[data-id="${this.id}"]`);
if(option && option.title) {
@@ -206,7 +210,6 @@ class Timeseries {
// Update the highcharts timeseries
updateViz() {
const config = this.pageConfig[this.id]?.viz;
- console.log('updateViz', config);
const timeseries = this.defaults(config);
// Accessibility settings
diff --git a/templates/techreport/components/subcategory.html b/templates/techreport/components/subcategory.html
index 0a2de6de..f8adaa67 100644
--- a/templates/techreport/components/subcategory.html
+++ b/templates/techreport/components/subcategory.html
@@ -7,7 +7,7 @@
id="subcategory-{{ subcategory.base }}"
data-controls="{{ id }}"
data-param="{{ subcategory.param }}"
- data-base="{{ subcategory.base }}"
+ data-endpoint="{{ endpoint }}"
>
{% for option in subcategory.options %}
diff --git a/templates/techreport/components/timeseries.html b/templates/techreport/components/timeseries.html
index fe3fa594..5eb42ac6 100644
--- a/templates/techreport/components/timeseries.html
+++ b/templates/techreport/components/timeseries.html
@@ -1,13 +1,14 @@
-{% set category = request.args.get(subcategory.param, '') or subcategory.default %}
+{% set category = selected_subcategory or subcategory.default %}
+{% set endpoint = timeseries.endpoint %}
{% set title = timeseries.title %}
{% set descr = timeseries.description %}
- {% if tech_report_labels.metrics[category] %}
- {% set title = tech_report_labels.metrics[category].title %}
- {% set descr = tech_report_labels.metrics[category].description %}
+ {% if tech_report_labels.metrics[endpoint][selected_subcategory] %}
+ {% set title = tech_report_labels.metrics[endpoint][selected_subcategory].title %}
+ {% set descr = tech_report_labels.metrics[endpoint][selected_subcategory].description %}
{% endif %}
{{ title }}
@@ -61,7 +62,6 @@
{% set table = timeseries.table %}
{% set id = timeseries.id %}
- {% set endpoint = timeseries.endpoint %}
{% set metric = timeseries.metric %}
{% set client = request.args.get('client', '') or 'mobile' %}
{% include "techreport/components/table.html" %}
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 091375c5..8bc6b318 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -70,7 +70,7 @@
{{ tech_report_page.config.good_cwv_summary.title }}
{% set timeseries = tech_report_page.config.good_cwv_timeseries %}
- {% set subcategory = request.args.get('good-cwv-over-time', '') or tech_report_page.config.good_cwv_timeseries.viz.default or 'overall' %}
+ {% set selected_subcategory = request.args.get('good-cwv-over-time', '') or tech_report_page.config.good_cwv_timeseries.viz.default or 'overall' %}
{% include "techreport/components/timeseries.html" %}
@@ -97,7 +97,7 @@ {{ tech_report_page.config.lighthouse_summary.title }}
{% set timeseries = tech_report_page.config.lighthouse_timeseries %}
- {% set subcategory = request.args.get('median-lighthouse-over-time', '') or 'performance' %}
+ {% set selected_subcategory = request.args.get('median-lighthouse-over-time', '') or 'performance' %}
{% include "techreport/components/timeseries.html" %}
@@ -124,6 +124,7 @@
{{ tech_report_page.config.weight_summary.title }}
{% set timeseries = tech_report_page.config.weight_timeseries %}
+ {% set selected_subcategory = request.args.get('weight-over-time', '') or tech_report_page.config.weight_timeseries.viz.default or 'performance' %}
{% include "techreport/components/timeseries.html" %}
@@ -140,6 +141,7 @@
Adoption
{% set timeseries = tech_report_page.config.adoption_timeseries %}
+ {% set selected_subcategory = tech_report_page.config.adoption_timeseries.viz.default or 'adoption' %}
{% include "techreport/components/timeseries.html" %}
From c9f2a51bcc6dad32e5dcd4c2dbdf5e0c788e627b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 6 Dec 2023 13:16:57 +0100
Subject: [PATCH 128/155] improve sr/keyboard interaction of charts
---
config/techreport.json | 115 +++++++++++++++++++++++++++-----
src/js/components/filters.js | 12 ++--
src/js/techreport/index.js | 11 ++-
src/js/techreport/timeseries.js | 4 +-
4 files changed, 116 insertions(+), 26 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index a3e41e8e..b37afa98 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -179,8 +179,7 @@
]
},
"xAxis": {
- "title": "Months",
- "description": "accessibility description of x-axis",
+ "title": "Monthly entries",
"tickAmount": 12,
"defaults": [
"Jan",
@@ -198,7 +197,7 @@
]
},
"yAxis": {
- "title": "Origins",
+ "title": "Amount of origins",
"tickAmount": 3
}
}
@@ -297,7 +296,7 @@
"table": {
"param":"good-cwv-over-time",
"default": "overall",
- "caption": "Good Core Web Vitals placeholder",
+ "caption": "Good Core Web Vitals",
"columns": [
{
"key": "date",
@@ -362,8 +361,7 @@
]
},
"xAxis": {
- "title": "Months",
- "description": "accessibility description of x-axis",
+ "title": "Monthly entries",
"tickAmount": 12,
"defaults": [
"Jan",
@@ -381,7 +379,7 @@
]
},
"yAxis": {
- "title": "% Good CWVs"
+ "title": "% Origins with good scores"
}
}
},
@@ -484,7 +482,7 @@
"base": "median_lighthouse_score_",
"param": "median-lighthouse-over-time",
"default": "performance",
- "title": "Performance lighthouse scores over time",
+ "title": "Scores over time",
"metric": "median_score_pct",
"height": 600,
"series": {
@@ -511,8 +509,7 @@
]
},
"xAxis": {
- "title": "Months",
- "description": "accessibility description of x-axis",
+ "title": "Monthly entries",
"tickAmount": 12,
"defaults": [
"Jan",
@@ -530,7 +527,7 @@
]
},
"yAxis": {
- "title": "Performance score"
+ "title": "Lighthouse Score"
}
}
},
@@ -645,8 +642,7 @@
]
},
"xAxis": {
- "title": "Months",
- "description": "accessibility description of x-axis",
+ "title": "Monthly entries",
"tickAmount": 12,
"defaults": [
"Jan",
@@ -664,7 +660,7 @@
]
},
"yAxis": {
- "title": "Image weight (kB)"
+ "title": "Weight in kB"
}
}
}
@@ -689,7 +685,7 @@
"#CB377C"
],
"overrides": {
- "WordPress": "#c0ced0"
+ "WordPress": "#ff0000"
}
},
"default": {
@@ -837,7 +833,28 @@
"name": "App",
"data": [0,0,0,0,0,0,0,0,0,0,0,0]
}
- ]
+ ],
+ "xAxis": {
+ "title": "Monthly entries",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
+ },
+ "yAxis": {
+ "title": "% Origins with good scores"
+ }
}
}
},
@@ -916,6 +933,27 @@
"data": [0,0,0,0,0,0,0,0,0,0,0,0]
}
]
+ },
+ "xAxis": {
+ "title": "Monthly entries",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
+ },
+ "yAxis": {
+ "title": "Lighthouse Score"
}
}
},
@@ -988,6 +1026,27 @@
"data": [0,0,0,0,0,0,0,0,0,0,0,0]
}
]
+ },
+ "xAxis": {
+ "title": "Monthly entries",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
+ },
+ "yAxis": {
+ "title": "Weight in kB"
}
}
},
@@ -1036,7 +1095,29 @@
"name": "App",
"data": [0,0,0,0,0,0,0,0,0,0,0,0]
}
- ]
+ ],
+ "xAxis": {
+ "title": "Monthly entries",
+ "tickAmount": 12,
+ "defaults": [
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ ]
+ },
+ "yAxis": {
+ "title": "Amount of origins",
+ "tickAmount": 3
+ }
}
}
}
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index f3d5d7dc..2074ba5b 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -66,7 +66,8 @@ function updateTechnologies(technologies) {
const selectedTechFormatted = techSelector.getAttribute('data-selected');
/* If the technology doesn't exist, throw a warning */
- const techNamesFiltered = techNames.find(techName => techName.replaceAll(' ', '-') === selectedTechFormatted);
+ // const techNamesFiltered = techNames.find(techName => techName.replaceAll(' ', '-') === selectedTechFormatted);
+ const techNamesFiltered = techNames;
if(!techNamesFiltered) {
const errorMsg = document.createElement('p');
errorMsg.textContent = 'Technology not found, please select a different one';
@@ -77,7 +78,7 @@ function updateTechnologies(technologies) {
technologies.forEach((technology) => {
const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
const option = optionTmpl.querySelector('option');
- const formattedTech = technology.app.replaceAll(" ", "-");
+ const formattedTech = technology.app;
option.textContent = technology.app;
option.value = formattedTech;
if(formattedTech === techSelector.getAttribute('data-selected')) {
@@ -97,7 +98,7 @@ function updateGeo(geos, filters) {
geos.forEach((geo) => {
const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
const option = optionTmpl.querySelector('option');
- const formattedTech = geo.geo.replaceAll(" ", "-");
+ const formattedTech = geo.geo;
option.textContent = geo.geo;
option.value = formattedTech;
if(formattedTech === filters.geo) {
@@ -114,7 +115,7 @@ function updateRank(ranks, filters) {
ranks.forEach((rank) => {
const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
const option = optionTmpl.querySelector('option');
- const formattedTech = rank.rank.replaceAll(" ", "-");
+ const formattedTech = rank.rank;
option.textContent = rank.rank;
option.value = formattedTech;
if(formattedTech === filters.rank) {
@@ -157,7 +158,8 @@ function updateCategory(event) {
selectedTechs.forEach((technology) => {
const option = document.createElement('option');
- const formattedTech = technology.replaceAll(" ", "-");
+ //const formattedTech = technology.replaceAll(" ", "-");
+ const formattedTech = technology;
option.textContent = technology;
option.value = formattedTech;
if(formattedTech === techSelector.getAttribute('data-selected')) {
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 5d73dbe2..598315f2 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -178,13 +178,17 @@ class TechReport {
const base = 'https://dev-gw-2vzgiib6.ue.gateway.dev/v1';
- const technology = technologies.join('%2C');
+ const technology = technologies.join('%2C')
+ .replaceAll(" ", "%20");
+
+ const geo = this.filters.geo.replaceAll(" ", "%20");
+ const rank = this.filters.rank.replaceAll(" ", "%20")
let allResults = {};
technologies.forEach(tech => allResults[tech] = []);
Promise.all(apis.map(api => {
- const url = `${base}/${api.endpoint}?technology=${technology}&geo=${this.filters.geo}&rank=${this.filters.rank}`;
+ const url = `${base}/${api.endpoint}?technology=${technology}&geo=${geo}&rank=${rank}`;
return fetch(url)
.then(result => result.json())
@@ -236,6 +240,9 @@ class TechReport {
// Fetch the data for the filter dropdowns
getFilterInfo() {
+ const base = 'https://dev-gw-2vzgiib6.ue.gateway.dev/v1';
+
+ // TODO: This should be replaced by other technologies filter once fixed
fetch('https://cdn.httparchive.org/reports/cwvtech/technologies.json')
.then(result => result.json())
.then(result => Filters.updateTechnologies(result, this.filters));
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 512147fe..62ca3dec 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -346,7 +346,7 @@ class Timeseries {
});
});
- const sortedData = formattedData.sort((a, b) => new Date(b.x) - new Date(a.x));
+ const sortedData = formattedData.sort((a, b) => new Date(a.x) - new Date(b.x));
const colors = this.defaults(config)?.chart?.colors;
@@ -354,7 +354,7 @@ class Timeseries {
series.push(
{
name: value.name,
- data: formattedData,
+ data: sortedData,
color: value.color || colors[index],
lineWidth: 2,
}
From ee95c3f0cde54ffaae6a0b4b31b1b0db95388bf4 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 15:13:12 +0000
Subject: [PATCH 129/155] Add test coverage
---
server/routes.py | 2 --
server/tests/routes_test.py | 16 ++++++++++++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/server/routes.py b/server/routes.py
index cc6e42b4..03c787a5 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -85,8 +85,6 @@ def techreport(page_id):
if request.args.get("tech"):
requested_technologies = request.args.get("tech").split(",")
- if isinstance(requested_technologies, str):
- requested_technologies = [requested_technologies]
# Get the filters
requested_geo = request.args.get("geo") or "ALL"
diff --git a/server/tests/routes_test.py b/server/tests/routes_test.py
index a036d100..1df3ad19 100644
--- a/server/tests/routes_test.py
+++ b/server/tests/routes_test.py
@@ -228,3 +228,19 @@ def test_render_js_cache_control(client):
assert response.status_code == 200 and "max-age=10800" in response.headers.get(
"Cache-Control"
)
+
+
+def test_tech_report_compare(client):
+ response = client.get("/reports/techreport/comparison?tech=jQuery%2CWordPress&geo=ALL&rank=ALL")
+ assert response.status_code == 200
+
+
+def test_tech_report_drilldown(client):
+ response = client.get("/reports/techreport/drilldown?geo=ALL&rank=ALL")
+ assert response.status_code == 200
+
+
+def test_tech_report_drilldown_wordpress(client):
+ response = client.get("/reports/techreport/drilldown?tech-=WordPress&geo=ALL&rank=ALL")
+ assert response.status_code == 200
+
From 8b7b2e6d6c4cb5349071cca00cb7db534908ea43 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 15:30:12 +0000
Subject: [PATCH 130/155] Fix test url
---
tools/generate/generate_sitemap.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/generate/generate_sitemap.js b/tools/generate/generate_sitemap.js
index 1a43334c..8bb4c55d 100644
--- a/tools/generate/generate_sitemap.js
+++ b/tools/generate/generate_sitemap.js
@@ -30,6 +30,11 @@ const generate_sitemap = async () => {
for (const report of report_config._reports) {
if (report_config[report] && report_config[report].url && report_config[report].url.startsWith('http')) {
console.log(`Skipping ${report} as has external url\n`);
+ } else if (report_config[report] && report_config[report].url && report_config[report].url.startsWith('/')) {
+ const loc = `reports/${report}`;
+ const lastmod = get_lastmod_date(loc);
+ const url = report_config[report].url.slice(1);
+ urls.push({ url, lastmod });
} else {
const loc = `reports/${report}`;
const lastmod = get_lastmod_date(loc);
From 16ee6b630c680d8325c474cac467d2b2e868e151 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 15:37:05 +0000
Subject: [PATCH 131/155] Linting
---
docs/cwv_tech_report.md | 2 +-
server/csp.py | 4 ++--
server/routes.py | 4 +++-
server/tests/routes_test.py | 9 ++++++---
4 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/docs/cwv_tech_report.md b/docs/cwv_tech_report.md
index 1cabc3c3..5632703e 100644
--- a/docs/cwv_tech_report.md
+++ b/docs/cwv_tech_report.md
@@ -89,7 +89,7 @@ We use vanilla CSS, no libraries. Bootstrap is loaded as well because it's used
## Behavior
-#### Filters
+### Filters
**On a global level**, the data can be filtered by:
- App / technology
diff --git a/server/csp.py b/server/csp.py
index 2a4e2c02..97d8a1b4 100644
--- a/server/csp.py
+++ b/server/csp.py
@@ -11,7 +11,7 @@
"spdcrv.global.ssl.fastly.net",
"lux.speedcurve.com",
"'unsafe-inline'",
- "dev-gw-2vzgiib6.ue.gateway.dev"
+ "dev-gw-2vzgiib6.ue.gateway.dev",
],
"font-src": ["'self'"],
"connect-src": [
@@ -25,7 +25,7 @@
"analytics.google.com",
"*.analytics.google.com",
"stats.g.doubleclick.net",
- "dev-gw-2vzgiib6.ue.gateway.dev"
+ "dev-gw-2vzgiib6.ue.gateway.dev",
],
"img-src": ["'self'", "https:"],
"frame-src": ["'none'"],
diff --git a/server/routes.py b/server/routes.py
index 03c787a5..c738f6d5 100644
--- a/server/routes.py
+++ b/server/routes.py
@@ -81,7 +81,9 @@ def techreport(page_id):
# Add the technologies requested in the URL to the filters
# Use the default configured techs as fallback
# Use ["ALL"] if there is nothing configured
- requested_technologies = active_tech_report.get("config").get("default").get("app") or ["ALL"]
+ requested_technologies = active_tech_report.get("config").get("default").get(
+ "app"
+ ) or ["ALL"]
if request.args.get("tech"):
requested_technologies = request.args.get("tech").split(",")
diff --git a/server/tests/routes_test.py b/server/tests/routes_test.py
index 1df3ad19..a887279c 100644
--- a/server/tests/routes_test.py
+++ b/server/tests/routes_test.py
@@ -231,7 +231,9 @@ def test_render_js_cache_control(client):
def test_tech_report_compare(client):
- response = client.get("/reports/techreport/comparison?tech=jQuery%2CWordPress&geo=ALL&rank=ALL")
+ response = client.get(
+ "/reports/techreport/comparison?tech=jQuery%2CWordPress&geo=ALL&rank=ALL"
+ )
assert response.status_code == 200
@@ -241,6 +243,7 @@ def test_tech_report_drilldown(client):
def test_tech_report_drilldown_wordpress(client):
- response = client.get("/reports/techreport/drilldown?tech-=WordPress&geo=ALL&rank=ALL")
+ response = client.get(
+ "/reports/techreport/drilldown?tech-=WordPress&geo=ALL&rank=ALL"
+ )
assert response.status_code == 200
-
From 801b0f8cb491bcef4e99581c0440aaec2582d150 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 15:42:47 +0000
Subject: [PATCH 132/155] More linting fixes
---
templates/techreport/comparison.html | 4 ++--
templates/techreport/components/filter_info_header.html | 9 +++++++--
templates/techreport/components/subcategory.html | 4 ++--
templates/techreport/components/table.html | 2 +-
4 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/templates/techreport/comparison.html b/templates/techreport/comparison.html
index dd8bf632..f2a2d488 100644
--- a/templates/techreport/comparison.html
+++ b/templates/techreport/comparison.html
@@ -110,8 +110,8 @@ Page weight
Adoption
Description
-
-
+
+
{% set timeseries = tech_report_page.config.adoption_timeseries %}
{% if timeseries %}
{% include "techreport/components/timeseries.html" %}
diff --git a/templates/techreport/components/filter_info_header.html b/templates/techreport/components/filter_info_header.html
index 335212e2..4de53cd8 100644
--- a/templates/techreport/components/filter_info_header.html
+++ b/templates/techreport/components/filter_info_header.html
@@ -24,8 +24,13 @@
Client
- Mobile
- Desktop
+ {% if request.args.get('client', '') == 'desktop' %}
+ Mobile
+ Desktop
+ {% else %}
+ Mobile
+ Desktop
+ {% endif %}
diff --git a/templates/techreport/components/subcategory.html b/templates/techreport/components/subcategory.html
index f8adaa67..e1cd07b8 100644
--- a/templates/techreport/components/subcategory.html
+++ b/templates/techreport/components/subcategory.html
@@ -1,4 +1,4 @@
-{% set selectedParam = request.args.get(subcategory.param, '') or subcategory.default %}
+{% set selectedparam = request.args.get(subcategory.param, '') or subcategory.default %}
Metric
{% for option in subcategory.options %}
-
+
{{ option.label }}
{% endfor %}
diff --git a/templates/techreport/components/table.html b/templates/techreport/components/table.html
index 03a9bcfa..d0c51eb1 100644
--- a/templates/techreport/components/table.html
+++ b/templates/techreport/components/table.html
@@ -23,7 +23,7 @@
data-metric="{{column.metric}}"
class="{{ column.className }}"
>
- {{ app }}
+ {{ app }}
{% if column.hiddenSuffix %}
{{ column.hiddenSuffix }}
From e9b30f65a6fed43a2d7dc63ebac1fdc3135c6ace Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 15:47:30 +0000
Subject: [PATCH 133/155] Linting fixes
---
templates/techreport/components/subcategory.html | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/templates/techreport/components/subcategory.html b/templates/techreport/components/subcategory.html
index e1cd07b8..4a5bf3e6 100644
--- a/templates/techreport/components/subcategory.html
+++ b/templates/techreport/components/subcategory.html
@@ -10,9 +10,15 @@
data-endpoint="{{ endpoint }}"
>
{% for option in subcategory.options %}
-
+ {% if selectedparam == option.value %}
+
{{ option.label }}
+ {% else %}
+
+ {{ option.label }}
+
+ {% endif %}
{% endfor %}
From f7b1ab404364b55fe1c7a462e52af62ed5f6fb21 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 3 Jan 2024 16:02:20 +0000
Subject: [PATCH 134/155] Fix Lighthouse tests
---
tools/scripts/set_lighthouse_urls.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/scripts/set_lighthouse_urls.sh b/tools/scripts/set_lighthouse_urls.sh
index f85b7a6b..1b3a46d8 100755
--- a/tools/scripts/set_lighthouse_urls.sh
+++ b/tools/scripts/set_lighthouse_urls.sh
@@ -56,16 +56,16 @@ elif [ "${RUN_TYPE}" == "pull_request" ] && [ "${COMMIT_SHA}" != "" ]; then
git pull --quiet
git checkout main
# Then get the changes
- CHANGED_FILES=$(git diff --name-only "main...${COMMIT_SHA}" --diff-filter=d templates config/reports.json | grep -v base.html | grep -v main.html | grep -v ejs | grep -v base_ | grep -v sitemap | grep -v error.html )
+ CHANGED_FILES=$(git diff --name-only "main...${COMMIT_SHA}" --diff-filter=d templates config/reports.json | grep -v base.html | grep -v main.html | grep -v ejs | grep -v base_ | grep -v sitemap | grep -v error.html | grep -v techreport/components | grep -v techreport/templates | grep -v techreport/report | grep -v techreport/techreport)
echo "${CHANGED_FILES}"
# Then back to the pull request changes
git checkout --progress --force "${COMMIT_SHA}"
# Transform the files to http://127.0.0.1:8080 URLs
- LIGHTHOUSE_URLS=$(echo "${CHANGED_FILES}" | sed 's/templates/http:\/\/127.0.0.1:8080/g' | sed 's/index\.html//g' | sed 's/\.html//g' | sed 's/_/-/g' )
+ LIGHTHOUSE_URLS=$(echo "${CHANGED_FILES}" | sed 's/templates/http:\/\/127.0.0.1:8080/g' | sed 's/techreport/reports\/techreport/g' | sed 's/index\.html//g' | sed 's/\.html//g' | sed 's/_/-/g' )
- # If report.json or any of the report templaes were changed, then test all the reports
+ # If report.json or any of the report templates were changed, then test all the reports
# TODO - make this list dynamic
LIGHTHOUSE_URLS=$(echo "${LIGHTHOUSE_URLS}" | sed 's/config\/reports.json/http:\/\/127.0.0.1:8080\/reports\/state-of-the-web\nhttp:\/\/127.0.0.1:8080\/reports\/state-of-javascript\nhttp:\/\/127.0.0.1:8080\/reports\/state-of-images\nhttp:\/\/127.0.0.1:8080\/reports\/loading-speed\nhttp:\/\/127.0.0.1:8080\/reports\/progressive-web-apps\nhttp:\/\/127.0.0.1:8080\/reports\/accessibility\nhttp:\/\/127.0.0.1:8080\/reports\/search-engine-optimization\nhttp:\/\/127.0.0.1:8080\/reports\/page-weight\nhttp:\/\/127.0.0.1:8080\/reports\/chrome-ux-report\nhttp:\/\/127.0.0.1:8080\/reports\/project-fugu/g')
LIGHTHOUSE_URLS=$(echo "${LIGHTHOUSE_URLS}" | sed 's/http:\/\/127.0.0.1:8080\/report\/.*/http:\/\/127.0.0.1:8080\/reports\/state-of-the-web\nhttp:\/\/127.0.0.1:8080\/reports\/state-of-javascript\nhttp:\/\/127.0.0.1:8080\/reports\/state-of-images\nhttp:\/\/127.0.0.1:8080\/reports\/loading-speed\nhttp:\/\/127.0.0.1:8080\/reports\/progressive-web-apps\nhttp:\/\/127.0.0.1:8080\/reports\/accessibility\nhttp:\/\/127.0.0.1:8080\/reports\/search-engine-optimization\nhttp:\/\/127.0.0.1:8080\/reports\/page-weight\nhttp:\/\/127.0.0.1:8080\/reports\/chrome-ux-report\nhttp:\/\/127.0.0.1:8080\/reports\/project-fugu/g')
From 1cc739f8627417ef53c08a762ee56de28e33b414 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 13 Jan 2024 02:49:33 +0100
Subject: [PATCH 135/155] replace filters with new apis
---
src/js/components/filters.js | 400 ++++++++++++++++----------------
src/js/techreport/index.js | 49 ++--
src/js/techreport/timeseries.js | 2 +-
src/js/techreport/utils/data.js | 12 +
4 files changed, 248 insertions(+), 215 deletions(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 2074ba5b..3e914dad 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -1,247 +1,253 @@
-/* Add event listeners to the interactive components */
-function bindFilterListener() {
- /* Submit the form */
- const submit = document.getElementById('submit-form');
- if(submit) {
- submit.addEventListener('click', setFilter);
- }
+const { DataUtils } = require("../techreport/utils/data");
+class Filters {
+ constructor(filterData, filters) {
+ this.categories = filterData?.categories;
+ this.technologies = filterData?.technologies;
+ this.geos = filterData?.geos;
+ this.ranks = filterData?.ranks;
+
+ this.filters = filters;
- /* Add a new technology */
- const addButton = document.getElementById('add-tech');
- if(addButton) {
- addButton.addEventListener('click', addTechnologySelector);
+ this.bindFilterListener();
}
- /* Remove a technology */
- const removeButtons = Object.values(document.getElementsByClassName('remove-tech'));
- removeButtons?.forEach(removeButton => removeButton.addEventListener('click', removeTechnology));
+ /* Add event listeners to the interactive components */
+ bindFilterListener() {
+ /* Submit the form */
+ const submit = document.getElementById('submit-form');
+ if(submit) {
+ submit.addEventListener('click', this.setFilter);
+ }
- /* Choose a category */
- const categoriesSelectors = Object.values(document.getElementsByClassName('categories-selector'));
- categoriesSelectors.forEach(categorySelector => categorySelector.addEventListener('change', updateCategory));
-}
+ /* Add a new technology */
+ const addButton = document.getElementById('add-tech');
+ if(addButton) {
+ addButton.addEventListener('click', this.addTechnologySelector);
+ }
-/* Submit form */
-function setFilter(event) {
- event.preventDefault();
+ /* Remove a technology */
+ const removeButtons = Object.values(document.getElementsByClassName('remove-tech'));
+ removeButtons?.forEach(removeButton => removeButton.addEventListener('click', this.removeTechnology));
- const url = new URL(location.href);
+ /* Choose a category */
+ const categoriesSelectors = Object.values(document.getElementsByClassName('categories-selector'));
+ categoriesSelectors.forEach((categorySelector) => {
+ categorySelector.addEventListener('change', (event) => this.updateCategory(event));
+ });
+ }
- /* Get the geo and rank filter */
- const geo = document.getElementsByName('geo')[0].value;
- const rank = document.getElementsByName('rank')[0].value;
+ /* Submit form */
+ setFilter(event) {
+ event.preventDefault();
- /* Create a string of technologies */
- let technologies = [];
- document.getElementsByName('tech').forEach(technology => {
- technologies.push(technology.value);
- });
- technologies.join(",");
+ const url = new URL(location.href);
- /* Modify the URL with the tech */
- url.searchParams.delete('tech');
- url.searchParams.append('tech', technologies);
+ /* Get the geo and rank filter */
+ const geo = document.getElementsByName('geo')[0].value;
+ const rank = document.getElementsByName('rank')[0].value;
- url.searchParams.delete('geo');
- url.searchParams.append('geo', geo);
+ /* Create a string of technologies */
+ let technologies = [];
+ document.getElementsByName('tech').forEach(technology => {
+ technologies.push(technology.value);
+ });
+ technologies.join(",");
- url.searchParams.delete('rank');
- url.searchParams.append('rank', rank);
+ /* Modify the URL with the tech */
+ url.searchParams.delete('tech');
+ url.searchParams.append('tech', technologies);
+ url.searchParams.delete('geo');
+ url.searchParams.append('geo', geo);
- /* Update the url */
- location.href = url;
-}
+ url.searchParams.delete('rank');
+ url.searchParams.append('rank', rank);
-/* Update the list of technologies */
-function updateTechnologies(technologies) {
- /* Get existing tech selectors on the page */
- const allTechSelectors = document.querySelectorAll('select.tech');
- const techNames = technologies.map(element => element.app);
- /* Update the options inside all of the selectors */
- allTechSelectors.forEach(techSelector => {
- techSelector.innerHTML = '';
+ /* Update the url */
+ location.href = url;
+ }
- const selectedTechFormatted = techSelector.getAttribute('data-selected');
+ /* Update the list of technologies */
+ updateTechnologies() {
+ this.technologies = DataUtils.filterDuplicates(this.technologies, 'technology');
- /* If the technology doesn't exist, throw a warning */
- // const techNamesFiltered = techNames.find(techName => techName.replaceAll(' ', '-') === selectedTechFormatted);
- const techNamesFiltered = techNames;
- if(!techNamesFiltered) {
- const errorMsg = document.createElement('p');
- errorMsg.textContent = 'Technology not found, please select a different one';
- techSelector.before(errorMsg);
- }
+ /* Get existing tech selectors on the page */
+ const allTechSelectors = document.querySelectorAll('select.tech');
+ const techNames = this.technologies.map(element => element.app);
+
+ /* Update the options inside all of the selectors */
+ allTechSelectors.forEach(techSelector => {
+ techSelector.innerHTML = '';
- /* Add one option per technology */
- technologies.forEach((technology) => {
+ /* If the technology doesn't exist, throw a warning */
+ const techNamesFiltered = techNames;
+ if(!techNamesFiltered) {
+ const errorMsg = document.createElement('p');
+ errorMsg.textContent = 'Technology not found, please select a different one';
+ techSelector.before(errorMsg);
+ }
+
+ /* Add one option per technology */
+ this.technologies.forEach((technology) => {
+ const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
+ const option = optionTmpl.querySelector('option');
+ const formattedTech = technology.technology;
+ option.textContent = technology.technology;
+ option.value = formattedTech;
+ if(formattedTech === techSelector.getAttribute('data-selected')) {
+ option.selected = true;
+ }
+ techSelector.append(optionTmpl);
+ });
+ });
+ }
+
+ /* Update the list with geographies */
+ updateGeo() {
+ const select = document.querySelector('select#geo');
+ select.innerHTML = '';
+ this.geos.forEach((geo) => {
const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
const option = optionTmpl.querySelector('option');
- const formattedTech = technology.app;
- option.textContent = technology.app;
+ const formattedTech = geo.geo;
+ option.textContent = geo.geo;
option.value = formattedTech;
- if(formattedTech === techSelector.getAttribute('data-selected')) {
+ if(formattedTech === this.filters.geo) {
option.selected = true;
}
- techSelector.append(optionTmpl);
+ select.append(optionTmpl);
});
- });
-
- // hideRemoveButton();
-}
+ }
-/* Update the list with geographies */
-function updateGeo(geos, filters) {
- const select = document.querySelector('select#geo');
- select.innerHTML = '';
- geos.forEach((geo) => {
- const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
- const option = optionTmpl.querySelector('option');
- const formattedTech = geo.geo;
- option.textContent = geo.geo;
- option.value = formattedTech;
- if(formattedTech === filters.geo) {
- option.selected = true;
- }
- select.append(optionTmpl);
- });
-}
+ /* Update the list with ranks */
+ updateRank() {
+ const select = document.querySelector('select#rank');
+ select.innerHTML = '';
+ this.ranks.forEach((rank) => {
+ const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
+ const option = optionTmpl.querySelector('option');
+ const formattedTech = rank.rank;
+ option.textContent = rank.rank;
+ option.value = formattedTech;
+ if(formattedTech === this.filters.rank) {
+ option.selected = true;
+ }
+ select.append(optionTmpl);
+ });
+ }
-/* Update the list with ranks */
-function updateRank(ranks, filters) {
- const select = document.querySelector('select#rank');
- select.innerHTML = '';
- ranks.forEach((rank) => {
- const optionTmpl = document.getElementById('filter-option').content.cloneNode(true);
- const option = optionTmpl.querySelector('option');
- const formattedTech = rank.rank;
- option.textContent = rank.rank;
- option.value = formattedTech;
- if(formattedTech === filters.rank) {
- option.selected = true;
+ /* Update the list with categories */
+ updateCategories() {
+ const selects = document.querySelectorAll('select[name="categories"]');
+
+ if(this.categories) {
+ selects.forEach(select => {
+ select.innerHTML = '';
+
+ const all = document.createElement('option');
+ all.value = 'ALL';
+ all.innerHTML = 'ALL';
+ select.append(all);
+
+ this.categories.forEach((category) => {
+ const option = document.createElement('option');
+ option.value = category.category;
+ option.innerHTML = category.category;
+ select.append(option);
+ });
+ })
}
- select.append(optionTmpl);
- });
-}
-
-/* Update the list with categories */
-function updateCategories(categories, filters) {
- const selects = document.querySelectorAll('select[name="categories"]');
-
- if(categories) {
- selects.forEach(select => {
- select.innerHTML = '';
-
- const all = document.createElement('option');
- all.value = 'ALL';
- all.innerHTML = 'ALL';
- select.append(all);
-
- Object.keys(categories).forEach((category) => {
- const option = document.createElement('option');
- option.value = category;
- option.innerHTML = category;
- option.dataset.technologies = categories[category].join(',');
- select.append(option);
- });
- })
}
-}
-/* Set the selected category */
-function updateCategory(event) {
- const selectedOption = document.querySelector(`option[value="${event.target.value}"]`);
- const selectedTechs = selectedOption.dataset.technologies.split(",");
- const techSelector = document.getElementById(event.target.dataset.tech);
- techSelector.innerHTML = '';
-
- selectedTechs.forEach((technology) => {
- const option = document.createElement('option');
- //const formattedTech = technology.replaceAll(" ", "-");
- const formattedTech = technology;
- option.textContent = technology;
- option.value = formattedTech;
- if(formattedTech === techSelector.getAttribute('data-selected')) {
- option.selected = true;
- }
- techSelector.append(option);
- });
+ /* Set the selected category */
+ updateCategory(event) {
+ const selectedTechs = this.categories.find(category => category.category === event.target.value)?.technologies;
+ const selectedTechInfo = [];
+ selectedTechs.forEach(selectedTech => selectedTechInfo.push(this.technologies.find(tech => tech.technology === selectedTech)));
+ const techSelector = document.getElementById(event.target.dataset.tech);
+ techSelector.innerHTML = '';
-}
+ selectedTechInfo.forEach((technology) => {
+ const option = document.createElement('option');
+ const formattedTech = technology.technology;
+ option.textContent = technology.technology;
+ option.value = formattedTech;
+ if(formattedTech === techSelector.getAttribute('data-selected')) {
+ option.selected = true;
+ }
+ techSelector.append(option);
+ });
+
+ }
-/* Duplicate the technology dropdowns */
-function addTechnologySelector(event) {
- event.preventDefault();
+ /* Duplicate the technology dropdowns */
+ addTechnologySelector(event) {
+ event.preventDefault();
- const selectorTemplate = document.getElementById('tech-selector').content.cloneNode(true);
+ const selectorTemplate = document.getElementById('tech-selector').content.cloneNode(true);
- const selectElement = selectorTemplate.querySelector('select.tech');
- const labelElement = selectorTemplate.querySelector('label.tech');
- const removeButton = selectorTemplate.querySelector('.remove-tech');
+ const selectElement = selectorTemplate.querySelector('select.tech');
+ const labelElement = selectorTemplate.querySelector('label.tech');
+ const removeButton = selectorTemplate.querySelector('.remove-tech');
- const categorySelect = selectorTemplate.querySelector('select.categories-selector');
- const categoryLabel = selectorTemplate.querySelector('label[for="categories-tech-new"]');
- categorySelect.innerHTML = document.querySelector('select.categories-selector').innerHTML;
- categorySelect.addEventListener('change', updateCategory);
+ const categorySelect = selectorTemplate.querySelector('select.categories-selector');
+ const categoryLabel = selectorTemplate.querySelector('label[for="categories-tech-new"]');
+ categorySelect.innerHTML = document.querySelector('select.categories-selector').innerHTML;
+ categorySelect.addEventListener('change', this.updateCategory);
- /* Set a unique name on the new element (based on the amount of techs) */
- const techId = `tech-${document.querySelectorAll('select.tech[name="tech"]').length + 1}`;
- selectElement.setAttribute('id', techId);
- labelElement.setAttribute('for', techId);
- removeButton.dataset.tech = techId;
+ /* Set a unique name on the new element (based on the amount of techs) */
+ const techId = `tech-${document.querySelectorAll('select.tech[name="tech"]').length + 1}`;
+ selectElement.setAttribute('id', techId);
+ labelElement.setAttribute('for', techId);
+ removeButton.dataset.tech = techId;
- categorySelect.setAttribute('id', `${techId}-category`);
- categoryLabel.setAttribute('for', `${techId}-category`);
- categorySelect.setAttribute('data-tech', techId);
+ categorySelect.setAttribute('id', `${techId}-category`);
+ categoryLabel.setAttribute('for', `${techId}-category`);
+ categorySelect.setAttribute('data-tech', techId);
- removeButton.classList.remove('hidden');
+ removeButton.classList.remove('hidden');
- /* Bind functionality to the button */
- removeButton.addEventListener('click', removeTechnology);
+ /* Bind functionality to the button */
+ removeButton.addEventListener('click', this.removeTechnology);
- /* Fill in all techs and select the first one */
- selectElement.innerHTML = document.querySelector('select.tech').innerHTML;
- selectElement.getElementsByTagName('option')[0].selected = true;
+ /* Fill in all techs and select the first one */
+ selectElement.innerHTML = document.querySelector('select.tech').innerHTML;
+ selectElement.getElementsByTagName('option')[0].selected = true;
- categorySelect.innerHTML = document.querySelector('select.categories-selector')?.innerHTML;
- categorySelect.getElementsByTagName('option')[0].selected = true;
+ categorySelect.innerHTML = document.querySelector('select.categories-selector')?.innerHTML;
+ categorySelect.getElementsByTagName('option')[0].selected = true;
- /* Add the new tech to the end of the list */
- const techs = document.getElementsByClassName('tech-selector-group');
- const last = techs[techs.length - 1];
- last.after(selectorTemplate);
+ /* Add the new tech to the end of the list */
+ const techs = document.getElementsByClassName('tech-selector-group');
+ const last = techs[techs.length - 1];
+ last.after(selectorTemplate);
- /* If this is there are 2 or more technologies, the first one can be removed too */
- if(techs.length === 2) {
- techs[0].getElementsByClassName('remove-tech')[0].classList.remove('hidden');
+ /* If this is there are 2 or more technologies, the first one can be removed too */
+ if(techs.length === 2) {
+ techs[0].getElementsByClassName('remove-tech')[0].classList.remove('hidden');
+ }
}
-}
-/* Remove the chosen technology option */
-function removeTechnology(event) {
- event.preventDefault();
+ /* Remove the chosen technology option */
+ removeTechnology(event) {
+ event.preventDefault();
- /* Remove the tech selector group from the DOM */
- const tech = document.querySelector(`.tech-selector-group[data-tech="${event.target.dataset.tech}"]`);
- tech.remove();
+ /* Remove the tech selector group from the DOM */
+ const tech = document.querySelector(`.tech-selector-group[data-tech="${event.target.dataset.tech}"]`);
+ tech.remove();
- /* Don't show any remove buttons if there is only one element left */
- hideRemoveButton();
-}
+ /* Don't show any remove buttons if there is only one element left */
+ this.hideRemoveButton();
+ }
-/* Hide possibility to remove tech when only one is selected */
-function hideRemoveButton() {
- const techs = document.getElementsByClassName('tech-selector-group');
- if(techs.length === 1) {
- techs[0].getElementsByClassName('remove-tech')[0].classList.add('hidden');
+ /* Hide possibility to remove tech when only one is selected */
+ hideRemoveButton() {
+ const techs = document.getElementsByClassName('tech-selector-group');
+ if(techs.length === 1) {
+ techs[0].getElementsByClassName('remove-tech')[0].classList.add('hidden');
+ }
}
}
-export const Filters = {
- bindFilterListener,
- updateTechnologies,
- updateGeo,
- updateRank,
- updateCategories,
-}
+export default Filters;
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 598315f2..3e3d110a 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -1,5 +1,5 @@
+import Filters from '../components/filters';
const { DrilldownHeader } = require("../components/drilldownHeader");
-const { Filters } = require("../components/filters");
const { DataUtils } = require("./utils/data");
const { UIUtils } = require("./utils/ui");
@@ -23,7 +23,6 @@ class TechReport {
// Load the page
this.initializePage();
- // this.getFilterInfo();
this.getAllMetricData();
this.bindSettingsListeners();
}
@@ -51,8 +50,6 @@ class TechReport {
// TODO
initializeReport() {
- Filters.bindFilterListener();
-
// TODO: Move to function
const showIndicators = localStorage.getItem('showIndicators');
document.querySelector('main').dataset.showIndicators = showIndicators;
@@ -240,24 +237,42 @@ class TechReport {
// Fetch the data for the filter dropdowns
getFilterInfo() {
+ const filterData = {};
const base = 'https://dev-gw-2vzgiib6.ue.gateway.dev/v1';
- // TODO: This should be replaced by other technologies filter once fixed
- fetch('https://cdn.httparchive.org/reports/cwvtech/technologies.json')
- .then(result => result.json())
- .then(result => Filters.updateTechnologies(result, this.filters));
+ const filterApis = ['categories', 'technologies', 'ranks', 'geos'];
+
+ Promise.all(filterApis.map(api => {
+ const url = `${base}/${api}`;
+
+ return fetch(url)
+ .then(result => result.json())
+ .then(result => filterData[api] = result)
+ .catch(error => console.log('Something went wrong', error));
+ })).then(() => {
+ const FilterComponent = new Filters(filterData, this.filters);
+
+ FilterComponent.updateCategories();
+ FilterComponent.updateTechnologies();
+ FilterComponent.updateRank();
+ FilterComponent.updateGeo();
+ });
+
+ // fetch('https://cdn.httparchive.org/reports/cwvtech/technologies.json')
+ // .then(result => result.json())
+ // .then(result => FilterComponent.updateTechnologies(result, this.filters));
- fetch('https://cdn.httparchive.org/reports/cwvtech/geos.json')
- .then(result => result.json())
- .then(result => Filters.updateGeo(result, this.filters));
+ // fetch(`${base}/ranks`)
+ // .then(result => result.json())
+ // .then(result => FilterComponent.updateRank(result, this.filters));
- fetch('https://cdn.httparchive.org/reports/cwvtech/ranks.json')
- .then(result => result.json())
- .then(result => Filters.updateRank(result, this.filters));
+ // fetch(`${base}/geos`)
+ // .then(result => result.json())
+ // .then(result => FilterComponent.updateGeo(result, this.filters));
- fetch('https://cdn.httparchive.org/reports/cwvtech/categories.json')
- .then(result => result.json())
- .then(result => Filters.updateCategories(result, this.filters));
+ // fetch(`${base}/categories`)
+ // .then(result => result.json())
+ // .then(result => FilterComponent.updateCategories(result));
}
// Update the page components
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 62ca3dec..3e61dd36 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -123,7 +123,7 @@ class Timeseries {
container.innerHTML = '';
/* Update the date to the most recent timestamp in the dataset */
- viz.querySelector('[data-slot="timestamp"]').innerHTML = sorted?.[0].date;
+ viz.querySelector('[data-slot="timestamp"]').innerHTML = sorted?.[0]?.date;
/* For each of the breakdowns, add a component with the latest data */
config.series.values.forEach(breakdown => {
diff --git a/src/js/techreport/utils/data.js b/src/js/techreport/utils/data.js
index 0dfe404b..e28a2ee4 100644
--- a/src/js/techreport/utils/data.js
+++ b/src/js/techreport/utils/data.js
@@ -74,9 +74,21 @@ const parsePageWeightData = (metric, date) => {
});
}
+const filterDuplicates = (array, key) => {
+ const filtered = [];
+ array.forEach((row) => {
+ const matchingKeys = filtered.filter(filteredRow => filteredRow[key] === row[key]);
+ if(matchingKeys.length < 1) {
+ filtered.push(row);
+ }
+ });
+ return filtered;
+};
+
export const DataUtils = {
parseVitalsData,
parseLighthouseData,
parseAdoptionData,
parsePageWeightData,
+ filterDuplicates
};
From 4a4eb25c90e62a3008a7c8ab10e7ade1c5ca2e93 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 13 Jan 2024 15:40:12 +0100
Subject: [PATCH 136/155] update highcharts colors
---
static/css/techreport/techreport.css | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index a884e925..b8d93e72 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -8,6 +8,8 @@
--color-blue-dark: #3a7098;
--color-blue-100: #eff7ff;
+ --color-gray-medium: #5c5c5d;
+
/* Colors based on function */
--color-link: var(--color-blue-dark);
--color-text: #444;
@@ -45,6 +47,10 @@
--color-card-background: #111111;
--color-card-border: #000;
--color-page-background: #292828;
+
+ /* Graph colors */
+ --graph-color-labels: #A6BBBE;
+ --graph-color-line: var(--color-gray-medium);
}
/* ------------------------- */
@@ -1075,6 +1081,11 @@ select {
/* -------------------- */
/* Highcharts */
+.highcharts-background,
+.highcharts-point {
+ fill: var(--color-card-background) !important;
+}
+
.highcharts-title {
font-weight: normal !important;
fill: var(--color-text) !important;
@@ -1082,6 +1093,10 @@ select {
font-size: 0.875rem !important;
}
+.highcharts-grid-line {
+ stroke: var(--graph-color-line) !important;
+}
+
svg.highcharts-root text {
font-weight: normal !important;
fill: var(--color-text) !important;
@@ -1089,7 +1104,7 @@ svg.highcharts-root text {
}
svg.highcharts-root .highcharts-axis-line {
- stroke: var(--graph-color-line);
+ stroke: var(--graph-color-line) !important;
}
svg.highcharts-root .highcharts-axis-labels text {
From 9045412d7814ed7edc596e98b06fa15805b8d66f Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sat, 13 Jan 2024 18:24:17 +0100
Subject: [PATCH 137/155] modify variables for dark mode
---
static/css/techreport/techreport.css | 45 +++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 4 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index b8d93e72..6b0910d0 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -7,6 +7,7 @@
--color-teal-darker: #1c4750;
--color-blue-dark: #3a7098;
--color-blue-100: #eff7ff;
+ --color-blue-light: #E1F1FF;
--color-gray-medium: #5c5c5d;
@@ -18,6 +19,12 @@
--color-card-background: #fff;
--color-card-border: #cdd4d6;
--color-page-background: #f4f4f4;
+ --color-checkbox: var(--color-blue-dark);
+ --color-checkbox-selected: var(--color-blue-dark);
+ --color-checkbox-button-selected: var(--color-blue-light);
+ --color-checkbox-button-label: var(--color-text);
+ --color-checkbox-button-label-selected: var(--color-text);
+ --color-theme-toggle-background: #f4f4f4;
/* Font sizes */
--font-size-medium: 1.75rem;
@@ -47,6 +54,10 @@
--color-card-background: #111111;
--color-card-border: #000;
--color-page-background: #292828;
+ --color-checkbox-button-label-selected: #292828;
+ --color-checkbox: #fff;
+ --color-checkbox-selected: #292828;
+ --color-theme-toggle-background: transparent;
/* Graph colors */
--graph-color-labels: #A6BBBE;
@@ -57,6 +68,19 @@
/* ---- Building blocks ---- */
/* ------------------------- */
+/* Page header and footer */
+body > :is(header, footer) {
+ background-color: var(--color-card-background);
+}
+
+/* Links */
+main :is(
+ a,
+ p a
+) {
+ color: var(--color-link);
+}
+
/* CTA */
.cta-link {
background-color: var(--color-teal-dark);
@@ -558,6 +582,12 @@ select {
}
/* Table */
+.show-table {
+ background-color: transparent;
+ color: var(--color-text-lighter);
+ border-color: var(--color-text-lighter);
+}
+
.table-ui-wrapper {
overflow-x: scroll;
}
@@ -1191,6 +1221,7 @@ path.highcharts-tick {
.check-wrapper label {
margin-bottom: 0;
padding-left: 1.5rem;
+ color: var(--color-checkbox-button-label);
}
.check-wrapper input {
@@ -1217,16 +1248,21 @@ path.highcharts-tick {
position: absolute;
left: 1rem;
top: 0.75rem;
- border: 1px solid var(--color-blue-dark);
+ border: 1px solid var(--color-checkbox);
}
.check-wrapper:has(input:checked) {
- background-color: #E1F1FF;
+ background-color: var(--color-checkbox-button-selected);
}
.check-wrapper:has(input:checked):before {
- background-color: var(--color-blue-dark);
- box-shadow: 0 0 0 1.5px #E1F1FF inset;
+ background-color: var(--color-checkbox-selected);
+ border-color: var(--color-checkbox-selected);
+ box-shadow: 0 0 0 1.5px var(--color-checkbox-button-selected) inset;
+}
+
+.check-wrapper:has(input:checked) label {
+ color: var(--color-checkbox-button-label-selected);
}
.check-descr {
@@ -1239,6 +1275,7 @@ path.highcharts-tick {
}
.theme-switcher {
+ background-color: var(--color-theme-toggle-background);
border: 1px solid var(--color-text-lighter);
margin-top: 1rem;
margin-bottom: 0.25rem;
From 2a334a33b9287188f9aeef0aee445aa2ac652343 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 14 Jan 2024 20:18:28 +0100
Subject: [PATCH 138/155] update page background
---
static/css/techreport/techreport.css | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 6b0910d0..15d71ce8 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -25,6 +25,8 @@
--color-checkbox-button-label: var(--color-text);
--color-checkbox-button-label-selected: var(--color-text);
--color-theme-toggle-background: #f4f4f4;
+ --color-bg-gradient: var(--color-teal-faded);
+ --color-page-border: var(--color-teal-medium);
/* Font sizes */
--font-size-medium: 1.75rem;
@@ -58,6 +60,8 @@
--color-checkbox: #fff;
--color-checkbox-selected: #292828;
--color-theme-toggle-background: transparent;
+ --color-bg-gradient: #111111;
+ --color-page-border: #000;
/* Graph colors */
--graph-color-labels: #A6BBBE;
@@ -509,7 +513,7 @@ select {
padding: 0.5rem 0;
background-color: var(--color-page-background);
z-index: 3;
- border-bottom: 1px solid #6A797C;
+ border-bottom: 1px solid var(--color-page-border);
}
.results-header :is(label, select) {
@@ -995,7 +999,7 @@ select {
.report-content {
- background-image: linear-gradient(#C0CED0, rgba(238,238,238,0));
+ background-image: linear-gradient(var(--color-bg-gradient), rgba(238,238,238,0));
background-size: 100% 50rem;
background-repeat: no-repeat;
padding-top: 3rem;
@@ -1014,7 +1018,7 @@ select {
background-image: none;
padding-top: 0;
background-color: #fff;
- border-bottom: 1px solid #6A797C;
+ border-bottom: 1px solid var(--color-page-border);
}
.report-content > .error {
From c2ab799f71076f4c9a24d28523a925cefce80092 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Sun, 14 Jan 2024 21:30:54 +0100
Subject: [PATCH 139/155] add dropdown dark mode
---
static/css/techreport/techreport.css | 39 ++++++++++++++++++----------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 15d71ce8..5b12809d 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -15,6 +15,7 @@
--color-link: var(--color-blue-dark);
--color-text: #444;
--color-text-lighter: #6E7576;
+ --color-text-darker: #1E1E1E;
--color-text-inverted: #fff;
--color-card-background: #fff;
--color-card-border: #cdd4d6;
@@ -52,6 +53,7 @@
--color-link: var(--color-teal-faded);
--color-text: #fff;
--color-text-lighter: #fff;
+ --color-text-darker: #fff;
--color-text-inverted: #000;
--color-card-background: #111111;
--color-card-border: #000;
@@ -304,7 +306,7 @@ main :is(
font-size: 1rem;
line-height: 100%;
- color: #1E1E1E;
+ color: var(--color-text-darker);
border-radius: 3px;
outline-offset: 2px;
}
@@ -331,16 +333,16 @@ main :is(
top: 50%;
top: calc(50% - 0.25rem);
- border-bottom: 1.5px solid #1E1E1E;
- border-left: 1.5px solid #1E1E1E;
+ border-bottom: 1.5px solid var(--color-text-darker);
+ border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
transform: rotate(-45deg);
}
.select-label:has(select:is(:focus-visible, :hover)):before {
- background-color: #1E1E1E;
- border-left: 1px solid #1E1E1E;
+ background-color: var(--color-text-darker);
+ border-left: 1px solid var(--color-text-darker);
}
.select-label:has(select:is(:focus-visible, :hover)):after {
@@ -368,6 +370,7 @@ main :is(
margin-bottom: 0;
border: 1px solid #959494;
+ color: var(--color-text-lighter);
-webkit-appearance: none;
-moz-appearance: none;
@@ -425,8 +428,8 @@ main :is(
top: 50%;
top: calc(50% - 0.25rem);
- border-bottom: 1.5px solid #1E1E1E;
- border-left: 1.5px solid #1E1E1E;
+ border-bottom: 1.5px solid var(--color-text-darker);
+ border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
transform: rotate(-45deg);
@@ -439,8 +442,8 @@ main :is(
}
.tech-input-wrapper:has(select:is(:focus-visible, :hover)):before {
- background-color: #1E1E1E;
- border-left: 1px solid #1E1E1E;
+ background-color: var(--color-text-darker);
+ border-left: 1px solid var(--color-text-darker);
}
.tech-input-wrapper:has(select:is(:focus-visible, :hover)):after {
@@ -486,6 +489,7 @@ main :is(
appearance: none;
background-color: transparent;
+ color: var(--color-text-lighter);
border: none;
font-size: 0.825rem;
@@ -672,8 +676,8 @@ select {
top: 50%;
top: calc(50% - 0.25rem);
- border-bottom: 1.5px solid #1E1E1E;
- border-left: 1.5px solid #1E1E1E;
+ border-bottom: 1.5px solid var(--color-text-darker);
+ border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
transform: rotate(-45deg);
@@ -686,8 +690,8 @@ select {
display: block;
height: 100%;
width: 2.5rem;
- background-color: #1E1E1E;
- border-left: 1px solid #1E1E1E;
+ background-color: var(--color-text-darker);
+ border-left: 1px solid var(--color-text-darker);
position: absolute;
right: 0;
top: 0;
@@ -1172,6 +1176,15 @@ path.highcharts-tick {
font-weight: normal;
}
+.highcharts-button:not(.highcharts-button-hover) rect {
+ fill: transparent;
+}
+
+.highcharts-button:not(.highcharts-button-hover) path {
+ fill: var(--color-text-lighter);
+ stroke: var(--color-text-lighter);
+}
+
/* ------------------------ */
/* ----- Small charts ----- */
/* ------------------------ */
From 2a02f0f8df70dfd465986943fd07c133bf5e61e0 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Mon, 15 Jan 2024 01:36:27 +0100
Subject: [PATCH 140/155] edit highcharts tooltip color for darkmode
---
static/css/techreport/techreport.css | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 5b12809d..63d185bb 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -28,6 +28,8 @@
--color-theme-toggle-background: #f4f4f4;
--color-bg-gradient: var(--color-teal-faded);
--color-page-border: var(--color-teal-medium);
+ --color-tooltip-background: var(--color-card-background);
+ --color-tooltip-border: var(--color-card-border);
/* Font sizes */
--font-size-medium: 1.75rem;
@@ -64,6 +66,7 @@
--color-theme-toggle-background: transparent;
--color-bg-gradient: #111111;
--color-page-border: #000;
+ --color-tooltip-border: var(--color-page-background);
/* Graph colors */
--graph-color-labels: #A6BBBE;
@@ -1185,6 +1188,16 @@ path.highcharts-tick {
stroke: var(--color-text-lighter);
}
+.highcharts-tooltip {
+ filter: none;
+}
+
+.highcharts-tooltip path {
+ fill: var(--color-tooltip-background);
+ stroke: var(--color-tooltip-border);
+ stroke-width: 1px;
+}
+
/* ------------------------ */
/* ----- Small charts ----- */
/* ------------------------ */
From 7a2a0bab61a1a49056b948040fcfb53451c67baf Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 17 Jan 2024 15:16:23 +0100
Subject: [PATCH 141/155] code cleanup & bugfix
---
src/js/techreport/index.js | 19 ++---------
src/js/techreport/section.js | 6 ++--
src/js/techreport/summaryCards.js | 12 +++++--
src/js/techreport/utils/data.js | 8 ++++-
src/js/techreport/utils/ui.js | 8 -----
static/css/techreport/techreport.css | 32 +++++++++++++++++--
.../techreport/components/summary_card.html | 28 ++++++++--------
7 files changed, 68 insertions(+), 45 deletions(-)
diff --git a/src/js/techreport/index.js b/src/js/techreport/index.js
index 3e3d110a..29f0108c 100644
--- a/src/js/techreport/index.js
+++ b/src/js/techreport/index.js
@@ -18,7 +18,7 @@ class TechReport {
config: {
...page.config,
labels: labels,
- }
+ },
};
// Load the page
@@ -71,6 +71,7 @@ class TechReport {
const reportSection = new Section(
section.id,
this.page.config,
+ this.config,
this.filters,
this.allData
);
@@ -257,22 +258,6 @@ class TechReport {
FilterComponent.updateRank();
FilterComponent.updateGeo();
});
-
- // fetch('https://cdn.httparchive.org/reports/cwvtech/technologies.json')
- // .then(result => result.json())
- // .then(result => FilterComponent.updateTechnologies(result, this.filters));
-
- // fetch(`${base}/ranks`)
- // .then(result => result.json())
- // .then(result => FilterComponent.updateRank(result, this.filters));
-
- // fetch(`${base}/geos`)
- // .then(result => result.json())
- // .then(result => FilterComponent.updateGeo(result, this.filters));
-
- // fetch(`${base}/categories`)
- // .then(result => result.json())
- // .then(result => FilterComponent.updateCategories(result));
}
// Update the page components
diff --git a/src/js/techreport/section.js b/src/js/techreport/section.js
index dc5a2619..4b774d76 100644
--- a/src/js/techreport/section.js
+++ b/src/js/techreport/section.js
@@ -2,10 +2,11 @@ import SummaryCard from "./summaryCards";
import TableLinked from "./tableLinked";
class Section {
- constructor(id, config, filters, data) {
+ constructor(id, pageConfig, globalConfig, filters, data) {
this.id = id;
this.data = data;
- this.pageConfig = config;
+ this.pageConfig = pageConfig;
+ this.config = globalConfig;
this.pageFilters = filters;
this.components = {};
@@ -49,6 +50,7 @@ class Section {
this.components[component.dataset.id] = new SummaryCard(
component.dataset.id,
this.pageConfig,
+ this.config,
this.pageFilters,
this.data
);
diff --git a/src/js/techreport/summaryCards.js b/src/js/techreport/summaryCards.js
index 20490e7c..34caf911 100644
--- a/src/js/techreport/summaryCards.js
+++ b/src/js/techreport/summaryCards.js
@@ -2,11 +2,14 @@
* Show static values for given metrics.
*/
+import { DataUtils } from "./utils/data";
+
class SummaryCard {
- constructor(id, config, filters, data) {
+ constructor(id, pageConfig, config, filters, data) {
this.data = data;
this.id = id;
- this.pageConfig = config;
+ this.pageConfig = pageConfig;
+ this.config = config;
this.pageFilters = filters;
this.client = 'mobile'; //TODO: get default from config
}
@@ -52,7 +55,12 @@ class SummaryCard {
const progress = card.querySelectorAll('.lighthouse-progress');
progress.forEach(circle => {
+ const scoreCategory = DataUtils.getLighthouseScoreCategories(latestValue, this.config.lighthouse_brackets);
+ const scoreCategoryName = scoreCategory?.name;
circle.setAttribute('style', `--offset: ${100 - latestValue};`);
+ const chart = card.querySelector('svg.progress-chart');
+ console.log('chart', chart);
+ chart.classList.add(scoreCategoryName);
});
}
diff --git a/src/js/techreport/utils/data.js b/src/js/techreport/utils/data.js
index e28a2ee4..d3f200e5 100644
--- a/src/js/techreport/utils/data.js
+++ b/src/js/techreport/utils/data.js
@@ -85,10 +85,16 @@ const filterDuplicates = (array, key) => {
return filtered;
};
+const getLighthouseScoreCategories = (score, brackets) => {
+ return brackets.find(bracket => bracket.min <= score && bracket.max >= score);
+
+}
+
export const DataUtils = {
parseVitalsData,
parseLighthouseData,
parseAdoptionData,
parsePageWeightData,
- filterDuplicates
+ filterDuplicates,
+ getLighthouseScoreCategories,
};
diff --git a/src/js/techreport/utils/ui.js b/src/js/techreport/utils/ui.js
index e493d089..77d1b938 100644
--- a/src/js/techreport/utils/ui.js
+++ b/src/js/techreport/utils/ui.js
@@ -24,14 +24,6 @@ const updateReportComponents = (sections, data, allData, page, labels) => {
section.data = data;
section.updateSection();
});
-
- const allDataComponents = document.querySelectorAll('[data-scope="all-data"]');
- allDataComponents.forEach((component) => {
- component.allData = allData;
- component.page = page;
- component.labels = labels;
- component.setAttribute('loaded', true);
- });
}
export const UIUtils = {
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 63d185bb..210ea00f 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -14,7 +14,7 @@
/* Colors based on function */
--color-link: var(--color-blue-dark);
--color-text: #444;
- --color-text-lighter: #6E7576;
+ --color-text-lighter: #5f6768;
--color-text-darker: #1E1E1E;
--color-text-inverted: #fff;
--color-card-background: #fff;
@@ -1059,7 +1059,6 @@ select {
[data-component="summaryCard"] {
position: relative;
- padding-bottom: 3rem;
}
[data-component="summaryCard"] > p.meta {
@@ -1205,6 +1204,23 @@ path.highcharts-tick {
transform: rotate(-90deg);
}
+.summary-value:has(.progress-chart) {
+ position: relative;
+ margin-top: 1rem;
+}
+
+.summary-value:has(.progress-chart) > p {
+ text-align: center;
+ width: 50%;
+ height: 100%;
+ height: calc(100% - 0.5rem);
+ position: absolute;
+ top: 0;
+ padding-top: 25%;
+ padding-top: calc(25% - 0.55rem);
+ line-height: 100%;
+}
+
.lighthouse-progress {
stroke-dashoffset: var(--offset);
transform-origin: center;
@@ -1218,6 +1234,18 @@ path.highcharts-tick {
transform: rotate(1deg);
}
+.progress-chart.poor .lighthouse-progress:not(.border-1, .border-2) {
+ stroke: #FF3333;
+}
+
+.progress-chart.good .lighthouse-progress:not(.border-1, .border-2) {
+ stroke: #18A975;
+}
+
+.progress-chart.improvement .lighthouse-progress:not(.border-1, .border-2) {
+ stroke: #C7870B;
+}
+
/* ----------------------- */
/* ---- Accessibility ---- */
/* ----------------------- */
diff --git a/templates/techreport/components/summary_card.html b/templates/techreport/components/summary_card.html
index 0a9b0a36..f14af454 100644
--- a/templates/techreport/components/summary_card.html
+++ b/templates/techreport/components/summary_card.html
@@ -15,19 +15,21 @@
{{ summary.label }}
-
- --
- {{ summary.suffix or "" }}
-
- {% if section_prefix == "lighthouse" %}
-
-
-
-
-
-
-
- {% endif %}
+
+
+ --
+ {{ summary.suffix or "" }}
+
+ {% if section_prefix == "lighthouse" %}
+
+
+
+
+
+
+
+ {% endif %}
+
{{ summary.description }}
From 4a981b266dd0f79238116356b8e7440c947e3286 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 13 Mar 2024 13:50:22 +0100
Subject: [PATCH 142/155] beta banner and feedback message
---
static/css/techreport/general.css | 12 ++++++++++++
templates/techreport/techreport.html | 18 ++++++++++++------
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 225974dc..030406cd 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -87,3 +87,15 @@ p {
margin-right: auto;
}
+.feedback {
+ background-image: linear-gradient(
+ var(--color-page-background),
+ var(--color-card-background)
+ );
+ padding: 4rem 0;
+ margin-top: -4rem;
+}
+
+.feedback h2 {
+ margin-top: 0;
+}
diff --git a/templates/techreport/techreport.html b/templates/techreport/techreport.html
index 9ab9b5ab..181ad873 100644
--- a/templates/techreport/techreport.html
+++ b/templates/techreport/techreport.html
@@ -11,12 +11,12 @@
{% endblock %}
{% block report_navigation %}
-
+
{% set filters = "" %}
@@ -60,6 +60,15 @@
{% block main %}
{% block section %}{% endblock %}
+
+
+
Feedback?
+
+ We are still working on this dashboard. The design and functionality can still change, and we're working on accessibility improvements and bugfixes.
+ What you're seeing here is a snapshot of our latest GitHub commit, and are open for feedback .
+
+
+
@@ -78,11 +87,8 @@
Accessibility
-
-
{% endblock %}
-
{% block scripts %}
{{ super() }}
From d46348916bfa67fb3f1a52c0c5405deabe7f49cb Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Mar 2024 14:07:09 +0100
Subject: [PATCH 143/155] Update src/js/components/filters.js
Co-authored-by: Rick Viscomi
---
src/js/components/filters.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/js/components/filters.js b/src/js/components/filters.js
index 3e914dad..b0c85a5d 100644
--- a/src/js/components/filters.js
+++ b/src/js/components/filters.js
@@ -51,7 +51,7 @@ class Filters {
document.getElementsByName('tech').forEach(technology => {
technologies.push(technology.value);
});
- technologies.join(",");
+ technologies = technologies.join(",");
/* Modify the URL with the tech */
url.searchParams.delete('tech');
From a052f933867e4ca5655e477315e7f9084324c471 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Mar 2024 14:07:18 +0100
Subject: [PATCH 144/155] Update server/tests/routes_test.py
Co-authored-by: Rick Viscomi
---
server/tests/routes_test.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/tests/routes_test.py b/server/tests/routes_test.py
index a887279c..4e72fb6b 100644
--- a/server/tests/routes_test.py
+++ b/server/tests/routes_test.py
@@ -244,6 +244,6 @@ def test_tech_report_drilldown(client):
def test_tech_report_drilldown_wordpress(client):
response = client.get(
- "/reports/techreport/drilldown?tech-=WordPress&geo=ALL&rank=ALL"
+ "/reports/techreport/drilldown?tech=WordPress&geo=ALL&rank=ALL"
)
assert response.status_code == 200
From 0398db304497aaaaa9d207a4b8cd9c9fe9e8d31c Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 27 Mar 2024 14:13:17 +0100
Subject: [PATCH 145/155] clean up code & improve 200% font-size
---
config/reports.json | 2 +-
src/js/techreport/table.js | 3 +-
src/js/techreport/tableLinked.js | 11 -----
src/js/techreport/timeseries.js | 2 +-
static/css/techreport/general.css | 3 ++
static/css/techreport/techreport.css | 16 +++++++
.../techreport/components/subcategory.html | 44 ++++++++++---------
templates/techreport/landing.html | 6 ---
8 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/config/reports.json b/config/reports.json
index b0e0c78b..76783346 100644
--- a/config/reports.json
+++ b/config/reports.json
@@ -1381,7 +1381,7 @@
}
},
"cwv-tech-new": {
- "name": "New Core Web Vitals Technology Report",
+ "name": "BETA: Core Web Vitals Technology Report",
"summary": "The Core Web Vitals Technology Report is a dashboard combining the powers of real-user experiences in the [Chrome User Experience Report (CrUX)](https://developers.google.com/web/tools/chrome-user-experience-report/) dataset with web technology detections available in HTTP Archive, to allow analysis of the way websites are both built and experienced.",
"url": "/reports/techreport/landing",
"metrics": [],
diff --git a/src/js/techreport/table.js b/src/js/techreport/table.js
index 764b5072..7d0d0b50 100644
--- a/src/js/techreport/table.js
+++ b/src/js/techreport/table.js
@@ -13,7 +13,6 @@ function formatData(tableConfig, data) {
// Loop through all of the dates
// Populate array of data rows with it
- const dates = Object.values(data)[0];
const client = component.dataset.client || 'mobile';
let _dates = [];
@@ -128,7 +127,7 @@ function updateTable(id, config, apps, data) {
text = `${value}${suffix}`;
} else {
text = 'N/A';
- className += ' no-data'
+ className += ' no-data';
}
// Wrap the text in a span for styling
diff --git a/src/js/techreport/tableLinked.js b/src/js/techreport/tableLinked.js
index 2cfc041c..cfbd1d2f 100644
--- a/src/js/techreport/tableLinked.js
+++ b/src/js/techreport/tableLinked.js
@@ -9,17 +9,6 @@ class TableLinked {
this.updateContent();
}
- // Format the data to fit in the table structure
- formatData(tableConfig, data) {
- const { apps, id, config } = tableConfig;
-
- const rows = [];
-
- apps.forEach(app => {
-
- });
- }
-
// Update content in the table
updateContent() {
// Select a table based on the passed in id
diff --git a/src/js/techreport/timeseries.js b/src/js/techreport/timeseries.js
index 3e61dd36..de090032 100644
--- a/src/js/techreport/timeseries.js
+++ b/src/js/techreport/timeseries.js
@@ -161,7 +161,7 @@ class Timeseries {
const id = this.id;
const pageFilters = this.pageFilters;
- const component = document.querySelector(`[data-id="${this.id}"]`);
+ const component = document.querySelector(`[data-id="${id}"]`);
const container = component.querySelector('.breakdown-list');
/* Get the currently selected subcategory based on the URL */
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 030406cd..22995614 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -6,8 +6,11 @@
body {
background-color: var(--color-page-background);
+ font-size: 1rem;
+
}
+
main {
color: var(--color-text);
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 210ea00f..ac2631b2 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -636,8 +636,17 @@ select {
padding-right: 0;
}
+.subcategory-selector-wrapper .position-wrapper {
+ display: flex;
+ align-items: center;
+ column-gap: 0.25rem;
+}
+
.subcategory-selector-wrapper label {
color: var(--color-text-lighter);
+ display: unset;
+ padding-bottom: 0;
+ margin-bottom: 0;
}
.subcategory-selector-wrapper select {
@@ -655,6 +664,7 @@ select {
z-index: 2;
position: relative;
+ display: unset;
}
.subcategory-selector-wrapper:has(select:focus) select {
@@ -1021,6 +1031,10 @@ select {
margin-bottom: 6rem;
}
+.report-section > .card {
+ margin-top: 2rem;
+}
+
.report-content:has(> .error) {
background-image: none;
padding-top: 0;
@@ -1082,6 +1096,8 @@ select {
display: flex;
column-gap: 3rem;
margin-top: 1rem;
+ margin-bottom: 2rem;
+ flex-wrap: wrap;
}
.data-summary .breakdown-item {
diff --git a/templates/techreport/components/subcategory.html b/templates/techreport/components/subcategory.html
index 4a5bf3e6..61c70f69 100644
--- a/templates/techreport/components/subcategory.html
+++ b/templates/techreport/components/subcategory.html
@@ -1,24 +1,26 @@
{% set selectedparam = request.args.get(subcategory.param, '') or subcategory.default %}
-
Metric
-
- {% for option in subcategory.options %}
- {% if selectedparam == option.value %}
-
- {{ option.label }}
-
- {% else %}
-
- {{ option.label }}
-
- {% endif %}
- {% endfor %}
-
+
+ Metric
+
+ {% for option in subcategory.options %}
+ {% if selectedparam == option.value %}
+
+ {{ option.label }}
+
+ {% else %}
+
+ {{ option.label }}
+
+ {% endif %}
+ {% endfor %}
+
+
diff --git a/templates/techreport/landing.html b/templates/techreport/landing.html
index 48585229..88659812 100644
--- a/templates/techreport/landing.html
+++ b/templates/techreport/landing.html
@@ -31,11 +31,5 @@
-
-
-
Explore
-
Placeholder
-
-
{% endblock %}
From 9d5a2e067015ecba8fd9f388bb1f21727dc2c8a9 Mon Sep 17 00:00:00 2001
From: Rick Viscomi
Date: Fri, 5 Apr 2024 11:58:58 -0400
Subject: [PATCH 146/155] fix config
---
config/last_updated.json | 39 ++++++++++++++++++++++++-----------
tools/generate/generate_js.js | 2 +-
2 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/config/last_updated.json b/config/last_updated.json
index 65a646e7..07836d7e 100644
--- a/config/last_updated.json
+++ b/config/last_updated.json
@@ -41,8 +41,8 @@
},
"/static/css/techreport/general.css": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "53dd766b1d280387b36a2c3ead47e68c"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "28eb032e3482a2447241be1e712ed74d"
},
"/static/css/techreport/landing.css": {
"date_published": "2023-10-09T00:00:00.000Z",
@@ -51,8 +51,8 @@
},
"/static/css/techreport/techreport.css": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "82ad10c0e3231f9a2e44f54007b1bda7"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "44544a77ae69a65af90cb8b147bd0263"
},
"/static/js/accessibility.js": {
"date_published": "2023-10-09T00:00:00.000Z",
@@ -74,6 +74,11 @@
"date_modified": "2024-01-28T00:00:00.000Z",
"hash": "bf113a2ddbc983f18f069cd5957814d9"
},
+ "/static/js/exporting.js.map": {
+ "date_published": "2024-04-05T00:00:00.000Z",
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "90a638c281c291abf8acb7531024d3a5"
+ },
"/static/js/faq.js": {
"date_published": "2018-05-08T00:00:00.000Z",
"date_modified": "2024-03-14T00:00:00.000Z",
@@ -84,6 +89,11 @@
"date_modified": "2024-01-28T00:00:00.000Z",
"hash": "1d792d50f4462089ca7b3453f8426d6c"
},
+ "/static/js/highcharts-more.js.map": {
+ "date_published": "2024-04-05T00:00:00.000Z",
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "8d31b26d9fd75b9f2749cf0fc652fb34"
+ },
"/static/js/highcharts.js": {
"date_published": "2023-10-09T00:00:00.000Z",
"date_modified": "2023-10-09T00:00:00.000Z",
@@ -94,6 +104,11 @@
"date_modified": "2024-01-28T00:00:00.000Z",
"hash": "2435bd016c365ddc7c6daad120bcde8b"
},
+ "/static/js/highstock.js.map": {
+ "date_published": "2024-04-05T00:00:00.000Z",
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "6a6de9a402c29ea5b76e30b5eed6ddd9"
+ },
"/static/js/histogram.js": {
"date_published": "2018-05-08T00:00:00.000Z",
"date_modified": "2024-03-14T00:00:00.000Z",
@@ -151,18 +166,18 @@
},
"/static/js/techreport.js": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "41063b92eb8850bde7a49af891037f22"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "c6d56aa085452dd25392d3cac889dba8"
},
"/static/js/techreport/section.js": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "fa7b58407c44adfc374711c767522ff4"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "692808a4620e6d84ce2a12d45eb7d40b"
},
"/static/js/techreport/timeseries.js": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "85a82b40a1082f03dda77c5956c57d8e"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "6e7983322c2a8dab527e43209910e939"
},
"/static/js/timeseries.js": {
"date_published": "2018-05-08T00:00:00.000Z",
@@ -211,8 +226,8 @@
},
"reports/cwv-tech-new": {
"date_published": "2023-10-09T00:00:00.000Z",
- "date_modified": "2023-10-09T00:00:00.000Z",
- "hash": "1c32b48207473a10ad996bb6fa245144"
+ "date_modified": "2024-04-05T00:00:00.000Z",
+ "hash": "59ca9a96a7a3a9ec1b19bb7aba15f930"
},
"reports/loading-speed": {
"date_published": "2018-05-08T00:00:00.000Z",
diff --git a/tools/generate/generate_js.js b/tools/generate/generate_js.js
index 305de231..218f5aa7 100644
--- a/tools/generate/generate_js.js
+++ b/tools/generate/generate_js.js
@@ -9,7 +9,7 @@ node_module_files = [
'highcharts/modules/export-data.js',
'highcharts/highcharts-more.js.map',
'highcharts/highstock.js.map',
- 'highcharts/modules/exporting.js.map'
+ 'highcharts/modules/exporting.js.map',
'highcharts/modules/exporting.js'
];
From 30e0e09edcb56b1bf5943ebde281395fdc3ac31b Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 10 Apr 2024 15:37:17 +0200
Subject: [PATCH 147/155] responsive and copy
---
config/techreport.json | 35 +++++++---------------------
static/css/techreport/techreport.css | 10 ++++----
templates/techreport/drilldown.html | 2 +-
3 files changed, 14 insertions(+), 33 deletions(-)
diff --git a/config/techreport.json b/config/techreport.json
index b37afa98..e167e208 100644
--- a/config/techreport.json
+++ b/config/techreport.json
@@ -15,7 +15,6 @@
"accessibility",
"best_practices",
"performance",
- "pwa",
"seo"
],
"lighthouse_brackets": [
@@ -127,7 +126,7 @@
],
"adoption_timeseries": {
"title": "All usage",
- "description": "Placeholder",
+ "description": "Information about how ",
"id": "adoption_timeseries",
"endpoint": "adoption",
"default": "adoption",
@@ -229,7 +228,7 @@
"metric": "good_pct",
"label": "Good FID",
"suffix": "%",
- "description": "Percentage of origins with good FID scores (under xxx).",
+ "description": "Percentage of origins with good FID scores (under 100ms).",
"url": "?good-cwv-over-time=FID#good-cwvs"
},
{
@@ -238,7 +237,7 @@
"metric": "good_pct",
"label": "Good CLS",
"suffix": "%",
- "description": "Percentage of origins with good CLS scores (under xxx).",
+ "description": "Percentage of origins with good CLS scores (under 0.1).",
"url": "?good-cwv-over-time=CLS#good-cwvs"
},
{
@@ -247,7 +246,7 @@
"metric": "good_pct",
"label": "Good INP",
"suffix": "%",
- "description": "Percentage of origins with good INP scores (under xxx).",
+ "description": "Percentage of origins with good INP scores (under 200ms).",
"url": "?good-cwv-over-time=INP#good-cwvs"
}
]
@@ -407,13 +406,6 @@
"label": "SEO",
"url": "?median-lighthouse-over-time=seo#lighthouse"
},
- {
- "endpoint": "lighthouse",
- "category": "pwa",
- "metric": "median_score_pct",
- "label": "PWA",
- "url": "?median-lighthouse-over-time=pwa#lighthouse"
- },
{
"endpoint": "lighthouse",
"category": "best_practices",
@@ -447,10 +439,6 @@
"label": "SEO (Search Engine Optimisation)",
"value": "seo"
},
- {
- "label": "PWA (Progressive Web Apps)",
- "value": "pwa"
- },
{
"label": "Best practices",
"value": "best_practices"
@@ -881,10 +869,6 @@
"label": "SEO (Search Engine Optimisation)",
"value": "seo"
},
- {
- "label": "PWA (Progressive Web Apps)",
- "value": "pwa"
- },
{
"label": "Best practices",
"value": "best_practices"
@@ -1129,6 +1113,9 @@
"labels": {
"metrics": {
"lighthouse": {
+ "general": {
+ "description": "Lighthouse has audits for performance, accessibility, progressive web apps, SEO, and more. Based on the audits, a score is calculated. Currently, this section visualizes median scores, but in the future you'll also be able to explore the details of the audits here."
+ },
"performance": {
"title": "Performance",
"description": "In general, only metrics contribute to your Lighthouse Performance score, not the results of Opportunities or Diagnostics. "
@@ -1139,15 +1126,11 @@
},
"seo": {
"title": "SEO",
- "description": "todo"
+ "description": "These checks ensure that your page is following basic search engine optimization advice. There are many additional factors Lighthouse does not score here that may affect your search ranking, including performance on Core Web Vitals."
},
"best_practices": {
"title": "Best Practices",
- "description": "todo"
- },
- "pwa": {
- "title": "Progressive Web Apps",
- "description": "todo"
+ "description": "This ensures that your page is built using modern web development best practices."
}
},
"vitals": {
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index ac2631b2..35e1b2b7 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -936,15 +936,13 @@ select {
.component-heading-wrapper {
display: flex;
flex-wrap: wrap-reverse;
-}
-
-.component-heading-wrapper > * {
- flex: 1;
- max-width: 100%;
+ gap: 1rem;
+ justify-content: space-between;
}
.component-heading {
- max-width: 90vw;
+ flex: 0 0 30rem;
+ max-width: 100%;
}
.component-heading h3 {
diff --git a/templates/techreport/drilldown.html b/templates/techreport/drilldown.html
index 8bc6b318..ccc86f75 100644
--- a/templates/techreport/drilldown.html
+++ b/templates/techreport/drilldown.html
@@ -83,7 +83,7 @@ {{ tech_report_page.config.good_cwv_summary.title }}
data-api="lighthouse"
>
Lighthouse
- Description
+ {{ tech_report_labels.metrics.lighthouse.general.description }}
{% if tech_report_page.config.lighthouse_summary %}
{% set section_prefix = "lighthouse" %}
From b7718b7feeeb44d02554cc4b728230c6f040d22a Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 10 Apr 2024 14:48:05 +0100
Subject: [PATCH 148/155] Remove source maps
---
tools/generate/generate_js.js | 4 ----
1 file changed, 4 deletions(-)
diff --git a/tools/generate/generate_js.js b/tools/generate/generate_js.js
index 218f5aa7..dbcf8732 100644
--- a/tools/generate/generate_js.js
+++ b/tools/generate/generate_js.js
@@ -5,11 +5,7 @@ node_module_files = [
'highcharts/highcharts-more.js',
'highcharts/highstock.js',
'highcharts/modules/accessibility.js',
- 'highcharts/modules/accessibility.js.map',
'highcharts/modules/export-data.js',
- 'highcharts/highcharts-more.js.map',
- 'highcharts/highstock.js.map',
- 'highcharts/modules/exporting.js.map',
'highcharts/modules/exporting.js'
];
From d312fbe6d7fb621c0e730eee81b8f570d66d94a1 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Wed, 10 Apr 2024 15:55:23 +0200
Subject: [PATCH 149/155] lowercase colors
---
static/css/techreport/techreport.css | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 35e1b2b7..7481a97a 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -349,11 +349,11 @@ main :is(
}
.select-label:has(select:is(:focus-visible, :hover)):after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.select-label:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.select-label:has(select:focus-visible) label {
@@ -395,7 +395,7 @@ main :is(
}
.tech-selector-group:has(.remove-tech:is(:focus, :hover)) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.tech-selector-group {
@@ -450,11 +450,11 @@ main :is(
}
.tech-input-wrapper:has(select:is(:focus-visible, :hover)):after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.tech-input-wrapper:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
color: var(--color-text);
}
@@ -712,11 +712,11 @@ select {
}
.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover)):after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.subcategory-selector-wrapper:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.subcategory-selector-wrapper:has(select:focus-visible) label {
@@ -1249,15 +1249,15 @@ path.highcharts-tick {
}
.progress-chart.poor .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #FF3333;
+ stroke: #ff3333;
}
.progress-chart.good .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #18A975;
+ stroke: #18a975;
}
.progress-chart.improvement .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #C7870B;
+ stroke: #c7870b;
}
/* ----------------------- */
From 6e8abc9f3f0aebb354226a44ad0e4bb8b9121bb1 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 10 Apr 2024 15:12:12 +0100
Subject: [PATCH 150/155] CSS linting
---
.github/linters/.stylelintrc.json | 9 +--
static/css/techreport/landing.css | 5 +-
static/css/techreport/techreport.css | 100 ++++++---------------------
3 files changed, 25 insertions(+), 89 deletions(-)
diff --git a/.github/linters/.stylelintrc.json b/.github/linters/.stylelintrc.json
index 47699a52..1827eecd 100644
--- a/.github/linters/.stylelintrc.json
+++ b/.github/linters/.stylelintrc.json
@@ -17,21 +17,14 @@
}
],
"length-zero-no-unit": null,
- "max-line-length": null,
+ "media-feature-range-notation": "prefix",
"no-descending-specificity": null,
- "no-eol-whitespace": [
- true,
- {
- "ignore": ["empty-lines"]
- }
- ],
"property-no-unknown": [
true,
{
"ignoreProperties": ["prince-pdf-display-doc-title","prince-pdf-tag-type"]
}
],
- "selector-list-comma-newline-after": "always",
"selector-pseudo-element-no-unknown": [
true,
{
diff --git a/static/css/techreport/landing.css b/static/css/techreport/landing.css
index fd9a4786..7d88c32f 100644
--- a/static/css/techreport/landing.css
+++ b/static/css/techreport/landing.css
@@ -5,8 +5,7 @@
.choices {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
- column-gap: 2rem;
- row-gap: 1rem;
+ gap: 1rem 2rem;
margin-bottom: 4rem;
margin-top: -15rem;
}
@@ -30,7 +29,7 @@
display: block;
width: 100%;
height: 17rem;
- background-color: #EEEEEE;
+ background-color: #EEE;
margin-top: 1rem;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index ac2631b2..f1ce7251 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -8,7 +8,6 @@
--color-blue-dark: #3a7098;
--color-blue-100: #eff7ff;
--color-blue-light: #E1F1FF;
-
--color-gray-medium: #5c5c5d;
/* Colors based on function */
@@ -57,14 +56,14 @@
--color-text-lighter: #fff;
--color-text-darker: #fff;
--color-text-inverted: #000;
- --color-card-background: #111111;
+ --color-card-background: #111;
--color-card-border: #000;
--color-page-background: #292828;
--color-checkbox-button-label-selected: #292828;
--color-checkbox: #fff;
--color-checkbox-selected: #292828;
--color-theme-toggle-background: transparent;
- --color-bg-gradient: #111111;
+ --color-bg-gradient: #111;
--color-page-border: #000;
--color-tooltip-border: var(--color-page-background);
@@ -252,8 +251,7 @@ main :is(
display: grid;
grid-template-columns: repeat(auto-fit, minmax(4rem, 1fr));
margin: 0;
- column-gap: 0.5rem;
- row-gap: 0.5rem;
+ gap: 0.5rem 0.5rem;
margin-bottom: 0.5rem;
margin-right: 0;
margin-top: 2rem;
@@ -291,30 +289,21 @@ main :is(
}
#page-filters .select-label select{
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
-
background-color: transparent;
z-index: 1;
-
position: relative;
-
- padding: 0;
border: none;
- border-radius: 0;
margin-bottom: 0;
padding: 1.75rem 0.5rem 0.5rem 0.75rem;
-
font-size: 1rem;
line-height: 100%;
-
color: var(--color-text-darker);
border-radius: 3px;
outline-offset: 2px;
}
-.select-label:before {
+.select-label::before {
content: "";
display: block;
width: 2.5rem;
@@ -324,31 +313,27 @@ main :is(
border-radius: 0 4px 4px 0;
}
-.select-label:after {
+.select-label::after {
content: "";
display: block;
-
width: 0.5rem;
height: 0.5rem;
-
position: absolute;
right: 1rem;
top: 50%;
top: calc(50% - 0.25rem);
-
border-bottom: 1.5px solid var(--color-text-darker);
border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
-
transform: rotate(-45deg);
}
-.select-label:has(select:is(:focus-visible, :hover)):before {
+.select-label:has(select:is(:focus-visible, :hover))::before {
background-color: var(--color-text-darker);
border-left: 1px solid var(--color-text-darker);
}
-.select-label:has(select:is(:focus-visible, :hover)):after {
+.select-label:has(select:is(:focus-visible, :hover))::after {
border-color: #F2F9FF;
}
@@ -371,16 +356,10 @@ main :is(
font-size: 1.25rem;
width: 100%;
margin-bottom: 0;
-
border: 1px solid #959494;
color: var(--color-text-lighter);
-
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
-
background-color: transparent;
-
padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
@@ -408,7 +387,7 @@ main :is(
position: relative;
}
-.tech-input-wrapper:before {
+.tech-input-wrapper::before {
content: "";
display: block;
width: 2.5rem;
@@ -419,22 +398,18 @@ main :is(
z-index: 0;
}
-.tech-input-wrapper:after {
+.tech-input-wrapper::after {
content: "";
display: block;
-
width: 0.5rem;
height: 0.5rem;
-
position: absolute;
right: 1rem;
top: 50%;
top: calc(50% - 0.25rem);
-
border-bottom: 1.5px solid var(--color-text-darker);
border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
-
transform: rotate(-45deg);
z-index: 0;
}
@@ -444,12 +419,12 @@ main :is(
position: relative;
}
-.tech-input-wrapper:has(select:is(:focus-visible, :hover)):before {
+.tech-input-wrapper:has(select:is(:focus-visible, :hover))::before {
background-color: var(--color-text-darker);
border-left: 1px solid var(--color-text-darker);
}
-.tech-input-wrapper:has(select:is(:focus-visible, :hover)):after {
+.tech-input-wrapper:has(select:is(:focus-visible, :hover))::after {
border-color: #F2F9FF;
}
@@ -480,28 +455,19 @@ main :is(
.categories-selector-group label {
font-weight: 400;
font-size: 0.825rem;
-
margin-bottom: 0;
}
.categories-selector-group select {
margin-bottom: 0;
-
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
-
background-color: transparent;
color: var(--color-text-lighter);
-
border: none;
font-size: 0.825rem;
-
padding: 0;
-
border-radius: 0;
width: 15ch;
-
border-bottom: 1px solid #959494;
}
@@ -543,25 +509,16 @@ select {
}
.client-breakdown-wrapper select {
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
-
background-color: transparent;
z-index: 1;
border-radius: 0;
border: none;
-
color: var(--color-text);
-
padding: 0;
-
width: 5rem;
-
border-bottom: 1px solid var(--color-text-lighter);
-
display: block;
-
font-size: 1rem;
}
@@ -617,8 +574,7 @@ select {
.summary-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
- column-gap: 1rem;
- row-gap: 1rem;
+ gap: 1rem 1rem;
}
.summary-grid + .card {
@@ -652,16 +608,10 @@ select {
.subcategory-selector-wrapper select {
margin-bottom: 0;
border: none;
- -webkit-appearance: none;
- -moz-appearance: none;
appearance: none;
-
background-color: transparent;
-
color: var(--color-text);
-
padding-right: 3rem;
-
z-index: 2;
position: relative;
display: unset;
@@ -677,28 +627,23 @@ select {
}
-.subcategory-selector-wrapper:after {
+.subcategory-selector-wrapper::after {
content: "";
display: block;
-
width: 0.5rem;
height: 0.5rem;
-
position: absolute;
right: 1rem;
top: 50%;
top: calc(50% - 0.25rem);
-
border-bottom: 1.5px solid var(--color-text-darker);
border-left: 1.5px solid var(--color-text-darker);
border-radius: 1px;
-
transform: rotate(-45deg);
-
z-index: 1;
}
-.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover)):before {
+.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover))::before {
content: "";
display: block;
height: 100%;
@@ -711,7 +656,7 @@ select {
z-index: 0;
}
-.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover)):after {
+.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover))::after {
border-color: #F2F9FF;
}
@@ -915,7 +860,7 @@ select {
display: block;
}
-.table-ui td.pct-value[data-value] span:after {
+.table-ui td.pct-value[data-value] span::after {
content: '';
display: block;
height: 0.5rem;
@@ -1109,14 +1054,13 @@ select {
margin-right: 3rem;
}
-.data-summary .breakdown-label:after {
+.data-summary .breakdown-label::after {
content: "";
display: block;
width: 2rem;
height: 0.17rem;
background-color: black;
background-color: var(--breakdown-color);
-
position: absolute;
top: 0.7rem;
left: 100%;
@@ -1251,7 +1195,7 @@ path.highcharts-tick {
}
.progress-chart.poor .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #FF3333;
+ stroke: #F33;
}
.progress-chart.good .lighthouse-progress:not(.border-1, .border-2) {
@@ -1303,7 +1247,7 @@ path.highcharts-tick {
height: 0;
}
-.check-wrapper input:after {
+.check-wrapper input::after {
position: absolute;
top: 0;
left: 0;
@@ -1313,7 +1257,7 @@ path.highcharts-tick {
height: 100%;
}
-.check-wrapper:before {
+.check-wrapper::before {
content: "";
display: block;
width: 1rem;
@@ -1329,7 +1273,7 @@ path.highcharts-tick {
background-color: var(--color-checkbox-button-selected);
}
-.check-wrapper:has(input:checked):before {
+.check-wrapper:has(input:checked)::before {
background-color: var(--color-checkbox-selected);
border-color: var(--color-checkbox-selected);
box-shadow: 0 0 0 1.5px var(--color-checkbox-button-selected) inset;
@@ -1400,7 +1344,7 @@ path.highcharts-tick {
min-width: 10rem;
}
- .table-ui td.pct-value[data-value] span:after {
+ .table-ui td.pct-value[data-value] span::after {
display: none;
}
From 71f7edde3763ecca26e11bb6827ea18e34d91c85 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 10 Apr 2024 15:23:25 +0100
Subject: [PATCH 151/155] More CSS linting
---
.github/linters/.stylelintrc.json | 9 ++++++++
static/css/techreport/landing.css | 2 +-
static/css/techreport/techreport.css | 32 ++++++++++++++--------------
3 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/.github/linters/.stylelintrc.json b/.github/linters/.stylelintrc.json
index 1827eecd..ca180858 100644
--- a/.github/linters/.stylelintrc.json
+++ b/.github/linters/.stylelintrc.json
@@ -16,15 +16,24 @@
"ignoreFontFamilyNames": ["monospace"]
}
],
+ "color-hex-case": "lower",
"length-zero-no-unit": null,
+ "max-line-length": null,
"media-feature-range-notation": "prefix",
"no-descending-specificity": null,
+ "no-eol-whitespace": [
+ true,
+ {
+ "ignore": ["empty-lines"]
+ }
+ ],
"property-no-unknown": [
true,
{
"ignoreProperties": ["prince-pdf-display-doc-title","prince-pdf-tag-type"]
}
],
+ "selector-list-comma-newline-after": "always",
"selector-pseudo-element-no-unknown": [
true,
{
diff --git a/static/css/techreport/landing.css b/static/css/techreport/landing.css
index 7d88c32f..dc23d173 100644
--- a/static/css/techreport/landing.css
+++ b/static/css/techreport/landing.css
@@ -29,7 +29,7 @@
display: block;
width: 100%;
height: 17rem;
- background-color: #EEE;
+ background-color: #eee;
margin-top: 1rem;
}
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index f1ce7251..568e8335 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -7,14 +7,14 @@
--color-teal-darker: #1c4750;
--color-blue-dark: #3a7098;
--color-blue-100: #eff7ff;
- --color-blue-light: #E1F1FF;
+ --color-blue-light: #e1f1ff;
--color-gray-medium: #5c5c5d;
/* Colors based on function */
--color-link: var(--color-blue-dark);
--color-text: #444;
--color-text-lighter: #5f6768;
- --color-text-darker: #1E1E1E;
+ --color-text-darker: #1e1e1e;
--color-text-inverted: #fff;
--color-card-background: #fff;
--color-card-border: #cdd4d6;
@@ -43,8 +43,8 @@
/* Graph colors */
--graph-color-primary: var(--color-teal-dark);
--graph-color-primary-darker: var(--color-teal-darker);
- --graph-color-line: #A6BBBE;
- --graph-color-labels: #62777B;
+ --graph-color-line: #a6bbbe;
+ --graph-color-labels: #62777b;
/* Defaults */
--breakdown-color: var(--color-text);
@@ -68,7 +68,7 @@
--color-tooltip-border: var(--color-page-background);
/* Graph colors */
- --graph-color-labels: #A6BBBE;
+ --graph-color-labels: #a6bbbe;
--graph-color-line: var(--color-gray-medium);
}
@@ -222,7 +222,7 @@ main :is(
}
.remove-tech:is(:hover, :focus) img {
- background: #FCC9C4;
+ background: #fcc9c4;
border-radius: 3rem;
}
@@ -334,11 +334,11 @@ main :is(
}
.select-label:has(select:is(:focus-visible, :hover))::after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.select-label:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.select-label:has(select:focus-visible) label {
@@ -374,7 +374,7 @@ main :is(
}
.tech-selector-group:has(.remove-tech:is(:focus, :hover)) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.tech-selector-group {
@@ -425,11 +425,11 @@ main :is(
}
.tech-input-wrapper:has(select:is(:focus-visible, :hover))::after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.tech-input-wrapper:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
color: var(--color-text);
}
@@ -657,11 +657,11 @@ select {
}
.subcategory-selector-wrapper:has(select:is(:focus-visible, :hover))::after {
- border-color: #F2F9FF;
+ border-color: #f2f9ff;
}
.subcategory-selector-wrapper:has(select:focus-visible) {
- background-color: #F2F9FF;
+ background-color: #f2f9ff;
}
.subcategory-selector-wrapper:has(select:focus-visible) label {
@@ -1195,15 +1195,15 @@ path.highcharts-tick {
}
.progress-chart.poor .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #F33;
+ stroke: #f33;
}
.progress-chart.good .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #18A975;
+ stroke: #18a975;
}
.progress-chart.improvement .lighthouse-progress:not(.border-1, .border-2) {
- stroke: #C7870B;
+ stroke: #c7870b;
}
/* ----------------------- */
From 083a93cf85be502da276c4fa8bb446f2b6c75499 Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 10 Apr 2024 15:30:56 +0100
Subject: [PATCH 152/155] More linting
---
.github/linters/.stylelintrc.json | 2 +-
static/css/techreport/general.css | 3 ---
static/css/techreport/techreport.css | 15 ++++-----------
3 files changed, 5 insertions(+), 15 deletions(-)
diff --git a/.github/linters/.stylelintrc.json b/.github/linters/.stylelintrc.json
index ca180858..8f6d5a3b 100644
--- a/.github/linters/.stylelintrc.json
+++ b/.github/linters/.stylelintrc.json
@@ -10,13 +10,13 @@
],
"color-function-notation": null,
"comment-empty-line-before": null,
+ "declaration-colon-newline-after": null,
"font-family-no-duplicate-names": [
true,
{
"ignoreFontFamilyNames": ["monospace"]
}
],
- "color-hex-case": "lower",
"length-zero-no-unit": null,
"max-line-length": null,
"media-feature-range-notation": "prefix",
diff --git a/static/css/techreport/general.css b/static/css/techreport/general.css
index 22995614..3651401f 100644
--- a/static/css/techreport/general.css
+++ b/static/css/techreport/general.css
@@ -7,10 +7,8 @@
body {
background-color: var(--color-page-background);
font-size: 1rem;
-
}
-
main {
color: var(--color-text);
}
@@ -29,7 +27,6 @@ h2 + p {
padding: 0;
}
-
/* Overwrite margin that's set elsewhere */
p {
margin: 0;
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 568e8335..1b27eac6 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -82,10 +82,7 @@ body > :is(header, footer) {
}
/* Links */
-main :is(
- a,
- p a
-) {
+main :is(a, p a) {
color: var(--color-link);
}
@@ -268,7 +265,6 @@ main :is(
border-color: var(--color-text-lighter);
}
-
.select-label {
border: 1px solid #959494;
padding: 0;
@@ -288,7 +284,7 @@ main :is(
color: #767474;
}
-#page-filters .select-label select{
+#page-filters .select-label select {
appearance: none;
background-color: transparent;
z-index: 1;
@@ -626,7 +622,6 @@ select {
outline-offset: 1.5px;
}
-
.subcategory-selector-wrapper::after {
content: "";
display: block;
@@ -669,7 +664,6 @@ select {
}
-
/* Timeseries cards */
.timeseries-container {
margin-top: 2rem;
@@ -861,7 +855,7 @@ select {
}
.table-ui td.pct-value[data-value] span::after {
- content: '';
+ content: "";
display: block;
height: 0.5rem;
width: 100%;
@@ -959,9 +953,8 @@ select {
margin-bottom: 0.5rem;
}
-
.report-content {
- background-image: linear-gradient(var(--color-bg-gradient), rgba(238,238,238,0));
+ background-image: linear-gradient(var(--color-bg-gradient), rgba(238, 238, 238, 0));
background-size: 100% 50rem;
background-repeat: no-repeat;
padding-top: 3rem;
From 522b564ad221cc2e3678255c5b46dc7f7eeacd7b Mon Sep 17 00:00:00 2001
From: Barry Pollard
Date: Wed, 10 Apr 2024 15:44:26 +0100
Subject: [PATCH 153/155] Linting
---
static/css/techreport/techreport.css | 1 -
1 file changed, 1 deletion(-)
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index 1b27eac6..2699f6ac 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -663,7 +663,6 @@ select {
color: var(--color-text) !important;
}
-
/* Timeseries cards */
.timeseries-container {
margin-top: 2rem;
From a9531bb2628eb8ee36a2ca9c36f2b82b03c45b50 Mon Sep 17 00:00:00 2001
From: Sarah Fossheim
Date: Fri, 12 Apr 2024 17:45:16 +0200
Subject: [PATCH 154/155] remove duplicate selectors
---
static/components/table.css | 5 +----
static/css/techreport/techreport.css | 9 +--------
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/static/components/table.css b/static/components/table.css
index f3a15630..97029c59 100644
--- a/static/components/table.css
+++ b/static/components/table.css
@@ -29,6 +29,7 @@
.table-ui :is(td, th) {
min-width: 5rem;
+ text-align: left;
}
.table-ui :is(td, th):not(:last-child) {
@@ -43,10 +44,6 @@
font-weight: normal;
}
-.table-ui :is(td, th) {
- text-align: left;
-}
-
.table-ui :is(td, th) strong {
margin-right: 0.1rem;
font-weight: 600;
diff --git a/static/css/techreport/techreport.css b/static/css/techreport/techreport.css
index a16130a0..beb10533 100644
--- a/static/css/techreport/techreport.css
+++ b/static/css/techreport/techreport.css
@@ -552,10 +552,6 @@ select {
border-color: var(--color-text-lighter);
}
-.table-ui-wrapper {
- overflow-x: scroll;
-}
-
.card.table-ui-wrapper {
margin-bottom: 2rem;
}
@@ -740,6 +736,7 @@ select {
.table-ui :is(td, th) {
min-width: 5rem;
+ text-align: left;
}
.table-ui :is(td, th):not(:last-child) {
@@ -754,10 +751,6 @@ select {
font-weight: normal;
}
-.table-ui :is(td, th) {
- text-align: left;
-}
-
.table-ui :is(td, th) strong {
margin-right: 0.1rem;
font-weight: 600;
From c7d9b3d60c66ea02c75d52763e8bb8b172566bef Mon Sep 17 00:00:00 2001
From: Rick Viscomi
Date: Mon, 29 Apr 2024 14:48:04 -0400
Subject: [PATCH 155/155] img h/w
---
templates/techreport/templates/selector_tech.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/techreport/templates/selector_tech.html b/templates/techreport/templates/selector_tech.html
index 5459764d..4608857c 100644
--- a/templates/techreport/templates/selector_tech.html
+++ b/templates/techreport/templates/selector_tech.html
@@ -24,7 +24,7 @@
{% if active_page == "comparison" %}
-
+
{% endif %}