diff --git a/src/dotnet/APIView/APIViewWeb/Client/css/pages/review.scss b/src/dotnet/APIView/APIViewWeb/Client/css/pages/review.scss index 262f2e81ef6..a698bc18f83 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/css/pages/review.scss +++ b/src/dotnet/APIView/APIViewWeb/Client/css/pages/review.scss @@ -1,8 +1,29 @@ @import "../shared/mixins.scss"; -#review-info-bar { - font-size: small; - background-color: var(--base-fg-color); +#review-info-bar > .SumoSelect:nth-of-type(even) { + width: 20%; +} + +#review-info-bar > .SumoSelect:nth-of-type(odd) { + width: 10%; +} + +#revision-select ~ .optWrapper { + width: auto; + min-width: 250px; +} + +#diff-select ~ .optWrapper { + width: auto; + min-width: 250px; +} + +#revision-select { + width: 20%; +} + +#diff-select { + width: 20%; } .breadcrumb .icon-language { @@ -13,7 +34,7 @@ #review-left { max-width: none; min-width: 10px; - height: calc(100vh - 120px); + height: calc(100vh - 135px); overflow: auto; max-height: 100vh; padding: 5px 0px 5px 10px; @@ -27,7 +48,7 @@ #review-right { max-width: 100%; min-width: 100px; - height: calc(100vh - 120px); + height: calc(100vh - 135px); padding: 0px; overflow: auto; background-color: var(--base-fg-color); diff --git a/src/dotnet/APIView/APIViewWeb/Client/css/shared/language-customizations.scss b/src/dotnet/APIView/APIViewWeb/Client/css/shared/language-customizations.scss index 063478b032e..c5bcb41e33d 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/css/shared/language-customizations.scss +++ b/src/dotnet/APIView/APIViewWeb/Client/css/shared/language-customizations.scss @@ -3,6 +3,7 @@ width: 31px; display: inline-block; vertical-align: middle; + padding-inline: 5px; } .java-variant { @@ -165,67 +166,67 @@ .icon-csharp { @extend .icon-language; - background: url(/icons/csharp-original.svg) center/contain no-repeat; + background: url(/icons/csharp-original.svg) center no-repeat; } .icon-javascript { @extend .icon-language; - background: url(/icons/javascript-original.svg) center/contain no-repeat; + background: url(/icons/javascript-original.svg) center no-repeat; } .icon-python { @extend .icon-language; - background: url(/icons/python-original.svg) center/contain no-repeat; + background: url(/icons/python-original.svg) center no-repeat; } .icon-c { @extend .icon-language; - background: url(/icons/c-original.svg) center/contain no-repeat; + background: url(/icons/c-original.svg) center no-repeat; } .icon-cplusplus { @extend .icon-language; - background: url(/icons/cplusplus-original.svg) center/contain no-repeat; + background: url(/icons/cplusplus-original.svg) center no-repeat; } .icon-go { @extend .icon-language; - background: url(/icons/go-original.svg) center/contain no-repeat; + background: url(/icons/go-original.svg) center no-repeat; } .icon-java { @extend .icon-language; - background: url(/icons/java-original.svg) center/contain no-repeat; + background: url(/icons/java-original.svg) center no-repeat; } .icon-java-spring { @extend .icon-language; - background: url(/icons/java-spring-original.svg) center/contain no-repeat; + background: url(/icons/java-spring-original.svg) center no-repeat; } .icon-java-android { @extend .icon-language; - background: url(/icons/java-android-original.svg) center/contain no-repeat; + background: url(/icons/java-android-original.svg) center no-repeat; } .icon-swift { @extend .icon-language; - background: url(/icons/swift-original.svg) center/contain no-repeat; + background: url(/icons/swift-original.svg) center no-repeat; } .icon-kotlin { @extend .icon-language; - background: url(/icons/kotlin-original.svg) center/contain no-repeat; + background: url(/icons/kotlin-original.svg) center no-repeat; } .icon-json { @extend .icon-language; - background: url(/icons/json-original.svg) center/contain no-repeat; + background: url(/icons/json-original.svg) center no-repeat; } .icon-swagger { @extend .icon-language; - background: url(/icons/swagger-original.svg) center/contain no-repeat; + background: url(/icons/swagger-original.svg) center no-repeat; } .icon-typespec { @@ -241,9 +242,9 @@ } .icon-chevron-right { - background: url(/icons/chevron-right.svg) center/contain no-repeat; + background: url(/icons/chevron-right.svg) center no-repeat; } .icon-chevron-up { - background: url(/icons/chevron-up.svg) center/contain no-repeat; + background: url(/icons/chevron-up.svg) center no-repeat; } \ No newline at end of file diff --git a/src/dotnet/APIView/APIViewWeb/Client/css/shared/mixins.scss b/src/dotnet/APIView/APIViewWeb/Client/css/shared/mixins.scss index cd072bb7b65..857ad912806 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/css/shared/mixins.scss +++ b/src/dotnet/APIView/APIViewWeb/Client/css/shared/mixins.scss @@ -31,7 +31,7 @@ min-height: calc(100vh - 100px); max-height: calc(100vh - 100px); overflow-y: auto; - margin-top: 70px; + margin-top: 85px; } @mixin review-approval-border { diff --git a/src/dotnet/APIView/APIViewWeb/Client/css/shared/off-canvas.scss b/src/dotnet/APIView/APIViewWeb/Client/css/shared/off-canvas.scss index 8213bcf5d04..afe3be653b7 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/css/shared/off-canvas.scss +++ b/src/dotnet/APIView/APIViewWeb/Client/css/shared/off-canvas.scss @@ -60,14 +60,6 @@ } } -#review-right-offcanvas-toggle, #samples-right-offcanvas-toggle, #revisions-right-offcanvas-toggle { - + .btn-sm { - padding: 0.05rem 0.4rem; - font-size: 0.775rem; - border-radius: 0.2rem; - } -} - #apiRevisions-context, #samplesRevisions-context { @include offcanvas-context-large } diff --git a/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.module.ts b/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.module.ts index 2d48bd8b664..f18c9a3919a 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.module.ts +++ b/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.module.ts @@ -490,6 +490,20 @@ export function addClickEventToClassesInSections() { }); } +/** + * Add Select Event Handlers to API Revision Select + */ +export function addSelectEventToAPIRevisionSelect() { + $('#revision-select, #diff-select').each(function (index, value) { + $(this).on('change', function () { + var url = $(this).find(":selected").val(); + if (url) { + window.location.href = url as string; + } + }); + }); +} + /** * Check if targetAnchor is present, if its not present, expand the section and scroll to the targetAnchor * @param { String } uriHash the hash/id of the anchor we are looking for diff --git a/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.ts b/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.ts index da557bdd750..7ce533d9540 100644 --- a/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.ts +++ b/src/dotnet/APIView/APIViewWeb/Client/src/pages/review.ts @@ -17,7 +17,13 @@ $(() => { rvM.hideCheckboxesIfNotApplicable(); // Run when document is ready - $(function() { + $(function () { + // Enable SumoSelect + ($("#revision-select")).SumoSelect({ search: true, searchText: 'Search Revisions...' }); + ($("#diff-select")).SumoSelect({ search: true, searchText: 'Search Revisons for Diff...' }); + ($("#revision-type-select")).SumoSelect(); + ($("#diff-revision-type-select")).SumoSelect(); + // Update codeLine Section state after page refresh const shownSectionHeadingLineNumbers = sessionStorage.getItem("shownSectionHeadingLineNumbers"); @@ -141,6 +147,43 @@ $(() => { $(this).get(0).scrollIntoView({ block: "center"}); }); + /* DROPDOWN FILTER FOR REVIEW, REVISIONS AND DIFF (UPDATES REVIEW PAGE ON CHANGE) + --------------------------------------------------------------------------------------------------------------------------------------------------------*/ + rvM.addSelectEventToAPIRevisionSelect(); + + $('#revision-type-select, #diff-revision-type-select').each(function (index, value) { + $(this).on('change', function () { + const pageIds = hp.getReviewAndRevisionIdFromUrl(window.location.href); + const reviewId = pageIds["reviewId"]; + const apiRevisionId = pageIds["revisionId"]; + + const select = (index == 0) ? $('#revision-select') : $('#diff-select'); + const text = (index == 0) ? 'Revisions' : 'Revisions for Diff'; + + let uri = (index == 0) ? '?handler=APIRevisionsPartial' : '?handler=APIDiffRevisionsPartial'; + uri = uri + `&reviewId=${reviewId}`; + uri = uri + `&apiRevisionId=${apiRevisionId}`; + uri = uri + '&apiRevisionType=' + $(this).find(":selected").val(); + + $.ajax({ + url: uri + }).done(function (partialViewResult) { + const id = select.attr('id'); + const selectUpdate = $(``); + selectUpdate.html(partialViewResult); + select.parent().replaceWith(selectUpdate); + ($(`#${id}`)).SumoSelect({ placeholder: `Select ${text}...`, search: true, searchText: `Search ${text}...` }) + + // Disable Diff Revision Select until a revision is selected + if (index == 0) { + ($('#diff-revision-type-select')[0]).sumo.disable(); + ($('#diff-select')[0]).sumo.disable(); + } + rvM.addSelectEventToAPIRevisionSelect(); + }); + }); + }); + /* BUTTON FOR REQUEST REVIEW (CHANGES BETWEEN REQUEST ALL AND REQUEST SELECTED IN THE REQUEST APPROVAL SECTION) --------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/src/dotnet/APIView/APIViewWeb/LeanModels/ReviewRevisionPageModels.cs b/src/dotnet/APIView/APIViewWeb/LeanModels/ReviewRevisionPageModels.cs index 21aafe22389..0c725225f23 100644 --- a/src/dotnet/APIView/APIViewWeb/LeanModels/ReviewRevisionPageModels.cs +++ b/src/dotnet/APIView/APIViewWeb/LeanModels/ReviewRevisionPageModels.cs @@ -32,4 +32,15 @@ public class ReviewContentModel public ReviewContentModelDirective Directive { get; set; } public Dictionary CrossLanguageViewContent { get; set; } = new Dictionary(); } + + public class ReviewBadgeModel + { + public ReviewListItemModel Review { get; set; } + public IEnumerable APIRevisions { get; set; } + public APIRevisionListItemModel ActiveAPIRevision { get; set; } + public APIRevisionListItemModel DiffAPIRevision { get; set; } + public UserPreferenceModel UserPreference { get; set; } + public bool? ShowDocumentation { get; set; } + public bool? ShowDiffOnly { get; set; } + } } diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Conversation.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Conversation.cshtml index c0c660f43c0..21b33566a93 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Conversation.cshtml +++ b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Conversation.cshtml @@ -10,7 +10,11 @@ }
- + @{ + var reviewBadgeModel = new ReviewBadgeModel(); + reviewBadgeModel.Review = Model.Review; + } +
@{ diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml index 30be6073cab..2751e19711c 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml +++ b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml @@ -573,8 +573,18 @@
-
- +
+ @{ + var reviewBadgeModel = new ReviewBadgeModel(); + reviewBadgeModel.Review = Model.ReviewContent.Review; + reviewBadgeModel.APIRevisions = Model.ReviewContent.APIRevisions; + reviewBadgeModel.ActiveAPIRevision = Model.ReviewContent.ActiveAPIRevision; + reviewBadgeModel.DiffAPIRevision = Model.ReviewContent.DiffAPIRevision; + reviewBadgeModel.UserPreference = Model.UserPreference; + reviewBadgeModel.ShowDocumentation = Model.ShowDocumentation; + reviewBadgeModel.ShowDiffOnly = Model.ShowDiffOnly; + } +
diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml.cs b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml.cs index 938f9067a03..d2e24577a66 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml.cs +++ b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml.cs @@ -190,6 +190,71 @@ public async Task OnGetCodeLineSectionAsync( return Partial("_CodeLinePartial", sectionKey); } + /// + /// Get Revisions Partial + /// + /// + /// + /// + /// + /// + public async Task OnGetAPIRevisionsPartialAsync(string reviewId, APIRevisionType apiRevisionType, bool showDoc = false, bool showDiffOnly = false) + { + var revisions = await _apiRevisionsManager.GetAPIRevisionsAsync(reviewId); + revisions = revisions.Where(r => r.APIRevisionType == apiRevisionType).OrderByDescending(c => c.CreatedOn).ToList(); + (IEnumerable revisions, APIRevisionListItemModel activeRevision, APIRevisionListItemModel diffRevision, bool forDiff, bool showDocumentation, bool showDiffOnly) revisionSelectModel = ( + revisions: revisions, + activeRevision: default(APIRevisionListItemModel), + diffRevision: default(APIRevisionListItemModel), + forDiff: false, + showDocumentation: showDoc, + showDiffOnly: showDiffOnly + ); + return Partial("_RevisionSelectPickerPartial", revisionSelectModel); + } + + /// + /// Get Diff Revisions Partial + /// + /// + /// + /// + /// + /// + /// + public async Task OnGetAPIDiffRevisionsPartialAsync(string reviewId, string apiRevisionId, APIRevisionType apiRevisionType, bool showDoc = false, bool showDiffOnly = false) + { + var apiRevisions = await _apiRevisionsManager.GetAPIRevisionsAsync(reviewId); + if (apiRevisions.IsNullOrEmpty()) + { + var notifcation = new NotificationModel() { Message = $"This review has no valid apiRevisons", Level = NotificatonLevel.Warning }; + await _signalRHubContext.Clients.Group(User.GetGitHubLogin()).SendAsync("RecieveNotification", notifcation); + } + + APIRevisionListItemModel activeRevision = default(APIRevisionListItemModel); + + if (!Guid.TryParse(apiRevisionId, out _)) + { + activeRevision = await _apiRevisionsManager.GetLatestAPIRevisionsAsync(reviewId, apiRevisions); + } + else + { + activeRevision = apiRevisions.FirstOrDefault(r => r.Id == apiRevisionId); + } + + var revisionsForDiff = apiRevisions.Where(r => r.APIRevisionType == apiRevisionType && r.Id != activeRevision.Id).OrderByDescending(c => c.CreatedOn).ToList(); + + (IEnumerable revisions, APIRevisionListItemModel activeRevision, APIRevisionListItemModel diffRevision, bool forDiff, bool showDocumentation, bool showDiffOnly) revisionSelectModel = ( + revisions: revisionsForDiff, + activeRevision: activeRevision, + diffRevision: default(APIRevisionListItemModel), + forDiff: true, + showDocumentation: showDoc, + showDiffOnly: showDiffOnly + ); + return Partial("_RevisionSelectPickerPartial", revisionSelectModel); + } + /// /// Toggle Review State /// diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Revisions.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Revisions.cshtml index b91d66c18b3..529f911125d 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Revisions.cshtml +++ b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Revisions.cshtml @@ -11,7 +11,11 @@ }
- + @{ + var reviewBadgeModel = new ReviewBadgeModel(); + reviewBadgeModel.Review = Model.Review; + } +
diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Samples.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Samples.cshtml index c2b396e9b5c..622a21f100f 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Samples.cshtml +++ b/src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Samples.cshtml @@ -25,7 +25,11 @@
- + @{ + var reviewBadgeModel = new ReviewBadgeModel(); + reviewBadgeModel.Review = Model.Review; + } +
diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Shared/_ReviewBadge.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Shared/_ReviewBadge.cshtml index c37bea7be0c..a3cd6221497 100644 --- a/src/dotnet/APIView/APIViewWeb/Pages/Shared/_ReviewBadge.cshtml +++ b/src/dotnet/APIView/APIViewWeb/Pages/Shared/_ReviewBadge.cshtml @@ -3,49 +3,143 @@ @using System.Text.RegularExpressions; @using APIViewWeb.Helpers; @using APIViewWeb.LeanModels; -@using APIViewWeb.Models -@model (ReviewListItemModel review, APIRevisionListItemModel activeAPIRevision, APIRevisionListItemModel diffAPIRevision, UserPreferenceModel userPreference); +@using APIViewWeb.Models; +@model ReviewBadgeModel;
- + } +
@if (TempData["page"].Equals("api")) { - if (Model.userPreference != null && Model.userPreference.HideReviewPageOptions.HasValue && Model.userPreference.HideReviewPageOptions == true) + if (Model.UserPreference != null && Model.UserPreference.HideReviewPageOptions.HasValue && Model.UserPreference.HideReviewPageOptions == true) { } @@ -53,11 +147,11 @@ { } - + } @if (TempData["page"].Equals("revisions")) { - if (Model.userPreference != null && Model.userPreference.HideRevisionsPageOptions.HasValue && Model.userPreference.HideRevisionsPageOptions == true) + if (Model.UserPreference != null && Model.UserPreference.HideRevisionsPageOptions.HasValue && Model.UserPreference.HideRevisionsPageOptions == true) { } @@ -65,11 +159,11 @@ { } - + } @if (TempData["page"].Equals("samples")) { - if (Model.userPreference != null && Model.userPreference.HideSamplesPageOptions.HasValue && Model.userPreference.HideSamplesPageOptions == true) + if (Model.UserPreference != null && Model.UserPreference.HideSamplesPageOptions.HasValue && Model.UserPreference.HideSamplesPageOptions == true) { } @@ -77,7 +171,7 @@ { } - + }
diff --git a/src/dotnet/APIView/APIViewWeb/Pages/Shared/_RevisionSelectPickerPartial.cshtml b/src/dotnet/APIView/APIViewWeb/Pages/Shared/_RevisionSelectPickerPartial.cshtml new file mode 100644 index 00000000000..6316411e0b0 --- /dev/null +++ b/src/dotnet/APIView/APIViewWeb/Pages/Shared/_RevisionSelectPickerPartial.cshtml @@ -0,0 +1,57 @@ +@using APIViewWeb.Helpers +@using APIViewWeb.LeanModels +@using APIViewWeb.Models +@model (IEnumerable revisions, APIRevisionListItemModel activeRevision, APIRevisionListItemModel diffRevision, bool forDiff, bool showDocumentation, bool showDiffOnly) + +@if (@Model.revisions.Any()) +{ + var selectedRevisionLabel = String.Empty; + if (!@Model.forDiff && @Model.activeRevision != default(APIRevisionListItemModel)) + { + selectedRevisionLabel = PageModelHelpers.ResolveRevisionLabel(@Model.activeRevision, false); + } + else if (@Model.diffRevision != default(APIRevisionListItemModel)) + { + selectedRevisionLabel = PageModelHelpers.ResolveRevisionLabel(@Model.diffRevision, false); + } + + if (String.IsNullOrEmpty(selectedRevisionLabel)) + { + + } + + @foreach (var revision in @Model.revisions) + { + var optionClass = (revision.IsApproved) ? "option-approved" : "option-pending"; + + var urlValue = @Url.ActionLink("Review", "Assemblies", new + { + id = revision.ReviewId, + revisionId = @revision.Id, + doc = @Model.showDocumentation + }); + + if (Model.forDiff) + { + urlValue = @Url.ActionLink("Review", "Assemblies", new + { + id = revision.ReviewId, + revisionId = @Model.activeRevision.Id, + diffOnly = Model.showDiffOnly, + doc = @Model.showDocumentation, + diffRevisionId = @revision.Id + }); + } + + var revisionLabel = PageModelHelpers.ResolveRevisionLabel(@revision, false); + + if (!String.IsNullOrEmpty(selectedRevisionLabel) && revisionLabel == selectedRevisionLabel) + { + + } + else + { + + } + } +} \ No newline at end of file