-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add links to switch between different reports in left nav-bar #1477
Conversation
dc43a23
to
3127aab
Compare
Best to add screenshots in PR description and to any followup changes. |
this._url = url; | ||
this._config = config; | ||
|
||
this._root = fs.mkdtempSync(`${__dirname}/experiment-data`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this current directory? Can we rename it to .lighthouse-performance-data-
?
- Dot directory might make more sense
- If its in the current directory, user needs to be able to identify its from lighthouse
-
- at end for the temp suffix to look a bit nicer
What's the size of this data? Could we store it in memory for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not in CWD. It's under lighthouse/lighthouse-cli/performance-experiment/
.
I tested it on YouTube.com, and the results.json
was around 2.3 MB. It's pretty big already and could be bigger for some other websites. So I think we should store it in hard drive.
I addded a "-" to the end of the folder prefix. Thanks for the suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM.
a4cb057
to
4c60003
Compare
I assume this PR will also have to be reworked a bit once #1455 lands? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll wait for #1455 before completely getting into this, but looking good so far.
@@ -61,6 +61,18 @@ | |||
<h1 class="menu__header-title">Lighthouse</h1> | |||
<div class="menu__header-version">Version: {{lighthouseVersion}}</div> | |||
</div> | |||
{{#each relatedReports}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the config panel, I don't see us using this outside of an interactive mode like perfX. This one will be slightly more awkward, but possible to pull out into a partial?
There might be some fancy handlebars way of including it, but also could do it brute force, something like
{{#if_eq reportContext "perf-x" }}
{{> related-reports}}
{{else}}
<ul class="menu__nav">
{{#each aggregations}}
<li class="menu__nav-item">
<a class="menu__link" href="#{{nameToLink this.name}}">
{{ this.name }}
</a>
</li>
{{/each}}
</ul>
{{/if_eq}}
(including the menu__nav
block in the related-reports
partial)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thx for the advice. I will do this after #1455 is landed.
@@ -34,7 +34,7 @@ describe('Report', () => { | |||
it('should format generated Time', () => { | |||
const reportGenerator = new ReportGenerator(); | |||
const html = reportGenerator.generateHTML(sampleResults); | |||
assert.ok(/on 11\/\d{1,2}\/2016\, /gim.test(html)); | |||
assert.ok(/on: 11\/\d{1,2}\/2016\, /gim.test(html)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, how did this pass before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also am curious about this. @WeiweiAtGit do you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, it was matching on the footer, which has Generated by <b>Lighthouse</b> {{lighthouseVersion}} on {{generatedTime}}
this._url = url; | ||
this._config = config; | ||
|
||
this._root = fs.mkdtempSync(`${__dirname}/experiment-data-`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reason for the ending -
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make it looks nicer. Since fs.mkdtempSync
will adds some random characters as postfix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, nice, didn't know fs.mkdtempSync
existed :)
Yes. |
Previously, I thought we had discussed using |
7695d47
to
54c5e2e
Compare
Ready for review. PTAL |
} | ||
return formatter.format(new Date(date)); | ||
// format time | ||
Handlebars.registerHelper('format_time', function(date) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make this a helper so I can use it in perf-x-left-nav partial
@@ -323,7 +330,7 @@ class ReportGenerator { | |||
return template({ | |||
url: results.url, | |||
lighthouseVersion: results.lighthouseVersion, | |||
generatedTime: this._formatTime(results.generatedTime), | |||
generatedTime: results.generatedTime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass generated time as time instead of string to ease time comparison in perf-x-left-nav
this._config = config; | ||
this._defaultId = undefined; | ||
|
||
this._root = fs.mkdtempSync(`${__dirname}/experiment-data-`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename to _fsRoot
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed. thx for your advice : )
const perfXReportGenerator = new PerfXReportGenerator(); | ||
|
||
const results = JSON.parse(fs.readFileSync(path.join(this._root, id, 'results.json'), 'utf8')); | ||
const relatedReports = Object.keys(this._timeStamps) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
otherReports
as they aren't necessarily related, but they are the only other ones the server knows about, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
* @param {?string} id When id is not provided, this._defaultId will be used | ||
*/ | ||
getHTML(id) { | ||
id = id || this._defaultId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i dont really follow what the purpose is of the defaultId. Seems like we don't need a fallback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this allows users to access report from URL bar without inputting a long report id (when they accidentally closed the report tab). Although they can just go to history page most of the time and they still need to remember the port, I feel it's nice to have this feature. But if you feel it's confusing, I can remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. I see. it's a fallback solution so navigating to the web root will always give them a page to use.
Seems okay since we dont have a "please select a report on the left to view" index page yet. cool.
I'd prefer this is handled at the router level rather than the database one. can we move it to the server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to server.js. Thx for the advice.
{{/each}} | ||
{{/createRelatedReportsContext}} | ||
<a class="menu__report-tab" href="#"> | ||
<p class="menu__report-tab__url" title="{{ url }}">Report for: {{ url }}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should probably run this URL through URL.getDisplayName
in the url-shim
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this. It didn't fit very well imo. When I tested http://localhost:8080
, the url here simply became /. Just to clarify, the URL in
Report for: {{ url }}` is the URL of the website being tested, not the report URL.
By the way, originally, the tabs in the left nav were meant to replace the meta data on the top bar. Since we are going to keep the top bar, shall we use report ID here?
} | ||
</style> | ||
|
||
{{#createRelatedReportsContext}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we can do this partial better.
one approach: single loop through the reports. check if the reportId matches the requestedID and if it does, tweak the menu__report-tab
link. maybe generate the menu__nav
's for all the reports, but display:none the others with some classes/css
probably some better ways than that, but let's DRY this up some.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed. thx for the advice.
</li> | ||
{{/each}} | ||
</ul> | ||
{{#if_eq reportContext "perf-x" }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to branch this template not on reportContext, but on the data provided to the template?
so we have a partial for this leftnav thing... we have _relatedReports
or w/e, then we display all those, otherwise, simple menu__nav-item
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can do this. But that also means we'd better move the left-nav partial to the core folder or even embed it into report-template.html directly, because it's no longer just for perf-x in that case (although only perf-x uses it for now). I'm not sure whether I should put the partial in formatters (all the partials there are related to audits), under perf-x, in report-template.html or in a separate folder under core/report. Do you have a good place in mind? And shall we support multiple reports in core/report-generator.js directly in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the loop refactor it seems like the left-nav partial should be pretty straightforward. I like tossing it into the report-template.html
directly.
And yeah, report-generator can take the otherReports array now and handle that. Seems good!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of otherReports
array, I used reportsCatalog
. Because the nav needs to know which report is selected currently. Adding a boolean flag to each of the element in the report is another approach, but I feel using reportsCatalog
is safer, because we won't accidentally mark multiple reports as selected.
@@ -34,7 +34,7 @@ describe('Report', () => { | |||
it('should format generated Time', () => { | |||
const reportGenerator = new ReportGenerator(); | |||
const html = reportGenerator.generateHTML(sampleResults); | |||
assert.ok(/on 11\/\d{1,2}\/2016\, /gim.test(html)); | |||
assert.ok(/on: 11\/\d{1,2}\/2016\, /gim.test(html)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also am curious about this. @WeiweiAtGit do you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're in a good shape here. Just some fairly rote changes left and it'll be ready to land!
@@ -0,0 +1,3 @@ | |||
'use strict'; | |||
|
|||
module.exports = require('./database'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason to have this file and not just do const ExperimentDatabase = require('./experiment-database/database');
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I wanted to encapsulate the database (i.e. database and the temp file it generated will be treated as a whole). Although it will work perfectly as well if we just do const ExperimentDatabase = require('./experiment-database/database');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for not having an empty index.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. I really like the new createNav inline partial and handling there.
A few more ideas in the comments.
Also, should we have some tests? I think database.js is rather testable. And I can see us having a test for the server's reportRequestHandler, providing a fake request/response and asserting that the data provided to response.end
includes a few key text strings. EDIT: If you want, we can do these tests in a followup PR.
@@ -94,8 +97,19 @@ function requestHandler(request, response) { | |||
|
|||
function reportRequestHandler(request, response) { | |||
try { | |||
const id = request.parsedUrl.query.id || defaultReportId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets make a little getSelectedId(request)
method for this and the other handlers
|
||
const reportsMetadata = Object.keys(database.timeStamps).map(key => { | ||
const generatedTime = database.timeStamps[key]; | ||
return {url: database.url, reportHref: `/?id=${key}`, generatedTime}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think can keep the URL building out of here and only in the template for a cleaner view. Here's a proposal (this and the following comments).
return {url: database.url, reportId: key, generatedTime};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to define URL format only in perf-x server. Because if we somehow want to change the URL format in the future, we only need to make changes in perf-x server.
report-template.html does not need to know how routing is done in perf-x server. So there will be less coupling between perf-x server and report template.
Also, other clients will be able to pass reports in a different URL format to the generator if we build URL in the server side.
const generatedTime = database.timeStamps[key]; | ||
return {url: database.url, reportHref: `/?id=${key}`, generatedTime}; | ||
}); | ||
const reportsCatalog = {reportsMetadata, selectedReportHref: `/?id=${id}`}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const reportsCatalog = {reportsMetadata, selectedReportId: id};
{{> perf-x-reports-nav}} | ||
{{#if reportsCatalog }} | ||
{{#each reportsCatalog.reportsMetadata }} | ||
<a class="menu__report-tab" href="{{ reportHref }}"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... href="/?id={{ reportId }}">
<p class="menu__report-tab__url" title="{{ url }}">Report for: {{ url }}</p> | ||
<p class="menu__report-tab__time">Generated on: {{ format_time generatedTime }}</p> | ||
</a> | ||
{{#if_eq reportHref ../reportsCatalog.selectedReportHref }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{{#if_eq reportId ../reportsCatalog.selectedReportId }}
|
||
|
||
let database; | ||
let defaultReportId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we call this fallbackReportId
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed. thx.
Sure : ) |
@@ -31,6 +31,8 @@ class ConfigPanel { | |||
this._messageField = this._configPanel.querySelector('.js-message'); | |||
this._urlBlockingList = this._configPanel.querySelector('.js-url-blocking-patterns'); | |||
this._urlBlockingStatus = {}; | |||
const match = location.search.match(/[?&]id=([^&]*)/); | |||
this._reportId = match ? match[1]: ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this._reportId = new URL(window.location).searchParams.get('id');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't know that. Thx for your advice :)
…allback to server.js
dd18955
to
efef4a2
Compare
const generatedTime = database.timeStamps[key]; | ||
return {url: database.url, reportHref: `/?id=${key}`, generatedTime}; | ||
}); | ||
reportsMetadata.sort((metadata1, metadata2) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something like this should work:
reportsMetadata.sort((a, b) => b.generatedTime - a.generatedTime);
(maybe flip the two if the order is wrong ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
df9587b
to
260ca21
Compare
Allow users to navigate between different report. Part of Project Perf-X #1143.
![left-panel](https://cloud.githubusercontent.com/assets/20240088/22003148/59f5ff32-dca5-11e6-913d-578388786d60.png)
Screenshot of the new left nav-bar: