blob: 555a82fedfe2199c5793bebba75a5c80c5758bc2 [file] [log] [blame]
class ChartPane extends ChartPaneBase {
constructor(chartsPage, platformId, metricId)
{
super('chart-pane');
this._mainChartIndicatorWasLocked = false;
this._chartsPage = chartsPage;
this._paneOpenedByClick = null;
this.content().querySelector('close-button').component().setCallback(chartsPage.closePane.bind(chartsPage, this));
this.configure(platformId, metricId);
}
serializeState()
{
var state = [this._platformId, this._metricId];
if (this._mainChart) {
var selection = this._mainChart.currentSelection();
var currentPoint = this._mainChart.currentPoint();
if (selection)
state[2] = selection;
else if (this._mainChartIndicatorWasLocked && currentPoint)
state[2] = currentPoint.id;
}
return state;
}
updateFromSerializedState(state, isOpen)
{
if (!this._mainChart)
return;
var selectionOrIndicatedPoint = state[2];
if (selectionOrIndicatedPoint instanceof Array)
this._mainChart.setSelection([parseFloat(selectionOrIndicatedPoint[0]), parseFloat(selectionOrIndicatedPoint[1])]);
else if (typeof(selectionOrIndicatedPoint) == 'number') {
this._mainChart.setIndicator(selectionOrIndicatedPoint, true);
this._mainChartIndicatorWasLocked = true;
} else
this._mainChart.setIndicator(null, false);
}
setOverviewSelection(selection)
{
if (this._overviewChart)
this._overviewChart.setSelection(selection);
}
_overviewSelectionDidChange(domain, didEndDrag)
{
super._overviewSelectionDidChange(domain, didEndDrag);
this._chartsPage.setMainDomainFromOverviewSelection(domain, this, didEndDrag);
}
_mainSelectionDidChange(selection, didEndDrag)
{
super._mainSelectionDidChange(selection, didEndDrag);
this._chartsPage.mainChartSelectionDidChange(this, didEndDrag);
}
_mainSelectionDidZoom(selection)
{
super._mainSelectionDidZoom(selection);
this._chartsPage.setMainDomainFromZoom(selection, this);
}
router() { return this._chartsPage.router(); }
_requestOpeningCommitViewer(repository, from, to)
{
super._requestOpeningCommitViewer(repository, from, to);
this._chartsPage.setOpenRepository(repository);
}
setOpenRepository(repository)
{
if (repository != this._commitLogViewer.currentRepository()) {
var range = this._mainChartStatus.setCurrentRepository(repository);
this._commitLogViewer.view(repository, range.from, range.to).then(this.render.bind(this));
this.render();
}
}
_indicatorDidChange(indicatorID, isLocked)
{
this._chartsPage.mainChartIndicatorDidChange(this, isLocked != this._mainChartIndicatorWasLocked);
this._mainChartIndicatorWasLocked = isLocked;
super._indicatorDidChange(indicatorID, isLocked);
}
render()
{
if (this._platform && this._metric) {
var metric = this._metric;
var platform = this._platform;
this.renderReplace(this.content().querySelector('.chart-pane-title'),
metric.fullName() + ' on ' + platform.name());
}
if (this._mainChartStatus)
this._renderActionToolbar();
super.render();
}
_renderActionToolbar()
{
var actions = [];
var platform = this._platform;
var metric = this._metric;
var element = ComponentBase.createElement;
var link = ComponentBase.createLink;
var self = this;
if (this._chartsPage.canBreakdown(platform, metric)) {
actions.push(element('li', link('Breakdown', function () {
self._chartsPage.insertBreakdownPanesAfter(platform, metric, self);
})));
}
var platformPane = this.content().querySelector('.chart-pane-alternative-platforms');
var alternativePlatforms = this._chartsPage.alternatePlatforms(platform, metric);
if (alternativePlatforms.length) {
this.renderReplace(platformPane, Platform.sortByName(alternativePlatforms).map(function (platform) {
return element('li', link(platform.label(), function () {
self._chartsPage.insertPaneAfter(platform, metric, self);
}));
}));
actions.push(element('li', {class: this._paneOpenedByClick == platformPane ? 'selected' : ''},
this._makeAnchorToOpenPane(platformPane, 'Other Platforms', true)));
} else {
platformPane.style.display = 'none';
}
var analyzePane = this.content().querySelector('.chart-pane-analyze-pane');
var pointsRangeForAnalysis = this._mainChartStatus.pointsRangeForAnalysis();
if (pointsRangeForAnalysis) {
actions.push(element('li', {class: this._paneOpenedByClick == analyzePane ? 'selected' : ''},
this._makeAnchorToOpenPane(analyzePane, 'Analyze', false)));
var router = this._chartsPage.router();
analyzePane.onsubmit = function (event) {
event.preventDefault();
var newWindow = window.open(router.url('analysis/task/create'), '_blank');
var name = analyzePane.querySelector('input').value;
AnalysisTask.create(name, pointsRangeForAnalysis.startPointId, pointsRangeForAnalysis.endPointId).then(function (data) {
newWindow.location.href = router.url('analysis/task/' + data['taskId']);
// FIXME: Refetch the list of analysis tasks.
}, function (error) {
newWindow.location.href = router.url('analysis/task/create', {error: error});
});
}
} else {
analyzePane.style.display = 'none';
analyzePane.onsubmit = function (event) { event.preventDefault(); }
}
this._paneOpenedByClick = null;
this.renderReplace(this.content().querySelector('.chart-pane-action-buttons'), actions);
}
_makeAnchorToOpenPane(pane, label, shouldRespondToHover)
{
var anchor = null;
var ignoreMouseLeave = false;
var self = this;
var setPaneVisibility = function (pane, shouldShow) {
var anchor = pane.anchor;
if (shouldShow) {
var width = anchor.offsetParent.offsetWidth;
pane.style.top = anchor.offsetTop + anchor.offsetHeight + 'px';
pane.style.right = (width - anchor.offsetLeft - anchor.offsetWidth) + 'px';
}
pane.style.display = shouldShow ? null : 'none';
anchor.parentNode.className = shouldShow ? 'selected' : '';
if (self._paneOpenedByClick == pane && !shouldShow)
self._paneOpenedByClick = null;
}
var attributes = {
href: '#',
onclick: function (event) {
event.preventDefault();
var shouldShowPane = pane.style.display == 'none';
if (shouldShowPane) {
if (self._paneOpenedByClick)
setPaneVisibility(self._paneOpenedByClick, false);
self._paneOpenedByClick = pane;
}
setPaneVisibility(pane, shouldShowPane);
},
};
if (shouldRespondToHover) {
var mouseIsInAnchor = false;
var mouseIsInPane = false;
attributes.onmouseenter = function () {
if (self._paneOpenedByClick)
return;
mouseIsInAnchor = true;
setPaneVisibility(pane, true);
}
attributes.onmouseleave = function () {
setTimeout(function () {
if (!mouseIsInPane)
setPaneVisibility(pane, false);
}, 0);
mouseIsInAnchor = false;
}
pane.onmouseleave = function () {
setTimeout(function () {
if (!mouseIsInAnchor)
setPaneVisibility(pane, false);
}, 0);
mouseIsInPane = false;
}
pane.onmouseenter = function () {
mouseIsInPane = true;
}
}
var anchor = ComponentBase.createElement('a', attributes, label);
pane.anchor = anchor;
return anchor;
}
static paneHeaderTemplate()
{
return `
<header class="chart-pane-header">
<h2 class="chart-pane-title">-</h2>
<nav class="chart-pane-actions">
<ul>
<li class="close"><close-button></close-button></li>
</ul>
<ul class="chart-pane-action-buttons buttoned-toolbar"></ul>
<ul class="chart-pane-alternative-platforms" style="display:none"></ul>
<form class="chart-pane-analyze-pane" style="display:none">
<input type="text" required>
<button>Create</button>
</form>
</nav>
</header>
`;
}
static cssTemplate()
{
return ChartPaneBase.cssTemplate() + `
.chart-pane {
border: solid 1px #ccc;
border-radius: 0.5rem;
margin: 1rem;
margin-bottom: 2rem;
}
.chart-pane-body {
height: calc(100% - 2rem);
}
.chart-pane-header {
position: relative;
left: 0;
top: 0;
width: 100%;
height: 2rem;
line-height: 2rem;
border-bottom: solid 1px #ccc;
}
.chart-pane-title {
margin: 0 0.5rem;
padding: 0;
padding-left: 1.5rem;
font-size: 1rem;
font-weight: inherit;
}
.chart-pane-actions {
position: absolute;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
height: 2rem;
top: 0;
padding: 0 0;
}
.chart-pane-actions ul {
display: block;
padding: 0;
margin: 0 0.5rem;
font-size: 1rem;
line-height: 1rem;
list-style: none;
}
.chart-pane-actions .chart-pane-action-buttons {
font-size: 0.9rem;
line-height: 0.9rem;
}
.chart-pane-actions .chart-pane-alternative-platforms,
.chart-pane-analyze-pane {
position: absolute;
top: 0;
right: 0;
border: solid 1px #ccc;
border-radius: 0.2rem;
z-index: 10;
background: rgba(255, 255, 255, 0.8);
-webkit-backdrop-filter: blur(0.5rem);
padding: 0.2rem 0;
margin: 0;
margin-top: -0.2rem;
margin-right: -0.2rem;
}
.chart-pane-alternative-platforms li {
}
.chart-pane-alternative-platforms li a {
display: block;
text-decoration: none;
color: inherit;
font-size: 0.9rem;
padding: 0.2rem 0.5rem;
}
.chart-pane-alternative-platforms a:hover,
.chart-pane-analyze-pane input:focus {
background: rgba(204, 153, 51, 0.1);
}
.chart-pane-analyze-pane {
padding: 0.5rem;
}
.chart-pane-analyze-pane input {
font-size: 1rem;
width: 15rem;
outline: none;
border: solid 1px #ccc;
}
`;
}
}