blob: 9ace53517ee4b98dfa2ec660c187cbb930d72d06 [file] [log] [blame]
/**
* @module modules/point-links-sk
* @description <h2><code>point-links-sk</code></h2>
* This module provides the ability to display links which are specific to data points.
* The original data source for the links come from the ingestion file and the caller
* provides a list of keys to extract from the links and format those as anchor elements
* to be displayed.
*
* This module also generates commit range links for incoming links that are commits. This
* is done by getting the links for the current commit (the point that is selected) and the
* previous commit, and then generating a git log url to show the list of commits between
* both of these.
*
* @example
*
* Link in ingestion file (commit n): {'V8 Git Hash': 'https://chromium.googlesource.com/v8/v8/+/47f420e89ec1b33dacc048d93e0317ab7fec43dd'}
* Link in ingestion file (commit n-1): {'V8 Git Hash': 'https://chromium.googlesource.com/v8/v8/+/f052b8c4db1f08d1f8275351c047854e6ff1805f'}
*
* Since both the commit links are different, this module will generate a new link like below.
*
* <a href='https://chromium.googlesource.com/v8/v8/+log/f052b8c4..47f420e>V8 Git Hash Range</a>
*/
import { TemplateResult, html } from 'lit-html';
import { define } from '../../../elements-sk/modules/define';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { CommitDetailsRequest, CommitNumber, ingest } from '../json';
import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
import { errorMessage } from '../errorMessage';
export class PointLinksSk extends ElementSk {
constructor() {
super(PointLinksSk.template);
}
// Contains the urls to be displayed.
displayUrls: { [key: string]: string } = {};
// Contains the texts for the urls to be displayed.
displayTexts: { [key: string]: string } = {};
private static template = (ele: PointLinksSk) =>
html` <div ?hidden=${Object.keys(ele.displayUrls || {}).length === 0}>
<ul>
${ele.renderLinks()}
</ul>
</div>`;
connectedCallback(): void {
super.connectedCallback();
this._render();
}
renderLinks(): TemplateResult[] {
const keys = Object.keys(this.displayUrls);
const getHtml = (key: string): TemplateResult => {
const link = this.displayUrls![key];
const linkText = this.displayTexts[key];
return html`<li>${key}: <a href="${link}"> ${linkText}</a></li>`;
};
return keys.map(getHtml);
}
// load and display the links for the given commit and trace.
public async load(
cid: CommitNumber,
prev_cid: CommitNumber,
traceid: string,
keysForCommitRange: string[]
): Promise<void> {
// Clear any existing links first.
this.displayUrls = {};
this.displayTexts = {};
const currentLinks = await this.getLinksForPoint(cid, traceid);
const prevLinks = await this.getLinksForPoint(prev_cid, traceid);
keysForCommitRange.forEach((key) => {
const currentCommitUrl = currentLinks[key];
if (
currentCommitUrl !== undefined &&
currentCommitUrl !== null &&
currentCommitUrl !== ''
) {
const prevCommitUrl = prevLinks[key];
const currentCommitId = this.getCommitIdFromCommitUrl(
currentCommitUrl
).substring(0, 7);
const prevCommitId = this.getCommitIdFromCommitUrl(
prevCommitUrl
).substring(0, 7);
if (currentCommitId === prevCommitId) {
this.displayUrls[key] = currentCommitUrl;
this.displayTexts[key] = currentCommitId;
} else {
const repoUrl = this.getRepoUrlFromCommitUrl(currentCommitUrl);
const commitRangeUrl = `${repoUrl}+log/${prevCommitId}..${currentCommitId}`;
const displayKey = `${key} Range`;
this.displayUrls[displayKey] = commitRangeUrl;
this.displayTexts[displayKey] = this.getFormattedCommitRangeText(
prevCommitId,
currentCommitId
);
}
}
});
this._render();
}
/**
* Get the commit range text.
* @param start Start Commit.
* @param end End Commit.
* @returns Formatted text.
*/
private getFormattedCommitRangeText(start: string, end: string): string {
return `${start} - ${end}`;
}
/**
* Get the repository name from the given commit url.
* @param commitUrl Full commit url.
* @returns Repository name.
*/
private getRepoUrlFromCommitUrl(commitUrl: string): string {
const idx = commitUrl.indexOf('+');
return commitUrl.substring(0, idx);
}
/**
* Get the commit id from the given commit url.
* @param commitUrl Full commit url.
* @returns Commit id.
*/
private getCommitIdFromCommitUrl(commitUrl: string): string {
const idx = commitUrl.lastIndexOf('/');
return commitUrl.substring(idx + 1);
}
/**
* Get the links for the given commit.
* @param cid Commit id.
* @param traceId Trace id.
* @returns Links relevant to the commit id and trace id.
*/
private async getLinksForPoint(
cid: CommitNumber,
traceId: string
): Promise<{ [key: string]: string }> {
const body: CommitDetailsRequest = {
cid: cid,
traceid: traceId,
};
const url = '/_/details/?results=false';
try {
const resp = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const json = await jsonOrThrow(resp);
const format = json as ingest.Format;
return format.links!;
} catch (error) {
await errorMessage(error as string);
}
return {};
}
}
define('point-links-sk', PointLinksSk);