blob: a2439ec51ef49377d85e668cd867e01d5711415c [file] [log] [blame] [raw]
// Copyright (c) 2019, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
'use strict';
var
$ = require('jquery'),
_ = require('underscore'),
monaco = require('monaco-editor'),
ga = require('analytics'),
History = require('./history');
function HistoryDiffState(model) {
this.model = model;
this.result = null;
}
HistoryDiffState.prototype.update = function (result) {
this.result = result.sources;
this.refresh();
return true;
};
HistoryDiffState.prototype.refresh = function () {
var output = this.result || [];
var content = '';
_.each(output, function (val) {
if (content.length > 0) {
content += '\n';
}
content += '/****** ' + val.lang + ' ******/\n';
content += val.source;
});
this.model.setValue(content);
};
function HistoryWidget() {
this.modal = null;
this.diffEditor = null;
this.lhs = null;
this.rhs = null;
this.currentList = [];
}
HistoryWidget.prototype.initializeIfNeeded = function () {
if (this.modal === null) {
this.modal = $('#history');
var placeholder = this.modal.find('.monaco-placeholder');
this.diffEditor = monaco.editor.createDiffEditor(placeholder[0], {
fontFamily: 'Consolas, "Liberation Mono", Courier, monospace',
scrollBeyondLastLine: true,
readOnly: true,
language: 'c++',
minimap: {
enabled: true,
},
});
this.lhs = new HistoryDiffState(monaco.editor.createModel('', 'c++'));
this.rhs = new HistoryDiffState(monaco.editor.createModel('', 'c++'));
this.diffEditor.setModel({ original: this.lhs.model, modified: this.rhs.model });
this.modal.find('.inline-diff-checkbox').click(_.bind(function (event) {
var inline = $(event.target).prop('checked');
this.diffEditor.updateOptions({
renderSideBySide: !inline,
});
this.resizeLayout();
}, this));
}
};
HistoryWidget.prototype.getLanguagesFromHistoryEntry = function (entry) {
return _.pluck(entry.sources, 'lang');
};
HistoryWidget.prototype.populateFromLocalStorage = function () {
this.currentList = History.sortedList();
this.populate(
this.modal.find('.historiccode'),
_.map(this.currentList, _.bind(function (data) {
var dt = new Date(data.dt);
var languages = this.getLanguagesFromHistoryEntry(data).join(', ');
return {
dt: data.dt,
name: dt.toString().replace(/\s\(.*\)/, '').concat(' (' + languages + ')'),
load: _.bind(function () {
this.onLoad(data);
this.modal.modal('hide');
}, this),
};
}, this)));
};
HistoryWidget.prototype.hideRadiosAndSetDiff = function () {
var root = this.modal.find('.historiccode');
var items = root.find('li:not(.template)');
var foundbase = false;
var foundcomp = false;
items.each(_.bind(function (idx, elem) {
var li = $(elem);
var dt = li.data('dt');
var base = li.find('.base');
var comp = li.find('.comp');
var baseShouldBeVisible = true;
var compShouldBeVisible = true;
if (comp.prop('checked')) {
foundcomp = true;
baseShouldBeVisible = false;
var itemRight = _.find(this.currentList, function (item) {
return (item.dt === dt);
});
this.rhs.update(itemRight);
} else if (base.prop('checked')) {
foundbase = true;
var itemLeft = _.find(this.currentList, function (item) {
return (item.dt === dt);
});
this.lhs.update(itemLeft);
}
if (foundbase && foundcomp) {
compShouldBeVisible = false;
} else if (!foundbase && !foundcomp) {
baseShouldBeVisible = false;
}
if (compShouldBeVisible) {
comp.css('visibility', '');
} else {
comp.css('visibility', 'hidden');
}
if (baseShouldBeVisible) {
base.css('visibility', '');
} else {
base.css('visibility', 'hidden');
}
}, this));
};
HistoryWidget.prototype.populate = function (root, list) {
root.find('li:not(.template)').remove();
var template = root.find('.template');
var baseMarked = false;
var compMarked = false;
_.each(list, _.bind(function (elem) {
var li = template
.clone()
.removeClass('template')
.appendTo(root);
li.data('dt', elem.dt);
var base = li.find('.base');
var comp = li.find('.comp');
if (!compMarked) {
comp.prop('checked', 'checked');
compMarked = true;
} else if (!baseMarked) {
base.prop('checked', 'checked');
baseMarked = true;
}
base.click(_.bind(this.hideRadiosAndSetDiff, this));
comp.click(_.bind(this.hideRadiosAndSetDiff, this));
li.find('a').text(elem.name).click(elem.load);
}, this));
this.hideRadiosAndSetDiff();
};
HistoryWidget.prototype.resizeLayout = function () {
var tabcontent = this.modal.find('div.tab-content');
this.diffEditor.layout({
width: tabcontent.width(),
height: tabcontent.height() - 20,
});
};
HistoryWidget.prototype.run = function (onLoad) {
this.initializeIfNeeded();
this.populateFromLocalStorage();
this.onLoad = onLoad;
this.modal.on('shown.bs.modal', _.bind(function () {
this.resizeLayout();
}, this));
this.modal.modal();
ga.proxy('send', {
hitType: 'event',
eventCategory: 'OpenModalPane',
eventAction: 'History',
});
};
module.exports = {
HistoryWidget: HistoryWidget,
};