From 4d3d8bbca604d8a62f2f4017a3af57555f533336 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 2 Mar 2020 22:48:50 -0500 Subject: [PATCH 01/25] [WIP] Added Workspace Object --- js/explaingit.js | 14 +- js/workspace.js | 374 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 js/workspace.js diff --git a/js/explaingit.js b/js/explaingit.js index 8aa89d5..a3b9c77 100644 --- a/js/explaingit.js +++ b/js/explaingit.js @@ -1,4 +1,5 @@ -define(['historyview', 'controlbox', 'd3'], function(HistoryView, ControlBox, d3) { +define(['historyview', 'controlbox', 'workspace', 'd3'], function(HistoryView, +ControlBox, Workspace, d3) { var prefix = 'ExplainGit', openSandBoxes = [], open, @@ -44,12 +45,21 @@ define(['historyview', 'controlbox', 'd3'], function(HistoryView, ControlBox, d3 }); window.cb = controlBox; + workspace = new Workspace({ + historyView: historyView, + originView: originView, + undoHistory: args.undoHistory + }); + window.ws = workspace + controlBox.render(playground); historyView.render(playground); + workspace.render(playground); openSandBoxes.push({ hv: historyView, cb: controlBox, + ws: workspace, container: container }); }; @@ -59,6 +69,7 @@ define(['historyview', 'controlbox', 'd3'], function(HistoryView, ControlBox, d3 var osb = openSandBoxes[i]; osb.hv.destroy(); osb.cb.destroy(); + osb.ws.destroy(); osb.container.style('display', 'none'); } @@ -69,6 +80,7 @@ define(['historyview', 'controlbox', 'd3'], function(HistoryView, ControlBox, d3 explainGit = { HistoryView: HistoryView, ControlBox: ControlBox, + Workspace: Workspace, generateId: HistoryView.generateId, open: open, reset: reset diff --git a/js/workspace.js b/js/workspace.js new file mode 100644 index 0000000..fb70f25 --- /dev/null +++ b/js/workspace.js @@ -0,0 +1,374 @@ +define(['d3'], function() { + "use strict"; + + var REG_MARKER_END = 'url(#triangle)', + MERGE_MARKER_END = 'url(#brown-triangle)', + FADED_MARKER_END = 'url(#faded-triangle)', + + preventOverlap, + applyBranchlessClass, + cx, cy, fixCirclePosition, + px1, py1, fixPointerStartPosition, + px2, py2, fixPointerEndPosition, + fixIdPosition, tagY, getUniqueSetItems; + + preventOverlap = function preventOverlap(commit, view) { + var commitData = view.commitData, + baseLine = view.baseLine, + shift = view.commitRadius * 4.5, + overlapped = null; + + for (var i = 0; i < commitData.length; i++) { + var c = commitData[i]; + if (c.cx === commit.cx && c.cy === commit.cy && c !== commit) { + overlapped = c; + break; + } + } + + if (overlapped) { + var oParent = view.getCommit(overlapped.parent), + parent = view.getCommit(commit.parent); + + if (overlapped.cy < baseLine) { + overlapped = oParent.cy < parent.cy ? overlapped : commit; + overlapped.cy -= shift; + } else { + overlapped = oParent.cy > parent.cy ? overlapped : commit; + overlapped.cy += shift; + } + + preventOverlap(overlapped, view); + } + }; + + applyBranchlessClass = function(selection) { + if (selection.empty()) { + return; + } + + selection.classed('branchless', function(d) { + return d.branchless; + }); + + if (selection.classed('commit-pointer')) { + selection.attr('marker-end', function(d) { + return d.branchless ? FADED_MARKER_END : REG_MARKER_END; + }); + } else if (selection.classed('merge-pointer')) { + selection.attr('marker-end', function(d) { + return d.branchless ? FADED_MARKER_END : MERGE_MARKER_END; + }); + } + }; + + cx = function(commit, view) { + var parent = view.getCommit(commit.parent), + parentCX = parent.cx; + + if (typeof commit.parent2 === 'string') { + var parent2 = view.getCommit(commit.parent2); + + parentCX = parent.cx > parent2.cx ? parent.cx : parent2.cx; + } + + return parentCX + (view.commitRadius * 4.5); + }; + + cy = function(commit, view) { + var parent = view.getCommit(commit.parent), + parentCY = parent.cy || cy(parent, view), + baseLine = view.baseLine, + shift = view.commitRadius * 4.5, + branches = [], // count the existing branches + branchIndex = 0; + + for (var i = 0; i < view.commitData.length; i++) { + var d = view.commitData[i]; + + if (d.parent === commit.parent) { + branches.push(d.id); + } + } + + branchIndex = branches.indexOf(commit.id); + + if (commit.isNoFFBranch === true) { + branchIndex++; + } + if (commit.isNoFFCommit === true) { + branchIndex--; + } + + if (parentCY === baseLine) { + var direction = 1; + for (var bi = 0; bi < branchIndex; bi++) { + direction *= -1; + } + + shift *= Math.ceil(branchIndex / 2); + + return parentCY + (shift * direction); + } + + if (parentCY < baseLine) { + return parentCY - (shift * branchIndex); + } else if (parentCY > baseLine) { + return parentCY + (shift * branchIndex); + } + }; + + fixCirclePosition = function(selection) { + selection + .attr('cx', function(d) { + return d.cx; + }) + .attr('cy', function(d) { + return d.cy; + }); + }; + + // calculates the x1 point for commit pointer lines + px1 = function(commit, view, pp) { + pp = pp || 'parent'; + + var parent = view.getCommit(commit[pp]), + startCX = commit.cx, + diffX = startCX - parent.cx, + diffY = parent.cy - commit.cy, + length = Math.sqrt((diffX * diffX) + (diffY * diffY)); + + return startCX - (view.pointerMargin * (diffX / length)); + }; + + // calculates the y1 point for commit pointer lines + py1 = function(commit, view, pp) { + pp = pp || 'parent'; + + var parent = view.getCommit(commit[pp]), + startCY = commit.cy, + diffX = commit.cx - parent.cx, + diffY = parent.cy - startCY, + length = Math.sqrt((diffX * diffX) + (diffY * diffY)); + + return startCY + (view.pointerMargin * (diffY / length)); + }; + + fixPointerStartPosition = function(selection, view) { + selection.attr('x1', function(d) { + return px1(d, view); + }).attr('y1', function(d) { + return py1(d, view); + }); + }; + + px2 = function(commit, view, pp) { + pp = pp || 'parent'; + + var parent = view.getCommit(commit[pp]), + endCX = parent.cx, + diffX = commit.cx - endCX, + diffY = parent.cy - commit.cy, + length = Math.sqrt((diffX * diffX) + (diffY * diffY)); + + return endCX + (view.pointerMargin * 1.2 * (diffX / length)); + }; + + py2 = function(commit, view, pp) { + pp = pp || 'parent'; + + var parent = view.getCommit(commit[pp]), + endCY = parent.cy, + diffX = commit.cx - parent.cx, + diffY = endCY - commit.cy, + length = Math.sqrt((diffX * diffX) + (diffY * diffY)); + + return endCY - (view.pointerMargin * 1.2 * (diffY / length)); + }; + + fixPointerEndPosition = function(selection, view) { + selection.attr('x2', function(d) { + return px2(d, view); + }).attr('y2', function(d) { + return py2(d, view); + }); + }; + + fixIdPosition = function(selection, view, delta) { + selection.attr('x', function(d) { + return d.cx; + }).attr('y', function(d) { + return d.cy + view.commitRadius + delta; + }); + }; + + tagY = function tagY(t, view) { + var commit = view.getCommit(t.commit), + commitCY = commit.cy, + tags = commit.tags, + tagIndex = tags.indexOf(t.name); + + if (tagIndex === -1) { + tagIndex = tags.length; + } + + if (commitCY < (view.baseLine)) { + return commitCY - 45 - (tagIndex * 25); + } else { + return commitCY + 50 + (tagIndex * 25); + } + }; + + getUniqueSetItems = function(set1, set2) { + var uniqueSet1 = JSON.parse(JSON.stringify(set1)) + var uniqueSet2 = JSON.parse(JSON.stringify(set2)) + for (var id in set1) { + delete uniqueSet2[id] + } + for (var id in set2) { + delete uniqueSet1[id] + } + return [uniqueSet1, uniqueSet2] + }; + + /** + * @class Workspace + * @constructor + */ + function Workspace(config) { + this.historyView = config.historyView; + this.originView = config.originView; + } + + Workspace.prototype = { + /** + * @method render + * @param container {String} selector for the container to render the SVG into + */ + render: function(container) { + var svgContainer, svg, curr_ws, stash, index; + + svgContainer = container.select('svg-container'); + + svg = svgContainer.append('svg:svg'); + + svg.attr('id', this.name) + .attr('width', this.width) + .attr('height', this.isRemote ? this.height + 150 : this.height); + + stash = svg.append('svg:g').classed('stash', true) + stash.append('svg:rect') + .attr('width', 100) + .attr('height', 100) + .attr('x', 100) + .attr('y', 200) + .attr('fill', 'blue') + .attr('stroke', 'red'); + + curr_ws = svg.append('svg:g').classed('curr_ws', true) + curr_ws.append('svg:rect') + .attr('width', 100) + .attr('height', 100) + .attr('x', 100) + .attr('y', 200) + .attr('fill', 'red') + .attr('stroke', 'blue'); + + index = svg.append('svg:g').classed('index', true) + index.append('svg:rect') + .attr('width', 100) + .attr('height', 100) + .attr('x', 100) + .attr('y', 200) + .attr('rx', 20) + .attr('ry', 20) + .attr('fill', 'blue') + .attr('stroke', 'red'); + this.svgContainer = svgContainer; + this.svg = svg; + this.curr_ws = curr_ws; + this.stash = stash + this.index = index + //this.arrowBox = svg.append('svg:g').classed('pointers', true); + //this.commitBox = svg.append('svg:g').classed('commits', true); + //this.tagBox = svg.append('svg:g').classed('tags', true); + + //this.renderCommits(); + + //this._setCurrentBranch(this.currentBranch); + }, + + destroy: function() { + this.svg.remove(); + this.svgContainer.remove(); + clearInterval(this.refreshSizeTimer); + + for (var prop in this) { + if (this.hasOwnProperty(prop)) { + this[prop] = null; + } + } + }, + + _calculatePositionData: function() { + for (var i = 0; i < this.commitData.length; i++) { + var commit = this.commitData[i]; + commit.cx = cx(commit, this); + commit.cy = cy(commit, this); + preventOverlap(commit, this); + } + }, + + _resizeSvg: function() { + var ele = document.getElementById(this.svg.node().id); + var container = ele.parentNode; + var currentWidth = ele.offsetWidth; + var newWidth; + + if (ele.getBBox().width > container.offsetWidth) + newWidth = Math.round(ele.getBBox().width); + else + newWidth = container.offsetWidth - 5; + + if (currentWidth != newWidth) { + this.svg.attr('width', newWidth); + container.scrollLeft = container.scrollWidth; + } + }, + + _renderIdLabels: function() { + this._renderText('id-label', function(d) { + return d.id + '..'; + }, 14); + this._renderText('message-label', function(d) { + return d.message; + }, 24); + }, + + _renderText: function(className, getText, delta) { + var view = this, + existingTexts, + newtexts; + + existingTexts = this.commitBox.selectAll('text.' + className) + .data(this.commitData, function(d) { + return d.id; + }) + .text(getText); + + existingTexts.transition().call(fixIdPosition, view, delta); + + newtexts = existingTexts.enter() + .insert('svg:text', ':first-child') + .classed(className, true) + .text(getText) + .call(fixIdPosition, view, delta); + + existingTexts.exit() + .remove() + }, + + }; + + return Workspace; +}); From 7085925f03299e759287a2fa1bc0fc288b5a6b0c Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Tue, 3 Mar 2020 22:15:16 -0500 Subject: [PATCH 02/25] Got 3 boxes for Stash, CurrWs, and Index --- css/explaingit.css | 27 ++++++++++++++++++++ index.html | 6 ++--- js/controlbox.js | 6 +++++ js/explaingit.js | 5 +++- js/historyview.js | 3 +++ js/workspace.js | 61 +++++++++++++++++++++++++++------------------- 6 files changed, 79 insertions(+), 29 deletions(-) diff --git a/css/explaingit.css b/css/explaingit.css index 13f9b22..4ea9e4e 100644 --- a/css/explaingit.css +++ b/css/explaingit.css @@ -114,6 +114,17 @@ span.cmd { left: 20px; } +#ExplainGitZen-Container .ws-container { + display: inline-block; + border: 1px dotted #AAA; + position: absolute; + top: 500px; + bottom: 0; + right: 0; + left: 250px; + margin-left: 0; +} + .remote-name-display { font-weight: bold; text-align: right; @@ -285,6 +296,22 @@ text.message-label { font-size: 10px; } +g.stash > rect { + fill: #FFCC66; + stroke: #CC9900; + stroke-width: 2; +} + +g.curr-ws > rect { + fill: #7FC9FF; + stroke: #0026FF; +} + +g.index > rect { + fill: #CCC; + stroke: #888; +} + g.branch-tag > rect { fill: #FFCC66; stroke: #CC9900; diff --git a/index.html b/index.html index a87e584..d75e97f 100644 --- a/index.html +++ b/index.html @@ -109,9 +109,9 @@ explainGit.reset(); var savedState = null - if (window.localStorage) { - savedState = JSON.parse(window.localStorage.getItem('git-viz-snapshot') || 'null') - } + //if (window.localStorage) { + // savedState = JSON.parse(window.localStorage.getItem('git-viz-snapshot') || 'null') + //} var initial = Object.assign(copyDemo(lastDemo), { name: 'Zen', diff --git a/js/controlbox.js b/js/controlbox.js index c9761bf..37dcf61 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -915,6 +915,12 @@ function(_yargs, d3, demos) { this.info("Real git reflog supports the '" + subcommand + "' subcommand but this tool only supports 'show' and 'exists'") } + }, + + add: function(args) { + // Create boxes to visualize working tree, index, stash + console.log("in add") + return } }; diff --git a/js/explaingit.js b/js/explaingit.js index a3b9c77..e4f43c0 100644 --- a/js/explaingit.js +++ b/js/explaingit.js @@ -48,7 +48,10 @@ ControlBox, Workspace, d3) { workspace = new Workspace({ historyView: historyView, originView: originView, - undoHistory: args.undoHistory + undoHistory: args.undoHistory, + name: name + '-Workspace', + width: 300, + height: 400 }); window.ws = workspace diff --git a/js/historyview.js b/js/historyview.js index 7687ac1..44293de 100644 --- a/js/historyview.js +++ b/js/historyview.js @@ -530,6 +530,9 @@ define(['d3'], function() { .attr('width', this.width) .attr('height', this.isRemote ? this.height + 150 : this.height); + console.log(this.width); + console.log(this.height); + if (this.isRemote) { svg.append('svg:text') .classed('remote-name-display', true) diff --git a/js/workspace.js b/js/workspace.js index fb70f25..623fbd3 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -238,6 +238,11 @@ define(['d3'], function() { function Workspace(config) { this.historyView = config.historyView; this.originView = config.originView; + this.name = config.name || 'UnnamedWorkspace'; + this.width = config.width; + this.height = config.height || 400; + //this.width = this.historyView.width; + //this.height = this.historyView.height || 400; } Workspace.prototype = { @@ -248,42 +253,48 @@ define(['d3'], function() { render: function(container) { var svgContainer, svg, curr_ws, stash, index; - svgContainer = container.select('svg-container'); + //svgContainer = container.select('svg-container'); + svgContainer = container.append('div') + .classed('ws-container', true); svg = svgContainer.append('svg:svg'); svg.attr('id', this.name) - .attr('width', this.width) - .attr('height', this.isRemote ? this.height + 150 : this.height); + .attr('width', "100%") + .attr('height', "100%"); + //.attr('width', this.width) + //.attr('height', this.height); stash = svg.append('svg:g').classed('stash', true) + stash.append('svg:text') + .classed('workspace-label', true) + .text('Stash'); stash.append('svg:rect') - .attr('width', 100) - .attr('height', 100) - .attr('x', 100) - .attr('y', 200) - .attr('fill', 'blue') - .attr('stroke', 'red'); - - curr_ws = svg.append('svg:g').classed('curr_ws', true) + .attr('width', "31%") + .attr('height', "100%") + .attr('x', 0) + .attr('y', 0); + + curr_ws = svg.append('svg:g').classed('curr-ws', true) + curr_ws.append('svg:text') + .classed('workspace-label', true) + .text('Workspace'); curr_ws.append('svg:rect') - .attr('width', 100) - .attr('height', 100) - .attr('x', 100) - .attr('y', 200) - .attr('fill', 'red') - .attr('stroke', 'blue'); + .attr('width', "31%") + .attr('height', "100%") + .attr('x', this.width/3) + .attr('y', 0); index = svg.append('svg:g').classed('index', true) + index.append('svg:text') + .classed('workspace-label', true) + .text('Index'); index.append('svg:rect') - .attr('width', 100) - .attr('height', 100) - .attr('x', 100) - .attr('y', 200) - .attr('rx', 20) - .attr('ry', 20) - .attr('fill', 'blue') - .attr('stroke', 'red'); + .attr('width', "31%") + .attr('height', "100%") + .attr('x', 2 * this.width/3) + .attr('y', 0); + this.svgContainer = svgContainer; this.svg = svg; this.curr_ws = curr_ws; From 329931d16d6814341ade5c0b95e315ba8a3e3198 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 28 Mar 2020 18:34:58 -0400 Subject: [PATCH 03/25] Added basic blob rendering --- css/explaingit.css | 5 ++ js/controlbox.js | 29 +++++++++- js/explaingit.js | 17 +++--- js/workspace.js | 130 +++++++++++++++++++++++++++++++++++---------- 4 files changed, 145 insertions(+), 36 deletions(-) diff --git a/css/explaingit.css b/css/explaingit.css index 4ea9e4e..564b95a 100644 --- a/css/explaingit.css +++ b/css/explaingit.css @@ -312,6 +312,11 @@ g.index > rect { stroke: #888; } +g.blob-space > rect { + fill: #8ce08c; + stroke: #339900; +} + g.branch-tag > rect { fill: #FFCC66; stroke: #CC9900; diff --git a/js/controlbox.js b/js/controlbox.js index 37dcf61..ea274d5 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -20,6 +20,7 @@ function(_yargs, d3, demos) { function ControlBox(config) { this.historyView = config.historyView; this.originView = config.originView; + this.workspace = config.workspace; this.initialMessage = config.initialMessage || 'Enter git commands below.'; this._commandHistory = []; this._currentCommand = -1; @@ -919,7 +920,33 @@ function(_yargs, d3, demos) { add: function(args) { // Create boxes to visualize working tree, index, stash - console.log("in add") + console.log("in add"); + var workspace = this.workspace; + + console.log(workspace); + workspace.addBlob(workspace.curr_ws, workspace.index, true); + + + return + }, + + stash: function(args) { + // Create boxes to visualize working tree, index, stash + console.log("in stash"); + var workspace = this.workspace; + + console.log(workspace); + workspace.addBlob(workspace.curr_ws, workspace.stash, true); + return + }, + + edit: function(args) { + // Create boxes to visualize working tree, index, stash + console.log("in edit"); + var workspace = this.workspace; + + console.log(workspace); + workspace.addBlob(null, workspace.curr_ws); return } }; diff --git a/js/explaingit.js b/js/explaingit.js index e4f43c0..bd4e3b6 100644 --- a/js/explaingit.js +++ b/js/explaingit.js @@ -37,14 +37,6 @@ ControlBox, Workspace, d3) { window.ov = originView; } - controlBox = new ControlBox({ - historyView: historyView, - originView: originView, - initialMessage: args.initialMessage, - undoHistory: args.undoHistory - }); - window.cb = controlBox; - workspace = new Workspace({ historyView: historyView, originView: originView, @@ -55,6 +47,15 @@ ControlBox, Workspace, d3) { }); window.ws = workspace + controlBox = new ControlBox({ + historyView: historyView, + originView: originView, + workspace: workspace, + initialMessage: args.initialMessage, + undoHistory: args.undoHistory + }); + window.cb = controlBox; + controlBox.render(playground); historyView.render(playground); workspace.render(playground); diff --git a/js/workspace.js b/js/workspace.js index 623fbd3..9e55f5e 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -1,4 +1,4 @@ -define(['d3'], function() { +define(['historyview', 'd3'], function(HistoryView) { "use strict"; var REG_MARKER_END = 'url(#triangle)', @@ -203,20 +203,13 @@ define(['d3'], function() { }; tagY = function tagY(t, view) { - var commit = view.getCommit(t.commit), - commitCY = commit.cy, - tags = commit.tags, - tagIndex = tags.indexOf(t.name); + var blobs = view.getBlobs, + blobIndex = blobs.indexOf(t.blob); - if (tagIndex === -1) { - tagIndex = tags.length; - } - - if (commitCY < (view.baseLine)) { - return commitCY - 45 - (tagIndex * 25); - } else { - return commitCY + 50 + (tagIndex * 25); + if (blobIndex === -1) { + blobIndex = blobs.length; } + return t.blob.y - 45 - (blobIndex * 25); }; getUniqueSetItems = function(set1, set2) { @@ -264,47 +257,66 @@ define(['d3'], function() { .attr('height', "100%"); //.attr('width', this.width) //.attr('height', this.height); + var labelX = 15; + var labelY = 25; + - stash = svg.append('svg:g').classed('stash', true) - stash.append('svg:text') - .classed('workspace-label', true) - .text('Stash'); + stash = svg.append('svg:g').classed('stash', true).attr('id', 'stash') stash.append('svg:rect') .attr('width', "31%") .attr('height', "100%") .attr('x', 0) .attr('y', 0); + stash.append('svg:text') + .classed('workspace-label', true) + .text('Stash') + .attr('x', labelX) + .attr('y', labelY); + stash.append('svg:g').classed('blob-space', true).attr('id', 'stash.blob-space'); curr_ws = svg.append('svg:g').classed('curr-ws', true) - curr_ws.append('svg:text') - .classed('workspace-label', true) - .text('Workspace'); + .attr('id', 'curr_ws') + .attr('transform', 'translate(750, 0)'); curr_ws.append('svg:rect') .attr('width', "31%") .attr('height', "100%") - .attr('x', this.width/3) + .attr('x', 0) .attr('y', 0); + curr_ws.append('svg:text') + .classed('workspace-label', true) + .text('Workspace') + .attr('x', labelX) + .attr('y', labelY); + curr_ws.append('svg:g').classed('blob-space', true).attr('id', 'curr_ws.blob-space'); index = svg.append('svg:g').classed('index', true) - index.append('svg:text') - .classed('workspace-label', true) - .text('Index'); + .attr('id', 'index') + .attr('transform', 'translate(1500, 0)'); index.append('svg:rect') .attr('width', "31%") .attr('height', "100%") - .attr('x', 2 * this.width/3) - .attr('y', 0); + .attr('x', 0) + .attr('y', 0); + index.append('svg:text') + .classed('workspace-label', true) + .text('Index') + .attr('x', labelX) + .attr('y', labelY); + index.append('svg:g').classed('blob-space', true).attr('id', 'index.blob-space'); this.svgContainer = svgContainer; this.svg = svg; this.curr_ws = curr_ws; + this.curr_ws.blobs = this.curr_ws.blobs || [] this.stash = stash + this.stash.blobs = this.stash.blobs || [] this.index = index + this.index.blobs = this.index.blobs || [] //this.arrowBox = svg.append('svg:g').classed('pointers', true); //this.commitBox = svg.append('svg:g').classed('commits', true); //this.tagBox = svg.append('svg:g').classed('tags', true); - //this.renderCommits(); + this.renderBlobs(); //this._setCurrentBranch(this.currentBranch); }, @@ -321,6 +333,42 @@ define(['d3'], function() { } }, + addNewBlob: function(ws) { + console.log("adding new blob to " + ws); + if (ws.blobs === undefined || !ws.blobs) { + ws.blobs = []; + } + ws.blobs.push(HistoryView.generateId()); + console.log(ws.blobs); + }, + + addBlob: function(src, dst, moveAll = false) { + if (src === null) { + // Adding a brand new blob + this.addNewBlob(dst); + } else { + // Moving an existing blob from 'src' to 'dst' + if (src.blobs === undefined || src.blobs.length == 0) { + console.log("no blobs to move"); + } else if (moveAll) { + dst.blobs = src.blobs; + src.blobs = []; + console.log("Moving all blobs"); + } else { + if (dst.blobs === undefined) { + dst.blobs = []; + } + dst.blobs.push(src.blobs.pop()); + console.log("Moving top blob"); + } + console.log("src:"); + console.log(src.blobs); + console.log("dst:"); + console.log(dst.blobs); + } + this.renderBlobs(); + }, + _calculatePositionData: function() { for (var i = 0; i < this.commitData.length; i++) { var commit = this.commitData[i]; @@ -347,6 +395,34 @@ define(['d3'], function() { } }, + renderBlobs: function() { + var view = this, + existingBlobs, + newBlobs, + curr_workspace = this.stash, + workspaces = [this.stash, this.curr_ws, this.index]; + console.log("rendering blobs"); + + workspaces.forEach(function(ws) { + console.log(ws.blobs); + // Bind the data + var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); + // Enter + blob_rect.enter().append("svg:rect") + .attr("width", function(d) { console.log(d); return 200;}) + .attr("height", 75) + .attr("fill", "blue") + .attr("id", function(d) { return "blob-" + d; }) + .classed("rendered-blob", true); + // Update + blob_rect + .attr("x", 50) + .attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); + // Remove + blob_rect.exit().remove(); + }); + }, + _renderIdLabels: function() { this._renderText('id-label', function(d) { return d.id + '..'; From a45f61ad7413a305192b6dc69d6c482f39b6ba35 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 28 Mar 2020 21:24:24 -0400 Subject: [PATCH 04/25] Render stash and index as changesets --- js/workspace.js | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/js/workspace.js b/js/workspace.js index 9e55f5e..6060dca 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -307,10 +307,13 @@ define(['historyview', 'd3'], function(HistoryView) { this.svgContainer = svgContainer; this.svg = svg; this.curr_ws = curr_ws; + this.curr_ws.name = "workspace" this.curr_ws.blobs = this.curr_ws.blobs || [] this.stash = stash + this.stash.name = "stash" this.stash.blobs = this.stash.blobs || [] this.index = index + this.index.name = "index" this.index.blobs = this.index.blobs || [] //this.arrowBox = svg.append('svg:g').classed('pointers', true); //this.commitBox = svg.append('svg:g').classed('commits', true); @@ -351,9 +354,13 @@ define(['historyview', 'd3'], function(HistoryView) { if (src.blobs === undefined || src.blobs.length == 0) { console.log("no blobs to move"); } else if (moveAll) { - dst.blobs = src.blobs; - src.blobs = []; - console.log("Moving all blobs"); + if (dst.name === "stash" || dst.name == "index") { + dst.blobs.push(src.blobs); + } else { + dst.blobs = src.blobs; + } + src.blobs = []; + console.log("Moving all blobs"); } else { if (dst.blobs === undefined) { dst.blobs = []; @@ -361,10 +368,6 @@ define(['historyview', 'd3'], function(HistoryView) { dst.blobs.push(src.blobs.pop()); console.log("Moving top blob"); } - console.log("src:"); - console.log(src.blobs); - console.log("dst:"); - console.log(dst.blobs); } this.renderBlobs(); }, @@ -400,10 +403,12 @@ define(['historyview', 'd3'], function(HistoryView) { existingBlobs, newBlobs, curr_workspace = this.stash, - workspaces = [this.stash, this.curr_ws, this.index]; + workspaces = [this.curr_ws], + changeset_workspaces = [this.stash, this.index]; console.log("rendering blobs"); workspaces.forEach(function(ws) { + console.log(ws.name); console.log(ws.blobs); // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); @@ -411,7 +416,6 @@ define(['historyview', 'd3'], function(HistoryView) { blob_rect.enter().append("svg:rect") .attr("width", function(d) { console.log(d); return 200;}) .attr("height", 75) - .attr("fill", "blue") .attr("id", function(d) { return "blob-" + d; }) .classed("rendered-blob", true); // Update @@ -421,6 +425,24 @@ define(['historyview', 'd3'], function(HistoryView) { // Remove blob_rect.exit().remove(); }); + changeset_workspaces.forEach(function(ws) { + console.log(ws.name); + console.log(ws.blobs); + // Bind the data + var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); + // Enter + blob_rect.enter().append("svg:rect") + .attr("width", function(d) { console.log(d); return 200;}) + .attr("height", 75) + .attr("id", function(d) { return "changeset-" + d; }) + .classed("rendered-changeset", true); + // Update + blob_rect + .attr("x", 50) + .attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); + // Remove + blob_rect.exit().remove(); + }); }, _renderIdLabels: function() { From a413c3847c8822753b262fc3231025ace24b89e3 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 19:01:36 -0400 Subject: [PATCH 05/25] Treat 'stash' as a stack --- js/controlbox.js | 11 +++-- js/workspace.js | 113 ++++++++++++++++++++++++++++++----------------- 2 files changed, 77 insertions(+), 47 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index ea274d5..7e71c65 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -923,10 +923,7 @@ function(_yargs, d3, demos) { console.log("in add"); var workspace = this.workspace; - console.log(workspace); workspace.addBlob(workspace.curr_ws, workspace.index, true); - - return }, @@ -934,9 +931,12 @@ function(_yargs, d3, demos) { // Create boxes to visualize working tree, index, stash console.log("in stash"); var workspace = this.workspace; + if (args && args[0] === "pop") { + workspace.addBlob(workspace.stash, workspace.curr_ws); + } else { + workspace.addBlob(workspace.curr_ws, workspace.stash, true); + } - console.log(workspace); - workspace.addBlob(workspace.curr_ws, workspace.stash, true); return }, @@ -945,7 +945,6 @@ function(_yargs, d3, demos) { console.log("in edit"); var workspace = this.workspace; - console.log(workspace); workspace.addBlob(null, workspace.curr_ws); return } diff --git a/js/workspace.js b/js/workspace.js index 6060dca..ac473ae 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -7,7 +7,7 @@ define(['historyview', 'd3'], function(HistoryView) { preventOverlap, applyBranchlessClass, - cx, cy, fixCirclePosition, + cx, cy, fixBlobPosition, px1, py1, fixPointerStartPosition, px2, py2, fixPointerEndPosition, fixIdPosition, tagY, getUniqueSetItems; @@ -118,13 +118,13 @@ define(['historyview', 'd3'], function(HistoryView) { } }; - fixCirclePosition = function(selection) { + fixBlobPosition = function(selection) { selection - .attr('cx', function(d) { - return d.cx; + .attr('x', function(d) { + return d.x; }) - .attr('cy', function(d) { - return d.cy; + .attr('y', function(d) { + return d.y; }); }; @@ -196,9 +196,9 @@ define(['historyview', 'd3'], function(HistoryView) { fixIdPosition = function(selection, view, delta) { selection.attr('x', function(d) { - return d.cx; + return d.x + view.blob_width / 2; }).attr('y', function(d) { - return d.cy + view.commitRadius + delta; + return d.y + view.blob_height + delta; }); }; @@ -236,6 +236,8 @@ define(['historyview', 'd3'], function(HistoryView) { this.height = config.height || 400; //this.width = this.historyView.width; //this.height = this.historyView.height || 400; + this.blob_height = config.blob_height || 75; + this.blob_width = config.blob_height || 200; } Workspace.prototype = { @@ -337,11 +339,12 @@ define(['historyview', 'd3'], function(HistoryView) { }, addNewBlob: function(ws) { - console.log("adding new blob to " + ws); + console.log("adding new blob to " + ws.name); if (ws.blobs === undefined || !ws.blobs) { ws.blobs = []; } - ws.blobs.push(HistoryView.generateId()); + var blob = {'id': HistoryView.generateId(), 'x': 50, 'y': 50} + ws.blobs.push(blob); console.log(ws.blobs); }, @@ -354,8 +357,9 @@ define(['historyview', 'd3'], function(HistoryView) { if (src.blobs === undefined || src.blobs.length == 0) { console.log("no blobs to move"); } else if (moveAll) { - if (dst.name === "stash" || dst.name == "index") { - dst.blobs.push(src.blobs); + if (dst.name === "stash") { + // stash is treated like a stack of changesets (group of blobs) + dst.blobs.unshift(src.blobs); } else { dst.blobs = src.blobs; } @@ -365,19 +369,28 @@ define(['historyview', 'd3'], function(HistoryView) { if (dst.blobs === undefined) { dst.blobs = []; } - dst.blobs.push(src.blobs.pop()); + if (src.name == "stash") { + var top_blob = src.blobs.shift(); + } else { + var top_blob = src.blobs.pop(); + } + if (Array.isArray(top_blob)) { + dst.blobs = dst.blobs.concat(top_blob); + } else { + dst.blobs.push(top_blob); + } console.log("Moving top blob"); } } this.renderBlobs(); }, - _calculatePositionData: function() { - for (var i = 0; i < this.commitData.length; i++) { - var commit = this.commitData[i]; - commit.cx = cx(commit, this); - commit.cy = cy(commit, this); - preventOverlap(commit, this); + _calculatePositionData: function(blobs) { + for (var i = 0; i < blobs.length; i++) { + var blob = blobs[i]; + blob.x = 50; + blob.y = 50 + i * 125; + //preventOverlap(commit, this); } }, @@ -403,8 +416,8 @@ define(['historyview', 'd3'], function(HistoryView) { existingBlobs, newBlobs, curr_workspace = this.stash, - workspaces = [this.curr_ws], - changeset_workspaces = [this.stash, this.index]; + workspaces = [this.curr_ws, this.index], + changeset_workspaces = [this.stash]; console.log("rendering blobs"); workspaces.forEach(function(ws) { @@ -414,16 +427,21 @@ define(['historyview', 'd3'], function(HistoryView) { var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter blob_rect.enter().append("svg:rect") - .attr("width", function(d) { console.log(d); return 200;}) - .attr("height", 75) - .attr("id", function(d) { return "blob-" + d; }) + .attr("width", function(d) { console.log(d); return view.blob_width;}) + .attr("height", view.blob_height) + .attr("id", function(d) { return "blob-" + d.id; }) .classed("rendered-blob", true); // Update - blob_rect - .attr("x", 50) - .attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); + view._calculatePositionData(ws.blobs); + blob_rect.transition() + .duration(500) + .call(fixBlobPosition); + //blob_rect + //.attr("x", 50) + //.attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); // Remove blob_rect.exit().remove(); + view._renderIdLabels(ws); }); changeset_workspaces.forEach(function(ws) { console.log(ws.name); @@ -432,37 +450,50 @@ define(['historyview', 'd3'], function(HistoryView) { var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter blob_rect.enter().append("svg:rect") - .attr("width", function(d) { console.log(d); return 200;}) - .attr("height", 75) + .attr("width", function(d) { console.log(d); return view.blob_width;}) + .attr("height", view.blob_height) .attr("id", function(d) { return "changeset-" + d; }) .classed("rendered-changeset", true); // Update - blob_rect - .attr("x", 50) - .attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); + view._calculatePositionData(ws.blobs); + blob_rect.transition() + .duration(500) + .call(fixBlobPosition); + //blob_rect + //.attr("x", 50) + //.attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); // Remove blob_rect.exit().remove(); + view._renderIdLabels(ws); }); }, - _renderIdLabels: function() { - this._renderText('id-label', function(d) { + _renderIdLabels: function(ws) { + this._renderText(ws, 'id-label', function(d) { + if (Array.isArray(d)) { + var ret_str = ""; + d.forEach( function(blob) { + ret_str += blob.id + ','; + }); + return ret_str.substr(0, 16); + } return d.id + '..'; }, 14); - this._renderText('message-label', function(d) { - return d.message; + this._renderText(ws, 'message-label', function(d) { + if (ws.name === "stash") { + return "{" + ws.blobs.indexOf(d) + "}"; + } + return "filename"; }, 24); }, - _renderText: function(className, getText, delta) { + _renderText: function(ws, className, getText, delta) { var view = this, existingTexts, newtexts; - existingTexts = this.commitBox.selectAll('text.' + className) - .data(this.commitData, function(d) { - return d.id; - }) + existingTexts = ws.select("g.blob-space").selectAll('text.' + className) + .data(ws.blobs) .text(getText); existingTexts.transition().call(fixIdPosition, view, delta); From 37db6ea93127f7ebc2e334c19a2cf891fea99e94 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 19:31:38 -0400 Subject: [PATCH 06/25] Added 'git stash drop' --- js/controlbox.js | 6 ++++++ js/workspace.js | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/js/controlbox.js b/js/controlbox.js index 7e71c65..7026ba7 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -933,6 +933,12 @@ function(_yargs, d3, demos) { var workspace = this.workspace; if (args && args[0] === "pop") { workspace.addBlob(workspace.stash, workspace.curr_ws); + } else if (args && args[0] === "drop") { + if (args[1] != undefined) { + workspace.removeBlob(workspace.stash, args[1]); + } else { + console.log("Invalid stash to drop"); + } } else { workspace.addBlob(workspace.curr_ws, workspace.stash, true); } diff --git a/js/workspace.js b/js/workspace.js index ac473ae..98261b5 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -385,6 +385,11 @@ define(['historyview', 'd3'], function(HistoryView) { this.renderBlobs(); }, + removeBlob: function(ws, index_to_remove) { + ws.blobs.splice(index_to_remove, 1); + this.renderBlobs(); + }, + _calculatePositionData: function(blobs) { for (var i = 0; i < blobs.length; i++) { var blob = blobs[i]; From 1a2c79a28199df537d8b66d438965aed7358dfcd Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 19:40:41 -0400 Subject: [PATCH 07/25] Added 'git stash drop' and remove Index blobs on commit --- js/controlbox.js | 5 +++++ js/workspace.js | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/js/controlbox.js b/js/controlbox.js index 7026ba7..6186bb9 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -251,6 +251,8 @@ function(_yargs, d3, demos) { this.info('`git rev_parse`') this.info('`git revert`') this.info('`git tag`') + this.info('`git add`') + this.info('`git stash`') return } @@ -379,6 +381,7 @@ function(_yargs, d3, demos) { this.getRepoView().amendCommit(opts.m || this.getRepoView().getCommit('head').message) } else { this.getRepoView().commit(null, opts.m); + workspace.removeAllBlobs(workspace.index); } }, function(before, after) { var reflogMsg = 'commit: ' + msg @@ -939,6 +942,8 @@ function(_yargs, d3, demos) { } else { console.log("Invalid stash to drop"); } + } else if (args && args[0] === "clear") { + workspace.removeAllBlobs(workspace.stash); } else { workspace.addBlob(workspace.curr_ws, workspace.stash, true); } diff --git a/js/workspace.js b/js/workspace.js index 98261b5..47cdb9e 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -390,6 +390,11 @@ define(['historyview', 'd3'], function(HistoryView) { this.renderBlobs(); }, + removeAllBlobs: function(ws) { + ws.blobs = [] + this.renderBlobs(); + }, + _calculatePositionData: function(blobs) { for (var i = 0; i < blobs.length; i++) { var blob = blobs[i]; @@ -486,7 +491,7 @@ define(['historyview', 'd3'], function(HistoryView) { }, 14); this._renderText(ws, 'message-label', function(d) { if (ws.name === "stash") { - return "{" + ws.blobs.indexOf(d) + "}"; + return "stash@{" + ws.blobs.indexOf(d) + "}"; } return "filename"; }, 24); From 85ccd7871fbe0e82cee717e59196897c7b1c47a2 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 19:53:18 -0400 Subject: [PATCH 08/25] Clear Workspace and Index on 'git reset --hard' --- js/controlbox.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/controlbox.js b/js/controlbox.js index 6186bb9..2903aab 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -558,6 +558,8 @@ function(_yargs, d3, demos) { break; case '--hard': this.doReset(args.join(' ')); + workspace.removeAllBlobs(workspace.curr_ws); + workspace.removeAllBlobs(workspace.index); args.length = 0; break; default: @@ -565,6 +567,8 @@ function(_yargs, d3, demos) { args.length = 0; this.info('Assuming "--hard".'); this.doReset(remainingArgs.join(' ')); + workspace.removeAllBlobs(workspace.curr_ws); + workspace.removeAllBlobs(workspace.index); } } }, From 7943d9f320bb3136888fbeb7e6a53bf056832019 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 21:41:59 -0400 Subject: [PATCH 09/25] Added expected behavior for 'git reset --soft' and '--mixed' --- js/controlbox.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index 2903aab..e7e1d5a 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -543,21 +543,19 @@ function(_yargs, d3, demos) { switch (arg) { case '--soft': - this.info( - 'The "--soft" flag works in real git, but ' + - 'I am unable to show you how it works in this demo. ' + - 'So I am just going to show you what "--hard" looks like instead.' - ); + // no resetting of the index or working tree + this.doReset(args.join(' ')); + args.length = 0; break; case '--mixed': - this.info( - 'The "--mixed" flag works in real git, but ' + - 'I am unable to show you how it works in this demo. ' + - 'So I am just going to show you what "--hard" looks like instead.' - ); + // reset just the index + this.doReset(args.join(' ')); + workspace.removeAllBlobs(workspace.index); + args.length = 0; break; case '--hard': this.doReset(args.join(' ')); + // reset the index and the working tree workspace.removeAllBlobs(workspace.curr_ws); workspace.removeAllBlobs(workspace.index); args.length = 0; @@ -567,6 +565,7 @@ function(_yargs, d3, demos) { args.length = 0; this.info('Assuming "--hard".'); this.doReset(remainingArgs.join(' ')); + // reset the index and the working tree workspace.removeAllBlobs(workspace.curr_ws); workspace.removeAllBlobs(workspace.index); } From f808a155c0fb71633c85325934d5d04c8e1dea25 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Mon, 30 Mar 2020 21:47:34 -0400 Subject: [PATCH 10/25] Add working tree entry with 'edit' instead of 'git edit' --- js/controlbox.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index e7e1d5a..252c0e2 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -232,6 +232,7 @@ function(_yargs, d3, demos) { this.info('pres() = Turn on presenter mode') this.info('undo = Undo the last git command') this.info('redo = Redo the last undone git command') + this.info('edit = Make a file edit') this.info('mode = Change mode (`local` or `remote`)') this.info('clear = Clear the history pane and reset the visualization') this.info() @@ -303,6 +304,12 @@ function(_yargs, d3, demos) { return } + if (entry.toLowerCase() === 'edit') { + var workspace = this.workspace; + workspace.addBlob(null, workspace.curr_ws); + return + } + if (entry.toLowerCase() === 'clear') { window.resetVis() return @@ -951,15 +958,6 @@ function(_yargs, d3, demos) { workspace.addBlob(workspace.curr_ws, workspace.stash, true); } - return - }, - - edit: function(args) { - // Create boxes to visualize working tree, index, stash - console.log("in edit"); - var workspace = this.workspace; - - workspace.addBlob(null, workspace.curr_ws); return } }; From fc44756aee1b43bbdb101595255b664fabe3a649 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Tue, 31 Mar 2020 18:26:30 -0400 Subject: [PATCH 11/25] Implemented 'git add ' --- js/controlbox.js | 15 ++++++++++++++- js/workspace.js | 24 +++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index 252c0e2..1dddb21 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -935,8 +935,21 @@ function(_yargs, d3, demos) { // Create boxes to visualize working tree, index, stash console.log("in add"); var workspace = this.workspace; + while (args.length > 0) { + var arg = args.shift(); + switch (arg) { + case '-u': + case '.': + workspace.addBlob(workspace.curr_ws, workspace.index, true); + break; + default: + workspace.moveBlobByName(workspace.curr_ws, workspace.index, arg); + break; + } + + } - workspace.addBlob(workspace.curr_ws, workspace.index, true); + //workspace.addBlob(workspace.curr_ws, workspace.index, true); return }, diff --git a/js/workspace.js b/js/workspace.js index 47cdb9e..cdd968d 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -238,6 +238,7 @@ define(['historyview', 'd3'], function(HistoryView) { //this.height = this.historyView.height || 400; this.blob_height = config.blob_height || 75; this.blob_width = config.blob_height || 200; + this.filename_counter = 0; } Workspace.prototype = { @@ -343,12 +344,16 @@ define(['historyview', 'd3'], function(HistoryView) { if (ws.blobs === undefined || !ws.blobs) { ws.blobs = []; } - var blob = {'id': HistoryView.generateId(), 'x': 50, 'y': 50} + var blob = {'id': HistoryView.generateId(), + 'x': 50, + 'y': 50, + 'filename': 'file_' + this.filename_counter} + this.filename_counter += 1; ws.blobs.push(blob); console.log(ws.blobs); }, - addBlob: function(src, dst, moveAll = false) { + addBlob: function(src, dst, moveAll=false) { if (src === null) { // Adding a brand new blob this.addNewBlob(dst); @@ -385,6 +390,19 @@ define(['historyview', 'd3'], function(HistoryView) { this.renderBlobs(); }, + moveBlobByName: function(src, dst, filename) { + var target_blob = src.blobs.filter(function(d) { + return d.filename === filename; + }); + if (target_blob && target_blob.length == 1) { + // remove from src + src.blobs.splice(src.blobs.indexOf(target_blob[0]), 1); + // add to dst + dst.blobs.push(target_blob[0]); + } + this.renderBlobs(); + }, + removeBlob: function(ws, index_to_remove) { ws.blobs.splice(index_to_remove, 1); this.renderBlobs(); @@ -493,7 +511,7 @@ define(['historyview', 'd3'], function(HistoryView) { if (ws.name === "stash") { return "stash@{" + ws.blobs.indexOf(d) + "}"; } - return "filename"; + return d.filename; }, 24); }, From bc5aa196a874f0c0668dee17cf7502d40fedee30 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Tue, 31 Mar 2020 22:34:02 -0400 Subject: [PATCH 12/25] Implemented 'git checkout -- ' --- js/controlbox.js | 42 +++++++++++++++++++++++++----------------- js/workspace.js | 11 +++++++---- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index 1dddb21..c98b3c2 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -483,25 +483,33 @@ function(_yargs, d3, demos) { }, checkout: function(args, opts) { - if (opts.b) { - if (opts._[0]) { - this.branch(null, null, opts.b + ' ' + opts._[0]) - } else { - this.branch(null, null, opts.b) + if (args && args[0] === "--") { + args.shift(); + while (args.length > 0) { + var arg = args.shift(); + workspace.moveBlobByName(workspace.curr_ws, undefined, arg); + } + } else { + if (opts.b) { + if (opts._[0]) { + this.branch(null, null, opts.b + ' ' + opts._[0]) + } else { + this.branch(null, null, opts.b) + } } - } - var name = opts.b || opts._[0] + var name = opts.b || opts._[0] - this.transact(function() { - this.getRepoView().checkout(name); - }, function(before, after) { - this.getRepoView().addReflogEntry( - 'HEAD', after.commit.id, - 'checkout: moving from ' + before.ref + - ' to ' + name - ) - }) + this.transact(function() { + this.getRepoView().checkout(name); + }, function(before, after) { + this.getRepoView().addReflogEntry( + 'HEAD', after.commit.id, + 'checkout: moving from ' + before.ref + + ' to ' + name + ) + }) + } }, tag: function(args) { @@ -942,7 +950,7 @@ function(_yargs, d3, demos) { case '.': workspace.addBlob(workspace.curr_ws, workspace.index, true); break; - default: + default: workspace.moveBlobByName(workspace.curr_ws, workspace.index, arg); break; } diff --git a/js/workspace.js b/js/workspace.js index cdd968d..fd7c786 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -262,7 +262,7 @@ define(['historyview', 'd3'], function(HistoryView) { //.attr('height', this.height); var labelX = 15; var labelY = 25; - + stash = svg.append('svg:g').classed('stash', true).attr('id', 'stash') stash.append('svg:rect') @@ -391,6 +391,7 @@ define(['historyview', 'd3'], function(HistoryView) { }, moveBlobByName: function(src, dst, filename) { + // set dst to undefined to remove the blob var target_blob = src.blobs.filter(function(d) { return d.filename === filename; }); @@ -398,7 +399,9 @@ define(['historyview', 'd3'], function(HistoryView) { // remove from src src.blobs.splice(src.blobs.indexOf(target_blob[0]), 1); // add to dst - dst.blobs.push(target_blob[0]); + if (dst) { + dst.blobs.push(target_blob[0]); + } } this.renderBlobs(); }, @@ -453,7 +456,7 @@ define(['historyview', 'd3'], function(HistoryView) { console.log(ws.blobs); // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); - // Enter + // Enter blob_rect.enter().append("svg:rect") .attr("width", function(d) { console.log(d); return view.blob_width;}) .attr("height", view.blob_height) @@ -476,7 +479,7 @@ define(['historyview', 'd3'], function(HistoryView) { console.log(ws.blobs); // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); - // Enter + // Enter blob_rect.enter().append("svg:rect") .attr("width", function(d) { console.log(d); return view.blob_width;}) .attr("height", view.blob_height) From c6c0101cd7a505ef10f08d8ac13629b03a0d3809 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Fri, 3 Apr 2020 23:06:28 -0400 Subject: [PATCH 13/25] Cleaned up unstaging logic --- js/controlbox.js | 58 +++++++++++++++++++++++++----------------------- js/workspace.js | 6 ++--- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index c98b3c2..8f267f0 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -553,36 +553,38 @@ function(_yargs, d3, demos) { }, reset: function(args) { + var unstage = false; while (args.length > 0) { var arg = args.shift(); - - switch (arg) { - case '--soft': - // no resetting of the index or working tree - this.doReset(args.join(' ')); - args.length = 0; - break; - case '--mixed': - // reset just the index - this.doReset(args.join(' ')); - workspace.removeAllBlobs(workspace.index); - args.length = 0; - break; - case '--hard': - this.doReset(args.join(' ')); - // reset the index and the working tree - workspace.removeAllBlobs(workspace.curr_ws); - workspace.removeAllBlobs(workspace.index); - args.length = 0; - break; - default: - var remainingArgs = [arg].concat(args); - args.length = 0; - this.info('Assuming "--hard".'); - this.doReset(remainingArgs.join(' ')); - // reset the index and the working tree - workspace.removeAllBlobs(workspace.curr_ws); - workspace.removeAllBlobs(workspace.index); + if (unstage) { + workspace.moveBlobByName(workspace.index, workspace.curr_ws, arg); + } else { + switch (arg) { + case '--soft': + // no resetting of the index or working tree + this.doReset(args.join(' ')); + args.length = 0; + break; + case '--mixed': + // reset just the index + this.doReset(args.join(' ')); + workspace.removeAllBlobs(workspace.index); + args.length = 0; + break; + case '--hard': + this.doReset(args.join(' ')); + // reset the index and the working tree + workspace.removeAllBlobs(workspace.curr_ws); + workspace.removeAllBlobs(workspace.index); + args.length = 0; + break; + case "HEAD": + // unstage the file (move from index to working tree) + unstage = true; + break; + default: + this.info("Invalid ref: " + arg); + } } } }, diff --git a/js/workspace.js b/js/workspace.js index fd7c786..4a35a56 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -284,10 +284,10 @@ define(['historyview', 'd3'], function(HistoryView) { .attr('width', "31%") .attr('height', "100%") .attr('x', 0) - .attr('y', 0); + .attr('y', 0); curr_ws.append('svg:text') .classed('workspace-label', true) - .text('Workspace') + .text('Workspace/Working Tree') .attr('x', labelX) .attr('y', labelY); curr_ws.append('svg:g').classed('blob-space', true).attr('id', 'curr_ws.blob-space'); @@ -302,7 +302,7 @@ define(['historyview', 'd3'], function(HistoryView) { .attr('y', 0); index.append('svg:text') .classed('workspace-label', true) - .text('Index') + .text('Index/Stage') .attr('x', labelX) .attr('y', labelY); index.append('svg:g').classed('blob-space', true).attr('id', 'index.blob-space'); From 089bde9db63b67a8bb0161e041ac14e1666153e3 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 4 Apr 2020 11:27:05 -0400 Subject: [PATCH 14/25] Fixed workspace to index bug --- js/workspace.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/workspace.js b/js/workspace.js index 4a35a56..5b42b9c 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -366,8 +366,9 @@ define(['historyview', 'd3'], function(HistoryView) { // stash is treated like a stack of changesets (group of blobs) dst.blobs.unshift(src.blobs); } else { - dst.blobs = src.blobs; + dst.blobs = dst.blobs.concat(src.blobs); } + // empty out the src blobs src.blobs = []; console.log("Moving all blobs"); } else { From da233880cd59536ed4f68671d31c1d242d53ece8 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 4 Apr 2020 17:10:59 -0400 Subject: [PATCH 15/25] Added blob inflation --- js/workspace.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/js/workspace.js b/js/workspace.js index 5b42b9c..0b6d978 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -459,14 +459,23 @@ define(['historyview', 'd3'], function(HistoryView) { var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter blob_rect.enter().append("svg:rect") + .attr("id", function(d) { return "blob-" + d.id; }) + .classed("rendered-blob", true) + .attr("width", 1) + .attr("height", 1) + .transition("inflate") .attr("width", function(d) { console.log(d); return view.blob_width;}) .attr("height", view.blob_height) - .attr("id", function(d) { return "blob-" + d.id; }) - .classed("rendered-blob", true); + .duration(500); // Update view._calculatePositionData(ws.blobs); - blob_rect.transition() - .duration(500) + blob_rect + //.attr("width", 1) + //.attr("height", 1) + //.transition("inflate") + //.attr("width", function(d) { console.log(d); return view.blob_width;}) + //.attr("height", view.blob_height) + //.duration(500) .call(fixBlobPosition); //blob_rect //.attr("x", 50) @@ -482,10 +491,14 @@ define(['historyview', 'd3'], function(HistoryView) { var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter blob_rect.enter().append("svg:rect") + .attr("id", function(d) { return "changeset-" + d; }) + .classed("rendered-changeset", true) + .attr("width", 1) + .attr("height", 1) + .transition("inflate") .attr("width", function(d) { console.log(d); return view.blob_width;}) .attr("height", view.blob_height) - .attr("id", function(d) { return "changeset-" + d; }) - .classed("rendered-changeset", true); + .duration(500); // Update view._calculatePositionData(ws.blobs); blob_rect.transition() From d38aaf9a765787600f0653f3863e69dbe48e600b Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 4 Apr 2020 17:11:10 -0400 Subject: [PATCH 16/25] Half height for history and workspace view --- css/explaingit.css | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/css/explaingit.css b/css/explaingit.css index 564b95a..379d53f 100644 --- a/css/explaingit.css +++ b/css/explaingit.css @@ -88,10 +88,21 @@ span.cmd { border: 1px dotted #AAA; position: absolute; top: 0; + right: 0; + left: 250px; + margin-left: 0; + height: 50%; +} + +#ExplainGitZen-Container .ws-container { + display: inline-block; + border: 1px dotted #AAA; + position: absolute; bottom: 0; right: 0; left: 250px; margin-left: 0; + height: 50%; } #ExplainGitZen-Container .svg-container.remote-container { @@ -114,17 +125,6 @@ span.cmd { left: 20px; } -#ExplainGitZen-Container .ws-container { - display: inline-block; - border: 1px dotted #AAA; - position: absolute; - top: 500px; - bottom: 0; - right: 0; - left: 250px; - margin-left: 0; -} - .remote-name-display { font-weight: bold; text-align: right; From 6a080ccc2a7bc2e7a0c7c0007011c3e1da5da69c Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 4 Apr 2020 17:17:51 -0400 Subject: [PATCH 17/25] Removed unneeded code --- js/workspace.js | 84 ------------------------------------------------- 1 file changed, 84 deletions(-) diff --git a/js/workspace.js b/js/workspace.js index 0b6d978..347952b 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -128,72 +128,6 @@ define(['historyview', 'd3'], function(HistoryView) { }); }; - // calculates the x1 point for commit pointer lines - px1 = function(commit, view, pp) { - pp = pp || 'parent'; - - var parent = view.getCommit(commit[pp]), - startCX = commit.cx, - diffX = startCX - parent.cx, - diffY = parent.cy - commit.cy, - length = Math.sqrt((diffX * diffX) + (diffY * diffY)); - - return startCX - (view.pointerMargin * (diffX / length)); - }; - - // calculates the y1 point for commit pointer lines - py1 = function(commit, view, pp) { - pp = pp || 'parent'; - - var parent = view.getCommit(commit[pp]), - startCY = commit.cy, - diffX = commit.cx - parent.cx, - diffY = parent.cy - startCY, - length = Math.sqrt((diffX * diffX) + (diffY * diffY)); - - return startCY + (view.pointerMargin * (diffY / length)); - }; - - fixPointerStartPosition = function(selection, view) { - selection.attr('x1', function(d) { - return px1(d, view); - }).attr('y1', function(d) { - return py1(d, view); - }); - }; - - px2 = function(commit, view, pp) { - pp = pp || 'parent'; - - var parent = view.getCommit(commit[pp]), - endCX = parent.cx, - diffX = commit.cx - endCX, - diffY = parent.cy - commit.cy, - length = Math.sqrt((diffX * diffX) + (diffY * diffY)); - - return endCX + (view.pointerMargin * 1.2 * (diffX / length)); - }; - - py2 = function(commit, view, pp) { - pp = pp || 'parent'; - - var parent = view.getCommit(commit[pp]), - endCY = parent.cy, - diffX = commit.cx - parent.cx, - diffY = endCY - commit.cy, - length = Math.sqrt((diffX * diffX) + (diffY * diffY)); - - return endCY - (view.pointerMargin * 1.2 * (diffY / length)); - }; - - fixPointerEndPosition = function(selection, view) { - selection.attr('x2', function(d) { - return px2(d, view); - }).attr('y2', function(d) { - return py2(d, view); - }); - }; - fixIdPosition = function(selection, view, delta) { selection.attr('x', function(d) { return d.x + view.blob_width / 2; @@ -318,13 +252,8 @@ define(['historyview', 'd3'], function(HistoryView) { this.index = index this.index.name = "index" this.index.blobs = this.index.blobs || [] - //this.arrowBox = svg.append('svg:g').classed('pointers', true); - //this.commitBox = svg.append('svg:g').classed('commits', true); - //this.tagBox = svg.append('svg:g').classed('tags', true); this.renderBlobs(); - - //this._setCurrentBranch(this.currentBranch); }, destroy: function() { @@ -470,16 +399,7 @@ define(['historyview', 'd3'], function(HistoryView) { // Update view._calculatePositionData(ws.blobs); blob_rect - //.attr("width", 1) - //.attr("height", 1) - //.transition("inflate") - //.attr("width", function(d) { console.log(d); return view.blob_width;}) - //.attr("height", view.blob_height) - //.duration(500) .call(fixBlobPosition); - //blob_rect - //.attr("x", 50) - //.attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); // Remove blob_rect.exit().remove(); view._renderIdLabels(ws); @@ -504,9 +424,6 @@ define(['historyview', 'd3'], function(HistoryView) { blob_rect.transition() .duration(500) .call(fixBlobPosition); - //blob_rect - //.attr("x", 50) - //.attr("y", function(d) { return 50 + ws.blobs.indexOf(d) * 100; }); // Remove blob_rect.exit().remove(); view._renderIdLabels(ws); @@ -552,7 +469,6 @@ define(['historyview', 'd3'], function(HistoryView) { existingTexts.exit() .remove() }, - }; return Workspace; From aa7631937d9c5a12d42e73a141bd178a85019114 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sun, 5 Apr 2020 16:43:54 -0400 Subject: [PATCH 18/25] Cleaned up unused code --- js/controlbox.js | 13 ++--- js/workspace.js | 130 ++--------------------------------------------- 2 files changed, 6 insertions(+), 137 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index 8f267f0..6cded6e 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -86,7 +86,6 @@ function(_yargs, d3, demos) { }, changeMode: function (mode) { - console.log(mode) if (mode === 'local' && this.historyView) { this.mode = 'local' } else if (mode === 'remote' && this.originView) { @@ -943,7 +942,6 @@ function(_yargs, d3, demos) { add: function(args) { // Create boxes to visualize working tree, index, stash - console.log("in add"); var workspace = this.workspace; while (args.length > 0) { var arg = args.shift(); @@ -956,16 +954,12 @@ function(_yargs, d3, demos) { workspace.moveBlobByName(workspace.curr_ws, workspace.index, arg); break; } - } - - //workspace.addBlob(workspace.curr_ws, workspace.index, true); - return + return; }, stash: function(args) { // Create boxes to visualize working tree, index, stash - console.log("in stash"); var workspace = this.workspace; if (args && args[0] === "pop") { workspace.addBlob(workspace.stash, workspace.curr_ws); @@ -973,15 +967,14 @@ function(_yargs, d3, demos) { if (args[1] != undefined) { workspace.removeBlob(workspace.stash, args[1]); } else { - console.log("Invalid stash to drop"); + this.log("Invalid stash to drop"); } } else if (args && args[0] === "clear") { workspace.removeAllBlobs(workspace.stash); } else { workspace.addBlob(workspace.curr_ws, workspace.stash, true); } - - return + return; } }; diff --git a/js/workspace.js b/js/workspace.js index 347952b..4474eab 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -1,123 +1,9 @@ define(['historyview', 'd3'], function(HistoryView) { "use strict"; - var REG_MARKER_END = 'url(#triangle)', - MERGE_MARKER_END = 'url(#brown-triangle)', - FADED_MARKER_END = 'url(#faded-triangle)', - - preventOverlap, - applyBranchlessClass, - cx, cy, fixBlobPosition, - px1, py1, fixPointerStartPosition, - px2, py2, fixPointerEndPosition, + var fixBlobPosition, fixIdPosition, tagY, getUniqueSetItems; - preventOverlap = function preventOverlap(commit, view) { - var commitData = view.commitData, - baseLine = view.baseLine, - shift = view.commitRadius * 4.5, - overlapped = null; - - for (var i = 0; i < commitData.length; i++) { - var c = commitData[i]; - if (c.cx === commit.cx && c.cy === commit.cy && c !== commit) { - overlapped = c; - break; - } - } - - if (overlapped) { - var oParent = view.getCommit(overlapped.parent), - parent = view.getCommit(commit.parent); - - if (overlapped.cy < baseLine) { - overlapped = oParent.cy < parent.cy ? overlapped : commit; - overlapped.cy -= shift; - } else { - overlapped = oParent.cy > parent.cy ? overlapped : commit; - overlapped.cy += shift; - } - - preventOverlap(overlapped, view); - } - }; - - applyBranchlessClass = function(selection) { - if (selection.empty()) { - return; - } - - selection.classed('branchless', function(d) { - return d.branchless; - }); - - if (selection.classed('commit-pointer')) { - selection.attr('marker-end', function(d) { - return d.branchless ? FADED_MARKER_END : REG_MARKER_END; - }); - } else if (selection.classed('merge-pointer')) { - selection.attr('marker-end', function(d) { - return d.branchless ? FADED_MARKER_END : MERGE_MARKER_END; - }); - } - }; - - cx = function(commit, view) { - var parent = view.getCommit(commit.parent), - parentCX = parent.cx; - - if (typeof commit.parent2 === 'string') { - var parent2 = view.getCommit(commit.parent2); - - parentCX = parent.cx > parent2.cx ? parent.cx : parent2.cx; - } - - return parentCX + (view.commitRadius * 4.5); - }; - - cy = function(commit, view) { - var parent = view.getCommit(commit.parent), - parentCY = parent.cy || cy(parent, view), - baseLine = view.baseLine, - shift = view.commitRadius * 4.5, - branches = [], // count the existing branches - branchIndex = 0; - - for (var i = 0; i < view.commitData.length; i++) { - var d = view.commitData[i]; - - if (d.parent === commit.parent) { - branches.push(d.id); - } - } - - branchIndex = branches.indexOf(commit.id); - - if (commit.isNoFFBranch === true) { - branchIndex++; - } - if (commit.isNoFFCommit === true) { - branchIndex--; - } - - if (parentCY === baseLine) { - var direction = 1; - for (var bi = 0; bi < branchIndex; bi++) { - direction *= -1; - } - - shift *= Math.ceil(branchIndex / 2); - - return parentCY + (shift * direction); - } - - if (parentCY < baseLine) { - return parentCY - (shift * branchIndex); - } else if (parentCY > baseLine) { - return parentCY + (shift * branchIndex); - } - }; - fixBlobPosition = function(selection) { selection .attr('x', function(d) { @@ -269,7 +155,6 @@ define(['historyview', 'd3'], function(HistoryView) { }, addNewBlob: function(ws) { - console.log("adding new blob to " + ws.name); if (ws.blobs === undefined || !ws.blobs) { ws.blobs = []; } @@ -279,7 +164,6 @@ define(['historyview', 'd3'], function(HistoryView) { 'filename': 'file_' + this.filename_counter} this.filename_counter += 1; ws.blobs.push(blob); - console.log(ws.blobs); }, addBlob: function(src, dst, moveAll=false) { @@ -299,7 +183,6 @@ define(['historyview', 'd3'], function(HistoryView) { } // empty out the src blobs src.blobs = []; - console.log("Moving all blobs"); } else { if (dst.blobs === undefined) { dst.blobs = []; @@ -314,7 +197,6 @@ define(['historyview', 'd3'], function(HistoryView) { } else { dst.blobs.push(top_blob); } - console.log("Moving top blob"); } } this.renderBlobs(); @@ -351,7 +233,6 @@ define(['historyview', 'd3'], function(HistoryView) { var blob = blobs[i]; blob.x = 50; blob.y = 50 + i * 125; - //preventOverlap(commit, this); } }, @@ -379,11 +260,8 @@ define(['historyview', 'd3'], function(HistoryView) { curr_workspace = this.stash, workspaces = [this.curr_ws, this.index], changeset_workspaces = [this.stash]; - console.log("rendering blobs"); workspaces.forEach(function(ws) { - console.log(ws.name); - console.log(ws.blobs); // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter @@ -393,7 +271,7 @@ define(['historyview', 'd3'], function(HistoryView) { .attr("width", 1) .attr("height", 1) .transition("inflate") - .attr("width", function(d) { console.log(d); return view.blob_width;}) + .attr("width", view.blob_width) .attr("height", view.blob_height) .duration(500); // Update @@ -405,8 +283,6 @@ define(['historyview', 'd3'], function(HistoryView) { view._renderIdLabels(ws); }); changeset_workspaces.forEach(function(ws) { - console.log(ws.name); - console.log(ws.blobs); // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter @@ -416,7 +292,7 @@ define(['historyview', 'd3'], function(HistoryView) { .attr("width", 1) .attr("height", 1) .transition("inflate") - .attr("width", function(d) { console.log(d); return view.blob_width;}) + .attr("width", view.blob_width) .attr("height", view.blob_height) .duration(500); // Update From 7a42a3d57d8d432bb7efaf71b36d7e2634981cba Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sun, 5 Apr 2020 16:44:08 -0400 Subject: [PATCH 19/25] Added padding between history and workspace view --- css/explaingit.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/css/explaingit.css b/css/explaingit.css index 379d53f..067f8cc 100644 --- a/css/explaingit.css +++ b/css/explaingit.css @@ -91,7 +91,7 @@ span.cmd { right: 0; left: 250px; margin-left: 0; - height: 50%; + height: 49%; } #ExplainGitZen-Container .ws-container { @@ -101,8 +101,8 @@ span.cmd { bottom: 0; right: 0; left: 250px; - margin-left: 0; - height: 50%; + margin-left: 5px; + height: 49%; } #ExplainGitZen-Container .svg-container.remote-container { From d011d068af8c5e77098267e95b3dcb09cd0f410b Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Tue, 7 Apr 2020 22:41:28 -0400 Subject: [PATCH 20/25] Implemented 'git stash apply' --- js/controlbox.js | 6 ++++++ js/workspace.js | 22 ++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index 6cded6e..db86f42 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -963,6 +963,12 @@ function(_yargs, d3, demos) { var workspace = this.workspace; if (args && args[0] === "pop") { workspace.addBlob(workspace.stash, workspace.curr_ws); + } else if (args && args[0] === "apply") { + if (args[1] != undefined) { + workspace.moveBlobByName(workspace.stash, workspace.curr_ws, args[1], false); + } else { + this.log("Invalid stash to apply"); + } } else if (args && args[0] === "drop") { if (args[1] != undefined) { workspace.removeBlob(workspace.stash, args[1]); diff --git a/js/workspace.js b/js/workspace.js index 4474eab..01d0d79 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -202,17 +202,23 @@ define(['historyview', 'd3'], function(HistoryView) { this.renderBlobs(); }, - moveBlobByName: function(src, dst, filename) { + moveBlobByName: function(src, dst, filename, remove_from_src=true) { // set dst to undefined to remove the blob var target_blob = src.blobs.filter(function(d) { return d.filename === filename; }); if (target_blob && target_blob.length == 1) { - // remove from src - src.blobs.splice(src.blobs.indexOf(target_blob[0]), 1); + if (remove_from_src) { + src.blobs.splice(src.blobs.indexOf(target_blob[0]), 1); + } // add to dst if (dst) { - dst.blobs.push(target_blob[0]); + if (Array.isArray(target_blob[0])) { + // ensure there's no duplicates after a 'stash apply' + dst.blobs = Array.from(new Set(dst.blobs.concat(target_blob[0]))); + } else { + dst.blobs.push(target_blob[0]); + } } } this.renderBlobs(); @@ -313,13 +319,17 @@ define(['historyview', 'd3'], function(HistoryView) { d.forEach( function(blob) { ret_str += blob.id + ','; }); - return ret_str.substr(0, 16); + ret_str = ret_str.substr(0, ret_str.length - 1); + return ret_str.substr(0, 32); } return d.id + '..'; }, 14); this._renderText(ws, 'message-label', function(d) { if (ws.name === "stash") { - return "stash@{" + ws.blobs.indexOf(d) + "}"; + var filename = "stash@{" + ws.blobs.indexOf(d) + "}"; + // save the stash name in the changeset object + d.filename = filename; + return filename; } return d.filename; }, 24); From b108a69fafb43d0232a4961aaa718a815c559c7f Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 18 Apr 2020 14:52:03 -0400 Subject: [PATCH 21/25] 'git stash' default to '0' --- js/controlbox.js | 11 +++++------ js/workspace.js | 36 ++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/js/controlbox.js b/js/controlbox.js index db86f42..336fa6b 100644 --- a/js/controlbox.js +++ b/js/controlbox.js @@ -961,20 +961,19 @@ function(_yargs, d3, demos) { stash: function(args) { // Create boxes to visualize working tree, index, stash var workspace = this.workspace; + var stash_id = "0"; if (args && args[0] === "pop") { workspace.addBlob(workspace.stash, workspace.curr_ws); } else if (args && args[0] === "apply") { if (args[1] != undefined) { - workspace.moveBlobByName(workspace.stash, workspace.curr_ws, args[1], false); - } else { - this.log("Invalid stash to apply"); + stash_id = args[1]; } + workspace.moveBlobByName(workspace.stash, workspace.curr_ws, stash_id, false); } else if (args && args[0] === "drop") { if (args[1] != undefined) { - workspace.removeBlob(workspace.stash, args[1]); - } else { - this.log("Invalid stash to drop"); + stash_id = args[1]; } + workspace.removeBlob(workspace.stash, stash_id); } else if (args && args[0] === "clear") { workspace.removeAllBlobs(workspace.stash); } else { diff --git a/js/workspace.js b/js/workspace.js index 01d0d79..4390edf 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -172,9 +172,8 @@ define(['historyview', 'd3'], function(HistoryView) { this.addNewBlob(dst); } else { // Moving an existing blob from 'src' to 'dst' - if (src.blobs === undefined || src.blobs.length == 0) { - console.log("no blobs to move"); - } else if (moveAll) { + if (src.blobs !== undefined && src.blobs.length > 0) { + if (moveAll) { if (dst.name === "stash") { // stash is treated like a stack of changesets (group of blobs) dst.blobs.unshift(src.blobs); @@ -183,19 +182,20 @@ define(['historyview', 'd3'], function(HistoryView) { } // empty out the src blobs src.blobs = []; - } else { - if (dst.blobs === undefined) { - dst.blobs = []; - } - if (src.name == "stash") { - var top_blob = src.blobs.shift(); - } else { - var top_blob = src.blobs.pop(); - } - if (Array.isArray(top_blob)) { - dst.blobs = dst.blobs.concat(top_blob); } else { - dst.blobs.push(top_blob); + if (dst.blobs === undefined) { + dst.blobs = []; + } + if (src.name === "stash") { + var top_blob = src.blobs.shift(); + } else { + var top_blob = src.blobs.pop(); + } + if (Array.isArray(top_blob)) { + dst.blobs = dst.blobs.concat(top_blob); + } else { + dst.blobs.push(top_blob); + } } } } @@ -205,7 +205,11 @@ define(['historyview', 'd3'], function(HistoryView) { moveBlobByName: function(src, dst, filename, remove_from_src=true) { // set dst to undefined to remove the blob var target_blob = src.blobs.filter(function(d) { - return d.filename === filename; + if (src.name === "stash") { + return d.filename.split("{")[1].split("}")[0] === filename; + } else { + return d.filename === filename; + } }); if (target_blob && target_blob.length == 1) { if (remove_from_src) { From 89c1de144637b5be436592894cb5b40150ba80ef Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 18 Apr 2020 15:19:32 -0400 Subject: [PATCH 22/25] Added example documentation --- examples/working_tree.md | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 examples/working_tree.md diff --git a/examples/working_tree.md b/examples/working_tree.md new file mode 100644 index 0000000..9389b52 --- /dev/null +++ b/examples/working_tree.md @@ -0,0 +1,52 @@ +### Make local changes to the working tree + +Simulate file edits with the 'edit' command. No filename is required. + +``` +edit +``` + +### The Stash + +The stash a convenient place to store changes that aren't ready for committing. +To move these files changes to the stash: + +``` +git stash +``` + +To move these changes back to the working tree: + +``` +git stash apply +``` +OR +``` +git stash pop +``` + +Applying the changes will move the changes back to the working tree and leave a copy in the stash. +Popping the changes will move the changes back to the working tree but will remove the changes from +the stash. + +### Add files to the index + +If files are ready for committing, they can "staged"/"added to the index". + +``` +git add -u +``` + +The `-u` flag adds all previously tracked files to the staging area + +### Remove files from the index + +If a file needs to be removed from the staging area, use 'git reset' + +``` +git reset -- +``` + +### Committing + +Committing files will remove them from the index and add them to the local repository. From 3de364e37dd42105ed61479419db0c16ee733c87 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 18 Apr 2020 15:21:05 -0400 Subject: [PATCH 23/25] Updated documentation to reflect new 'add' and 'stash' commands --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index af2bb5d..e216309 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Type `help` in the command box to see a list of supported operations `pres()` = Turn on presenter mode
`undo` = Undo the last git command
`redo` = Redo the last undone git command
+`edit` = Make a file edit
`mode` = Change mode (`local` or `remote`)
`clear` = Clear the history pane and reset the visualization @@ -45,6 +46,8 @@ git reset git rev_parse git revert git tag +git add +git stash ``` From c42a0e27825ed41c1eacd720eefbdfb27eba0310 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 18 Apr 2020 15:21:23 -0400 Subject: [PATCH 24/25] Removed debug prints --- js/historyview.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/historyview.js b/js/historyview.js index 44293de..7687ac1 100644 --- a/js/historyview.js +++ b/js/historyview.js @@ -530,9 +530,6 @@ define(['d3'], function() { .attr('width', this.width) .attr('height', this.isRemote ? this.height + 150 : this.height); - console.log(this.width); - console.log(this.height); - if (this.isRemote) { svg.append('svg:text') .classed('remote-name-display', true) From 0baa509f3a87c16b647d27abe62ed010058f8616 Mon Sep 17 00:00:00 2001 From: dpatel19 Date: Sat, 18 Apr 2020 15:21:37 -0400 Subject: [PATCH 25/25] Simplified renderBlobs() function --- js/workspace.js | 47 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/js/workspace.js b/js/workspace.js index 4390edf..98be4e8 100644 --- a/js/workspace.js +++ b/js/workspace.js @@ -263,21 +263,13 @@ define(['historyview', 'd3'], function(HistoryView) { } }, - renderBlobs: function() { - var view = this, - existingBlobs, - newBlobs, - curr_workspace = this.stash, - workspaces = [this.curr_ws, this.index], - changeset_workspaces = [this.stash]; - - workspaces.forEach(function(ws) { + _renderWorkspace: function(view, ws, blob_type) { // Bind the data var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); // Enter blob_rect.enter().append("svg:rect") - .attr("id", function(d) { return "blob-" + d.id; }) - .classed("rendered-blob", true) + .attr("id", function(d) { return blob_type + "-" + d.id; }) + .classed("rendered-" + blob_type, true) .attr("width", 1) .attr("height", 1) .transition("inflate") @@ -291,28 +283,21 @@ define(['historyview', 'd3'], function(HistoryView) { // Remove blob_rect.exit().remove(); view._renderIdLabels(ws); + }, + + renderBlobs: function() { + var view = this, + existingBlobs, + newBlobs, + curr_workspace = this.stash, + workspaces = [this.curr_ws, this.index], + changeset_workspaces = [this.stash]; + + workspaces.forEach(function(ws) { + view._renderWorkspace(view, ws, "blob"); }); changeset_workspaces.forEach(function(ws) { - // Bind the data - var blob_rect = ws.select("g.blob-space").selectAll("rect").data(ws.blobs); - // Enter - blob_rect.enter().append("svg:rect") - .attr("id", function(d) { return "changeset-" + d; }) - .classed("rendered-changeset", true) - .attr("width", 1) - .attr("height", 1) - .transition("inflate") - .attr("width", view.blob_width) - .attr("height", view.blob_height) - .duration(500); - // Update - view._calculatePositionData(ws.blobs); - blob_rect.transition() - .duration(500) - .call(fixBlobPosition); - // Remove - blob_rect.exit().remove(); - view._renderIdLabels(ws); + view._renderWorkspace(view, ws, "changeset"); }); },