Skip to content

Commit b0ff143

Browse files
committed
feat: discard safeguard finished
1 parent 1f74651 commit b0ff143

File tree

8 files changed

+309
-11
lines changed

8 files changed

+309
-11
lines changed

cls/SourceControl/Git/Change.cls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ ClassMethod AddDeletedToUncommitted(Filename, InternalName) As %Status
6666
Quit ..SetUncommitted(Filename, "delete", InternalName, $USERNAME, "", 1, "", "", 0)
6767
}
6868

69+
/// The Filename here is an ExternalName formatted name with the full file path
6970
ClassMethod IsUncommitted(Filename, ByRef ID) As %Boolean
7071
{
7172
&SQL(SELECT ID INTO :ID FROM SourceControl_Git.Change WHERE ItemFile = :Filename AND Committed = '0')

cls/SourceControl/Git/DiscardState.cls

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Method RestoreToFileTree()
2020
do fileStream.CopyFrom(..Contents)
2121
$$$ThrowOnError(fileStream.%Save())
2222
do ##class(SourceControl.Git.Utils).ImportItem(..InternalName, 1, 1)
23+
do ##class(SourceControl.Git.Utils).AddToServerSideSourceControl(..InternalName)
2324
$$$ThrowOnError(..%DeleteId(..%Id()))
2425
}
2526

@@ -53,6 +54,7 @@ ClassMethod DiscardStatesInBranch() As %DynamicArray
5354
set discardState = ..%OpenId(resultSet.ID)
5455
do discardState.%JSONExportToString(.JSONStr)
5556
set discardStateObject = ##class(%DynamicAbstractObject).%FromJSON(JSONStr)
57+
set discardStateObject.Id = resultSet.ID
5658
do discardStates.%Push(discardStateObject)
5759
}
5860

cls/SourceControl/Git/Utils.cls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,7 @@ ClassMethod SyncIrisWithRepoThroughDiff(ByRef files, ByRef filterToFiles, invert
19171917
set addedFiles = $extract(addedFiles, 2, *)
19181918

19191919
if (deletedFiles '= ""){
1920+
set ^mtempdeletedFiles($i(^mtempdeletedFiles)) = deletedFiles
19201921
set sc = ##class(SourceControl.Git.Utils).RemoveFromServerSideSourceControl(deletedFiles)
19211922
}
19221923
if (addedFiles '= ""){

cls/SourceControl/Git/WebUIDriver.cls

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
2727
if $isobject($get(responseJSON)) {
2828
do responseJSON.%ToJSON(%data)
2929
}
30-
} elseif $match(pathStart,"git-command|git|dirname|hostname|viewonly|discarded-states") {
30+
} elseif $match(pathStart,"git-command|git|dirname|hostname|viewonly|discarded-states|restore-discarded") {
3131
if (%request.Method = "GET") {
3232
set %data = ##class(%Stream.TmpCharacter).%New()
3333
// Things not handled from Python backend:
@@ -213,6 +213,23 @@ ClassMethod HandleRequest(pagePath As %String, InternalName As %String = "", Out
213213
do %data.Write("Git-Return-Code: " _ returnCode) // No ending newline expected
214214
do %data.Rewind()
215215
set handled = 1
216+
} elseif (pathStart = "restore-discarded") {
217+
merge data = %request.Data
218+
set fileId = data("file",1)
219+
220+
set %data = ##class(%Stream.TmpCharacter).%New()
221+
222+
set discardState = ##class(SourceControl.Git.DiscardState).%OpenId(fileId)
223+
if ##class(SourceControl.Git.Change).IsUncommitted(discardState.FullExternalName) {
224+
do %data.WriteLine("Please commit changes to file before restoring discarded state")
225+
} else {
226+
do discardState.RestoreToFileTree()
227+
do %data.WriteLine("Successfully restored discarded file state")
228+
}
229+
230+
do %data.Rewind()
231+
do ##class(SourceControl.Git.Change).RefreshUncommitted(,,,1)
232+
set handled = 1
216233
}
217234
}
218235
}

git-webui/release/share/git-webui/webui/css/git-webui.css

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,3 +936,52 @@ body {
936936
-webkit-flex: 1 1 0px;
937937
overflow: auto;
938938
}
939+
#discardedView {
940+
width: 100%;
941+
}
942+
#discardedView #discardedList {
943+
height: 100%;
944+
border-right: 1px #dddddd solid;
945+
}
946+
#discardedView #discardedList h4 {
947+
text-align: center;
948+
padding-top: 100px;
949+
}
950+
#discardedView .active {
951+
background-color: rgba(13, 110, 253, 0.9) !important;
952+
color: #fff;
953+
}
954+
#discardedView header {
955+
display: flex;
956+
display: -webkit-flex;
957+
min-height: 0;
958+
min-width: 0;
959+
}
960+
#discardedView header .file-internalname {
961+
display: inline-block;
962+
}
963+
#discardedView header .discard-date {
964+
margin-left: auto;
965+
}
966+
#discardedView .external-name {
967+
font-size: 1rem;
968+
padding: 20px 15px 0 0;
969+
}
970+
#discardedView .contents-menu {
971+
display: flex;
972+
display: -webkit-flex;
973+
min-height: 0;
974+
min-width: 0;
975+
}
976+
#discardedView .contents-menu .restore-discarded {
977+
padding-top: 15px;
978+
margin-left: auto;
979+
margin-right: 15px;
980+
}
981+
#discardedView .has-items {
982+
padding-bottom: 20px;
983+
border-bottom: 1px solid lightgrey;
984+
}
985+
#discardedView .file-contents {
986+
padding-top: 20px;
987+
}

git-webui/release/share/git-webui/webui/js/git-webui.js

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,17 +1841,100 @@ webui.DiscardedView = function(mainView) {
18411841
mainView.switchTo(self.element);
18421842
};
18431843

1844-
self.getDiscardedStates = function() {
1844+
1845+
self.update = function() {
1846+
self.discarded = [];
1847+
discardedList.innerHTML = '';
1848+
$('.file-contents').html('');
1849+
$('.contents-menu').removeClass("has-items");
1850+
$('.external-name').text('');
1851+
$('.restore-discarded').html('');
1852+
1853+
// TODO: Empty the discarded list properly
18451854
$.get("discarded-states", function(discarded) {
1846-
console.log(discarded);
1855+
self.discarded = JSON.parse(discarded);
1856+
if (self.discarded.length == 0) {
1857+
discardedList.innerHTML = '<h4>You have no saved discarded states</h4>';
1858+
}
1859+
1860+
self.populateUiWithDiscardedStates();
18471861
});
1862+
1863+
18481864
}
18491865

1850-
self.update = function() {
1851-
self.getDiscardedStates();
1866+
1867+
1868+
self.populateUiWithDiscardedStates = function() {
1869+
self.discarded.forEach((discardedState, ind) => {
1870+
var discardedListEntry = $(
1871+
'<a class="log-entry list-group-item">' +
1872+
'<header>' +
1873+
'<h6 class="file-internalname">' + discardedState.InternalName + '</h6>' +
1874+
'<span class="discard-date">' + self.formatTimestamp(discardedState.Timestamp) + '</span>' +
1875+
'</header>' +
1876+
'<span> Branch: ' + discardedState.Branch + ' </span> <br>' +
1877+
'<span> User: '+ discardedState.Username + '</span>' +
1878+
1879+
'</a>'
1880+
);
1881+
1882+
discardedListEntry.on("click", function() {
1883+
$('.log-entry.list-group-item').removeClass('active');
1884+
$(this).addClass('active');
1885+
1886+
$('.contents-menu').addClass("has-items");
1887+
$('.external-name').text(self.discarded[ind].FullExternalName);
1888+
1889+
var btn = $('<button class="btn btn-sm btn-primary restore-discarded-btn">Restore</button>')[0];
1890+
var discardElement = $('.restore-discarded')[0];
1891+
discardElement.innerHTML = '';
1892+
discardElement.appendChild(btn);
1893+
1894+
$('.restore-discarded-btn').off("click").on("click", function() {
1895+
$.post("restore-discarded", {file: discardedState.Id}, function(message) {
1896+
if (message.trim() == "Please commit changes to file before restoring discarded state") {
1897+
webui.showError(message);
1898+
} else {
1899+
webui.showSuccess(message);
1900+
}
1901+
1902+
self.update();
1903+
});
1904+
});
1905+
1906+
$('.file-contents').html('<pre>' + discardedState.Contents + '</pre>');
1907+
});
1908+
1909+
1910+
discardedListEntry.prependTo(discardedList)[0];
1911+
});
18521912
}
1913+
/// This function takes in an IRIS timestamp format makes it use the "date, time" format
1914+
self.formatTimestamp = function(timestamp) {
1915+
var timestampArr = timestamp.split("T");
1916+
return timestampArr[0] + ', ' + timestampArr[1].slice(0, -1);
1917+
}
1918+
1919+
self.element = $(
1920+
'<div class="row" id="discardedView">' +
1921+
'<div class="col-sm-7">' +
1922+
'<div id="discardedList"></div>' +
1923+
'</div>' +
1924+
'<div class="col-sm-5">' +
1925+
'<div class="contents-menu">' +
1926+
'<div class="nav-item external-name"></div>' +
1927+
'<div class="nav-item restore-discarded"></div>' +
1928+
'</div>' +
1929+
'<div class="container file-contents">' +
18531930

1854-
self.element = $('<div id="discardedView"></div>')[0];
1931+
'</div>' +
1932+
'</div>' +
1933+
'</div>'
1934+
1935+
)[0];
1936+
self.discarded = [];
1937+
var discardedList = $("#discardedList", self.element)[0];
18551938

18561939
}
18571940

git-webui/src/share/git-webui/webui/css/git-webui.less

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,3 +942,65 @@ body {
942942
}
943943
}
944944
}
945+
946+
#discardedView {
947+
width: 100%;
948+
949+
#discardedList {
950+
height: 100%;
951+
border-right: 1px @separator-line solid;
952+
953+
h4{
954+
text-align: center;
955+
padding-top: 100px;
956+
}
957+
}
958+
959+
960+
.active {
961+
background-color: rgba(13, 110, 253, 0.9) !important;
962+
color: #fff;
963+
}
964+
965+
header {
966+
.display-flex();
967+
.file-internalname {
968+
display: inline-block;
969+
}
970+
971+
.discard-date {
972+
margin-left: auto;
973+
}
974+
}
975+
976+
.external-name {
977+
font-size: 1rem;
978+
padding: 20px 15px 0 0;
979+
}
980+
981+
982+
983+
.contents-menu {
984+
.display-flex();
985+
986+
.restore-discarded {
987+
padding-top: 15px;
988+
margin-left: auto;
989+
margin-right: 15px;
990+
}
991+
992+
993+
994+
}
995+
996+
.has-items {
997+
padding-bottom: 20px;
998+
border-bottom: 1px solid lightgrey;
999+
}
1000+
1001+
.file-contents {
1002+
padding-top: 20px;
1003+
}
1004+
1005+
1006+
}

git-webui/src/share/git-webui/webui/js/git-webui.js

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,17 +1841,100 @@ webui.DiscardedView = function(mainView) {
18411841
mainView.switchTo(self.element);
18421842
};
18431843

1844-
self.getDiscardedStates = function() {
1844+
1845+
self.update = function() {
1846+
self.discarded = [];
1847+
discardedList.innerHTML = '';
1848+
$('.file-contents').html('');
1849+
$('.contents-menu').removeClass("has-items");
1850+
$('.external-name').text('');
1851+
$('.restore-discarded').html('');
1852+
1853+
// TODO: Empty the discarded list properly
18451854
$.get("discarded-states", function(discarded) {
1846-
console.log(discarded);
1855+
self.discarded = JSON.parse(discarded);
1856+
if (self.discarded.length == 0) {
1857+
discardedList.innerHTML = '<h4>You have no saved discarded states</h4>';
1858+
}
1859+
1860+
self.populateUiWithDiscardedStates();
18471861
});
1862+
1863+
18481864
}
18491865

1850-
self.update = function() {
1851-
self.getDiscardedStates();
1866+
1867+
1868+
self.populateUiWithDiscardedStates = function() {
1869+
self.discarded.forEach((discardedState, ind) => {
1870+
var discardedListEntry = $(
1871+
'<a class="log-entry list-group-item">' +
1872+
'<header>' +
1873+
'<h6 class="file-internalname">' + discardedState.InternalName + '</h6>' +
1874+
'<span class="discard-date">' + self.formatTimestamp(discardedState.Timestamp) + '</span>' +
1875+
'</header>' +
1876+
'<span> Branch: ' + discardedState.Branch + ' </span> <br>' +
1877+
'<span> User: '+ discardedState.Username + '</span>' +
1878+
1879+
'</a>'
1880+
);
1881+
1882+
discardedListEntry.on("click", function() {
1883+
$('.log-entry.list-group-item').removeClass('active');
1884+
$(this).addClass('active');
1885+
1886+
$('.contents-menu').addClass("has-items");
1887+
$('.external-name').text(self.discarded[ind].FullExternalName);
1888+
1889+
var btn = $('<button class="btn btn-sm btn-primary restore-discarded-btn">Restore</button>')[0];
1890+
var discardElement = $('.restore-discarded')[0];
1891+
discardElement.innerHTML = '';
1892+
discardElement.appendChild(btn);
1893+
1894+
$('.restore-discarded-btn').off("click").on("click", function() {
1895+
$.post("restore-discarded", {file: discardedState.Id}, function(message) {
1896+
if (message.trim() == "Please commit changes to file before restoring discarded state") {
1897+
webui.showError(message);
1898+
} else {
1899+
webui.showSuccess(message);
1900+
}
1901+
1902+
self.update();
1903+
});
1904+
});
1905+
1906+
$('.file-contents').html('<pre>' + discardedState.Contents + '</pre>');
1907+
});
1908+
1909+
1910+
discardedListEntry.prependTo(discardedList)[0];
1911+
});
18521912
}
1913+
/// This function takes in an IRIS timestamp format makes it use the "date, time" format
1914+
self.formatTimestamp = function(timestamp) {
1915+
var timestampArr = timestamp.split("T");
1916+
return timestampArr[0] + ', ' + timestampArr[1].slice(0, -1);
1917+
}
1918+
1919+
self.element = $(
1920+
'<div class="row" id="discardedView">' +
1921+
'<div class="col-sm-7">' +
1922+
'<div id="discardedList"></div>' +
1923+
'</div>' +
1924+
'<div class="col-sm-5">' +
1925+
'<div class="contents-menu">' +
1926+
'<div class="nav-item external-name"></div>' +
1927+
'<div class="nav-item restore-discarded"></div>' +
1928+
'</div>' +
1929+
'<div class="container file-contents">' +
18531930

1854-
self.element = $('<div id="discardedView"></div>')[0];
1931+
'</div>' +
1932+
'</div>' +
1933+
'</div>'
1934+
1935+
)[0];
1936+
self.discarded = [];
1937+
var discardedList = $("#discardedList", self.element)[0];
18551938

18561939
}
18571940

0 commit comments

Comments
 (0)