kopia lustrzana https://github.com/c9/core
576 wiersze
21 KiB
JavaScript
576 wiersze
21 KiB
JavaScript
define(function(require, exports, module) {
|
|
main.consumes = [
|
|
"SCMPanel", "preferences", "settings", "panels", "Tree", "scm", "Menu",
|
|
"MenuItem", "tabManager", "c9", "util", "tabbehavior", "ui", "layout",
|
|
"scm.log"
|
|
];
|
|
main.provides = ["scm.detail"];
|
|
return main;
|
|
|
|
function main(options, imports, register) {
|
|
var SCMPanel = imports.SCMPanel;
|
|
var prefs = imports.preferences;
|
|
var settings = imports.settings;
|
|
var tabManager = imports.tabManager;
|
|
var panels = imports.panels;
|
|
var Tree = imports.Tree;
|
|
var scm = imports.scm;
|
|
var c9 = imports.c9;
|
|
var layout = imports.layout;
|
|
var ui = imports.ui;
|
|
var Menu = imports.Menu;
|
|
var MenuItem = imports.MenuItem;
|
|
var tabbehavior = imports.tabbehavior;
|
|
var util = imports.util;
|
|
var scmlog = imports["scm.log"];
|
|
|
|
// var async = require("async");
|
|
var basename = require("path").basename;
|
|
var dirname = require("path").dirname;
|
|
var escapeHTML = require("ace/lib/lang").escapeHTML;
|
|
|
|
/***** Initialization *****/
|
|
|
|
var plugin = new SCMPanel("Ajax.org", main.consumes, {
|
|
caption: "Test Results",
|
|
index: 100,
|
|
height: 250,
|
|
splitter: true
|
|
});
|
|
// var emit = plugin.getEmitter();
|
|
|
|
var workspaceDir = c9.workspaceDir;
|
|
|
|
var tree, menuContext, label;
|
|
var arrayCache = [];
|
|
|
|
function load() {
|
|
if (!scm.on) return;
|
|
|
|
scm.on("workspaceDir", function(options) {
|
|
workspaceDir = options.workspaceDir || c9.workspaceDir;
|
|
}, plugin);
|
|
|
|
panels.on("afterAnimate", function() {
|
|
if (panels.isActive("changes"))
|
|
tree && tree.resize();
|
|
});
|
|
|
|
// settings.on("read", function(){
|
|
// settings.setDefaults("user/test", [["collapsegroups", false]]);
|
|
// }, plugin);
|
|
|
|
// prefs.add({
|
|
// "Test" : {
|
|
// position: 1000,
|
|
// "Test Runner" : {
|
|
// position: 100,
|
|
// "Collapse Passed and Skipped Groups" : {
|
|
// type: "checkbox",
|
|
// position: 200,
|
|
// setting: "user/test/@collapsegroups"
|
|
// }
|
|
// }
|
|
// }
|
|
// }, plugin);
|
|
}
|
|
|
|
var drawn = false;
|
|
function draw(opts) {
|
|
if (drawn) return;
|
|
drawn = true;
|
|
|
|
opts.html.innerHTML = "<div class='detail-label'></div><div class='detail-tree'></div>";
|
|
opts.html.className = "detail-root top-test-panel";
|
|
label = opts.html.firstChild;
|
|
label.host = { textselect: true };
|
|
|
|
tree = new Tree({
|
|
container: opts.html.lastChild,
|
|
scrollMargin: [10, 0],
|
|
theme: "filetree",
|
|
enableDragdrop: true,
|
|
|
|
getIconHTML: function(node) {
|
|
var icon = node.isFolder ? "folder" : "status-icon-" + node.type;
|
|
if (node.parent == conflicts)
|
|
icon = "status-icon-conflict";
|
|
if (node.status === "loading") icon = "loading";
|
|
if (tree.model.twoWay && !node.isFolder)
|
|
icon += " clickable";
|
|
return "<span class='status-icon " + icon + "'>"
|
|
+ (node.type || "") + "</span>";
|
|
},
|
|
|
|
getCaptionHTML: function(node) {
|
|
if (node.path) {
|
|
var path = node.labelPath || node.path;
|
|
return basename(path)
|
|
+ "<span class='extrainfo'> - "
|
|
+ dirname(path) + "</span>";
|
|
}
|
|
return escapeHTML(node.label || node.name);
|
|
},
|
|
|
|
getRowIndent: function(node) {
|
|
return 0; //node.$depth ? node.$depth - 2 : 0;
|
|
},
|
|
|
|
isLoading: function() {},
|
|
|
|
getEmptyMessage: function() {
|
|
if (!this.keyword)
|
|
return this.isLoading()
|
|
? "Loading file list. One moment please..."
|
|
: "No files found.";
|
|
else
|
|
return "No files found that match '" + this.keyword + "'";
|
|
}
|
|
}, plugin);
|
|
|
|
tree.container.style.position = "absolute";
|
|
tree.container.style.left = "0";
|
|
tree.container.style.top = "0";
|
|
tree.container.style.right = "0";
|
|
tree.container.style.bottom = "0";
|
|
tree.container.style.height = "";
|
|
tree.renderer.scrollBarV.$minWidth = 10;
|
|
|
|
tree.commands.bindKey("Space", function(e) {
|
|
if (tabManager.previewTab)
|
|
tabManager.preview({ cancel: true });
|
|
else
|
|
openSelection({ preview: true });
|
|
});
|
|
|
|
tree.commands.bindKey("Enter", function(e) {
|
|
openSelection();
|
|
});
|
|
|
|
tree.commands.bindKey("Shift-Enter", function(e) {
|
|
openSelectedFiles();
|
|
});
|
|
|
|
layout.on("eachTheme", function(e) {
|
|
var height = parseInt(ui.getStyleRule(".filetree .tree-row", "height"), 10) || 22;
|
|
tree.rowHeightInner = height;
|
|
tree.rowHeight = height + 1;
|
|
if (e.changed)
|
|
tree.resize();
|
|
}, plugin);
|
|
|
|
tree.on("afterChoose", function(e) {
|
|
openSelection();
|
|
});
|
|
|
|
tree.on("userSelect", function(e) {
|
|
if (tabManager.previewTab)
|
|
openSelection({ preview: true });
|
|
});
|
|
|
|
tree.on("drop", function(e) {
|
|
if (e.target && e.selectedNodes) {
|
|
var nodes = e.selectedNodes;
|
|
if (e.target == staged) {
|
|
scm.addFileToStaging(nodes);
|
|
} else if (e.target == changed) {
|
|
scm.unstage(nodes);
|
|
}
|
|
}
|
|
});
|
|
|
|
tree.on("click", function(e) {
|
|
if (e.domEvent.target.classList.contains("status-icon")) {
|
|
var node = e.getNode();
|
|
if (node.parent == staged) {
|
|
scm.unstage(node);
|
|
} else if (node.parent == changed || node.parent == ignored) {
|
|
scm.addFileToStaging(node);
|
|
} else if (node.parent == conflicts) {
|
|
scm.addFileToStaging(node);
|
|
}
|
|
}
|
|
});
|
|
|
|
tree.setRoot(arrayCache);
|
|
|
|
// tree.on("focus", function(){
|
|
// test.focussedPanel = plugin;
|
|
// });
|
|
|
|
// settings.on("read", function(){
|
|
// test.settingsMenu.append(new MenuItem({
|
|
// caption: "Collapse Passed and Skipped Groups",
|
|
// checked: "user/test/@collapsegroups",
|
|
// type: "check",
|
|
// position: 300
|
|
// }));
|
|
// }, plugin);
|
|
|
|
// settings.on("user/test/@collapsegroups", function(value){
|
|
// if (plugin.visible) {
|
|
// skipNode.isOpen = !value;
|
|
// passNode.isOpen = !value;
|
|
// tree.refresh();
|
|
// }
|
|
// }, plugin);
|
|
|
|
scm.on("reload", function(options) {
|
|
reload(options || { hash: 0, force: true }, function(e, status) {
|
|
|
|
});
|
|
}, plugin);
|
|
|
|
scm.on("resize", function() {
|
|
tree && tree.resize();
|
|
});
|
|
|
|
scmlog.on("select", function(options) {
|
|
if (options) reload(options, function() {});
|
|
}, plugin);
|
|
|
|
// Context Menu
|
|
menuContext = new Menu({ items: [
|
|
new MenuItem({ match: "file", class: "strong", caption: "Open Diff", onclick: openSelection }, plugin),
|
|
new MenuItem({ match: "file", caption: "Open", onclick: openSelectedFiles }, plugin),
|
|
new MenuItem({ match: "file", caption: "Reveal in File Tree", onclick: reveal }, plugin),
|
|
]});
|
|
opts.aml.setAttribute("contextmenu", menuContext.aml);
|
|
|
|
reload({ hash: 0, force: true }, function() {});
|
|
}
|
|
|
|
/***** Methods *****/
|
|
|
|
var changed = {
|
|
label: "modified files",
|
|
className: "heading",
|
|
items: [],
|
|
isOpen: true,
|
|
isFolder: true,
|
|
noSelect: true,
|
|
$sorted: true
|
|
};
|
|
var staged = {
|
|
label: "files staged for commit",
|
|
className: "heading",
|
|
items: [],
|
|
isOpen: true,
|
|
isFolder: true,
|
|
noSelect: true,
|
|
$sorted: true
|
|
};
|
|
var ignored = {
|
|
label: "ignored files",
|
|
className: "heading",
|
|
items: [],
|
|
isOpen: false,
|
|
isFolder: true,
|
|
map: {},
|
|
noSelect: true,
|
|
$sorted: true
|
|
};
|
|
var untracked = {
|
|
label: "untracked files",
|
|
className: "heading",
|
|
items: [],
|
|
isOpen: false,
|
|
isFolder: true,
|
|
map: {},
|
|
noSelect: true,
|
|
$sorted: true
|
|
};
|
|
var conflicts = {
|
|
label: "conflicts",
|
|
className: "heading",
|
|
items: [],
|
|
isOpen: true,
|
|
isFolder: true,
|
|
noSelect: true,
|
|
$sorted: true
|
|
};
|
|
function reload(options, cb) {
|
|
if (!options) options = { hash: 0 };
|
|
if (!tree.meta.options) tree.meta.options = {};
|
|
if (!options.force)
|
|
if (tree.meta.options.hash == options.hash && tree.meta.options.base == options.base)
|
|
return;
|
|
|
|
scm.getStatus(options, function(e, status) {
|
|
var root = [];
|
|
var i, name, x;
|
|
var twoWay = options.twoWay;
|
|
|
|
status = (status || "").split("\x00");
|
|
console.log(status);
|
|
if (twoWay) {
|
|
status.shift();
|
|
changed.items = changed.children = [];
|
|
staged.items = staged.children = [];
|
|
ignored.items = ignored.children = [];
|
|
conflicts.items = conflicts.children = [];
|
|
untracked.items = untracked.children = [];
|
|
root = {
|
|
items: [changed, staged, untracked],
|
|
$sorted: true,
|
|
isFolder: true
|
|
};
|
|
for (i = 0; i < status.length; i++) {
|
|
x = status[i];
|
|
name = x.substr(twoWay ? 3 : 2);
|
|
if (!name) continue;
|
|
|
|
if (x[0] == "U" || x[1] == "U") {
|
|
conflicts.items.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[0] + x[1]
|
|
});
|
|
continue;
|
|
}
|
|
if (x[0] == "R") {
|
|
i++;
|
|
staged.items.push({
|
|
label: name,
|
|
path: name,
|
|
originalPath: status[i],
|
|
type: x[0]
|
|
});
|
|
}
|
|
else if (x[0] != " " && x[0] != "?") {
|
|
staged.items.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[0]
|
|
});
|
|
}
|
|
if (x[1] == "?") {
|
|
untracked.items.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[1],
|
|
isFolder: name.slice(-1) == "/"
|
|
});
|
|
}
|
|
if (x[1] == "!") {
|
|
ignored.items.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[1],
|
|
isFolder: name.slice(-1) == "/"
|
|
});
|
|
}
|
|
else if (x[1] != " ") {
|
|
changed.items.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[1]
|
|
});
|
|
}
|
|
}
|
|
if (ignored.items.length)
|
|
root.items.push(ignored);
|
|
if (conflicts.items.length)
|
|
root.items.unshift(conflicts);
|
|
label.style.display = "none";
|
|
} else {
|
|
for (i = 0; i < status.length; i += 2) {
|
|
x = status[i];
|
|
name = status[i + 1];
|
|
if (!name) continue;
|
|
|
|
if (x[0] == "R") {
|
|
i++;
|
|
root.push({
|
|
label: status[i + 1] + "(from " + name + ")",
|
|
path: name,
|
|
originalPath: status[i + 1],
|
|
type: x[0]
|
|
});
|
|
} else {
|
|
root.push({
|
|
label: name,
|
|
path: name,
|
|
type: x[0]
|
|
});
|
|
}
|
|
}
|
|
|
|
if (options.commit) {
|
|
label.innerHTML = "<span class='hash'>" + escapeHTML(options.hash) + "</span> "
|
|
+ "<span>" + escapeHTML(options.commit.authorname) + "</span>"
|
|
+ "<div>" + escapeHTML(options.commit.label) + "</div>";
|
|
} else {
|
|
label.innerHTML = "<span class='hash'>" + escapeHTML(options.hash) + "</span>"
|
|
+ " ... "
|
|
+ "<span class='hash'>" + escapeHTML(options.base) + "</span> ";
|
|
}
|
|
label.style.display = "block";
|
|
}
|
|
tree.setRoot(root);
|
|
tree.meta.options = options;
|
|
tree.model.twoWay = twoWay;
|
|
});
|
|
}
|
|
|
|
function reveal() {
|
|
var node = tree.selection.getCursor();
|
|
var path = node.path;
|
|
if (path) {
|
|
if (path[0] != "/") path = "/" + path;
|
|
path = workspaceDir + path;
|
|
path = util.normalizePath(path);
|
|
tabbehavior.revealtab({ path: path });
|
|
}
|
|
}
|
|
|
|
function openSelection(opts) {
|
|
if (!c9.has(c9.STORAGE))
|
|
return;
|
|
|
|
var node = tree.selectedNode;
|
|
if (!node || node.isFolder)
|
|
return;
|
|
|
|
if (node.parent == conflicts)
|
|
return openConflictView(node);
|
|
|
|
var options = tree.meta.options;
|
|
var oldPath = node.path;
|
|
var newPath = node.originalPath || node.path;
|
|
|
|
var hash = options.hash
|
|
? options.hash + ":"
|
|
: (node.parent == staged ? "STAGED:" : "MODIFIED:");
|
|
|
|
var base = options.base
|
|
? options.base + ":"
|
|
: (node.parent == staged ? "HEAD:" : "PREVIOUS:");
|
|
|
|
var diffview = {
|
|
oldPath: base + oldPath,
|
|
newPath: hash + newPath
|
|
};
|
|
|
|
var tab = findOpenDiffview(diffview);
|
|
if (tab && !(opts && opts.preview)) {
|
|
if (tab.document.meta.preview)
|
|
tabManager.preview({ cancel: true, keep: true });
|
|
else {
|
|
opts && opts.preview
|
|
? tabManager.activateTab(tab)
|
|
: tabManager.focusTab(tab);
|
|
}
|
|
return;
|
|
}
|
|
|
|
tabManager[opts && opts.preview ? "preview" : "open"]({
|
|
editorType: "diffview",
|
|
focus: true,
|
|
document: {
|
|
diffview: diffview
|
|
}
|
|
}, function() {});
|
|
}
|
|
|
|
function findOpenDiffview(options) {
|
|
var pages = tabManager.getTabs();
|
|
for (var i = 0, tab = pages[i]; tab; tab = pages[i++]) {
|
|
if (tab.editorType == "diffview") {
|
|
var session = tab.document.getSession();
|
|
if (session && session.oldPath == options.oldPath
|
|
&& session.newPath == options.newPath)
|
|
return tab;
|
|
}
|
|
}
|
|
}
|
|
|
|
function openConflictView(node) {
|
|
var addConflictMarker = require("../diff/conflictmarker");
|
|
var path = workspaceDir + "/" + node.path;
|
|
tabManager.open({ path: path, focus: true }, function(e, tab) {
|
|
addConflictMarker(tab.editor.ace);
|
|
});
|
|
}
|
|
|
|
function openSelectedFiles(opts) {
|
|
if (!c9.has(c9.STORAGE))
|
|
return;
|
|
|
|
var focus = opts && opts.focusNewTab || true;
|
|
var sel = tree.selection.getSelectedNodes();
|
|
var main = tree.selection.getCursor();
|
|
|
|
sel.forEach(function(node) {
|
|
if (!node || node.isFolder)
|
|
return;
|
|
|
|
var pane = tabManager.focussedTab && tabManager.focussedTab.pane;
|
|
if (tabManager.getPanes(tabManager.container).indexOf(pane) == -1)
|
|
pane = null;
|
|
|
|
tabManager.open({
|
|
path: workspaceDir + "/" + node.path,
|
|
pane: pane,
|
|
noanim: sel.length > 1,
|
|
active: node === main,
|
|
focus: node === main && focus
|
|
}, function() {});
|
|
});
|
|
}
|
|
|
|
/***** Lifecycle *****/
|
|
|
|
plugin.on("load", function() {
|
|
load();
|
|
});
|
|
plugin.on("draw", function(e) {
|
|
draw(e);
|
|
});
|
|
plugin.on("show", function(e) {
|
|
// txtFilter.focus();
|
|
// txtFilter.select();
|
|
});
|
|
plugin.on("hide", function(e) {
|
|
// Cancel Preview
|
|
// tabs.preview({ cancel: true });
|
|
});
|
|
plugin.on("unload", function() {
|
|
drawn = false;
|
|
});
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
* This is an example of an implementation of a plugin. Check out [the source](source/template.html)
|
|
* for more information.
|
|
*
|
|
* @class Template
|
|
* @extends Plugin
|
|
* @singleton
|
|
*/
|
|
plugin.freezePublicAPI({
|
|
/**
|
|
* @property {Object} The tree implementation
|
|
* @private
|
|
*/
|
|
get tree() { return tree; },
|
|
/**
|
|
*
|
|
*/
|
|
get changed() { return changed; },
|
|
/**
|
|
*
|
|
*/
|
|
get ignored() { return ignored; },
|
|
/**
|
|
*
|
|
*/
|
|
get staged() { return staged; }
|
|
});
|
|
|
|
register(null, {
|
|
"scm.detail": plugin
|
|
});
|
|
}
|
|
}); |