Add Option for Hiding Left Navigation (#3686)
* Add option for hiding left navigation * Improve reviews page command bar * Persist page settings as user preferences * Smart update cache * Add auto mapper for mapping between models
This commit is contained in:
Родитель
13a0b3bf6f
Коммит
8e661c62b1
|
@ -22,6 +22,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.13.0" />
|
||||
<PackageReference Include="CsvHelper" Version="27.2.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0-beta4" />
|
||||
|
|
|
@ -571,6 +571,7 @@ code {
|
|||
cursor: pointer;
|
||||
width: 1%;
|
||||
white-space: nowrap;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.line-details table {
|
||||
|
|
|
@ -1,33 +1 @@
|
|||
import Split from "split.js";
|
||||
|
||||
addEventListener("load", () => {
|
||||
$(".nav-list-toggle").click(function () {
|
||||
$(this).parents(".nav-list-group").first().toggleClass("nav-list-collapsed");
|
||||
});
|
||||
});
|
||||
|
||||
$(() => {
|
||||
/* 992px matches bootstrap col-lg min-width */
|
||||
($('.namespace-view') as any).stickySidebar({ minWidth: 992 });
|
||||
|
||||
/* Split left and right review panes using split.js */
|
||||
const rl = $('#review-left');
|
||||
const rr = $('#review-right');
|
||||
|
||||
if (rl.length && rr.length) {
|
||||
Split(['#review-left', '#review-right'], {
|
||||
direction: 'horizontal',
|
||||
sizes: [17, 83],
|
||||
elementStyle: (dimension, size, gutterSize) => {
|
||||
return {
|
||||
'flex-basis': `calc(${size}% - ${gutterSize}px`
|
||||
}
|
||||
},
|
||||
gutterStyle: (dimension, gutterSize) => {
|
||||
return {
|
||||
'flex-basis': `${gutterSize}px`
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
$(() => {
|
||||
import Split from "split.js";
|
||||
|
||||
$(() => {
|
||||
const SEL_DOC_CLASS = ".documentation";
|
||||
const SHOW_DOC_CHECK_COMPONENT = "#show-documentation-component";
|
||||
const SHOW_DOC_CHECKBOX = ".show-doc-checkbox";
|
||||
|
@ -6,15 +8,73 @@
|
|||
const SHOW_DIFFONLY_CHECKBOX = ".show-diffonly-checkbox";
|
||||
const SHOW_DIFFONLY_HREF = ".show-diffonly";
|
||||
const HIDE_LINE_NUMBERS = "#hide-line-numbers";
|
||||
const HIDE_LEFT_NAVIGATION = "#hide-left-navigation";
|
||||
|
||||
hideCheckboxIfNoDocs();
|
||||
|
||||
/* FUNCTIONS
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
function hideCheckboxIfNoDocs() {
|
||||
if ($(SEL_DOC_CLASS).length == 0) {
|
||||
$(SHOW_DOC_CHECK_COMPONENT).hide();
|
||||
}
|
||||
if ($(SEL_DOC_CLASS).length == 0) {
|
||||
$(SHOW_DOC_CHECK_COMPONENT).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function splitReviewPageContent() {
|
||||
/* Split left and right review panes using split.js */
|
||||
const rl = $('#review-left');
|
||||
const rr = $('#review-right');
|
||||
|
||||
if (rl.length && rr.length) {
|
||||
Split(['#review-left', '#review-right'], {
|
||||
direction: 'horizontal',
|
||||
sizes: [17, 83],
|
||||
elementStyle: (dimension, size, gutterSize) => {
|
||||
return {
|
||||
'flex-basis': `calc(${size}% - ${gutterSize}px`
|
||||
}
|
||||
},
|
||||
gutterStyle: (dimension, gutterSize) => {
|
||||
return {
|
||||
'flex-basis': `${gutterSize}px`
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Updated Page Setting by Updating UserPreference
|
||||
function updatePageSettings(callBack) {
|
||||
var hideLineNumbers = $(HIDE_LINE_NUMBERS).prop("checked");
|
||||
var hideLeftNavigation = $(HIDE_LEFT_NAVIGATION).prop("checked");
|
||||
var uri = `?handler=updatepagesettings&hideLineNumbers=${hideLineNumbers}&hideLeftNavigation=${hideLeftNavigation}`;
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: uri
|
||||
}).done(callBack());
|
||||
}
|
||||
|
||||
/* ADD EVENT LISTENER FOR TOGGLING LEFT NAVIGATION
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
addEventListener("load", () => {
|
||||
$(".nav-list-toggle").click(function () {
|
||||
$(this).parents(".nav-list-group").first().toggleClass("nav-list-collapsed");
|
||||
});
|
||||
});
|
||||
|
||||
/* SPLIT REVIEW PAGE CONTENT
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* 992px matches bootstrap col-lg min-width */
|
||||
($('.namespace-view') as any).stickySidebar({ minWidth: 992 });
|
||||
if (!$("#review-left").hasClass("d-none"))
|
||||
{
|
||||
// Only Add Split gutter if left navigation is not hidden
|
||||
splitReviewPageContent();
|
||||
}
|
||||
|
||||
/* TOGGLE PAGE OPTIONS
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
$(SHOW_DOC_CHECKBOX).on("click", e => {
|
||||
$(SHOW_DOC_HREF)[0].click();
|
||||
});
|
||||
|
@ -24,17 +84,32 @@
|
|||
});
|
||||
|
||||
$(HIDE_LINE_NUMBERS).on("click", e => {
|
||||
$(".line-number").toggleClass("d-none");
|
||||
});
|
||||
|
||||
/* DIFF BUTTON (UPDATES REVIEW PAGE ON CLICK)
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
$('.diff-button').each(function(index, value){
|
||||
$(this).on('click', function () {
|
||||
window.location.href = $(this).val() as string;
|
||||
updatePageSettings(function(){
|
||||
$(".line-number").toggleClass("d-none");
|
||||
});
|
||||
});
|
||||
|
||||
$(HIDE_LEFT_NAVIGATION).on("click", e => {
|
||||
updatePageSettings(function(){
|
||||
var leftContainer = $("#review-left");
|
||||
var rightContainer = $("#review-right");
|
||||
var gutter = $(".gutter-horizontal");
|
||||
|
||||
if (leftContainer.hasClass("d-none")) {
|
||||
leftContainer.removeClass("d-none");
|
||||
rightContainer.removeClass("col-12");
|
||||
rightContainer.addClass("col-10");
|
||||
splitReviewPageContent();
|
||||
}
|
||||
else {
|
||||
leftContainer.addClass("d-none");
|
||||
rightContainer.css("flex-basis", "100%");
|
||||
gutter.remove();
|
||||
rightContainer.removeClass("col-10");
|
||||
rightContainer.addClass("col-12");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* DROPDOWN FILTER FOR REVIEW, REVISIONS AND DIFF (UPDATES REVIEW PAGE ON CHANGE)
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
@ -59,7 +134,6 @@
|
|||
var caretDirection = caretClasses ? caretClasses.split(' ').filter(c => c.startsWith('fa-angle-'))[0] : "";
|
||||
var foldableClassPrefix = headingRowClasses ? headingRowClasses.split(' ').filter(c => c.endsWith('-heading'))[0].replace("-heading", "") : "";
|
||||
|
||||
|
||||
if (triggeringClass == "row-fold-caret" && caretDirection == "fa-angle-down") {
|
||||
var classesOfRowsToHide = [`${foldableClassPrefix}-content`];
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
$(() => {
|
||||
// Search
|
||||
const defaultPageSize = 50;
|
||||
const reviewsFilterPartial = $( '#reviews-filter-partial' );
|
||||
const languageFilter = $( '#language-filter-bootstraps-select' );
|
||||
|
@ -77,10 +76,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Triggers partial page update to retriev properties for poulating filter dropdowns
|
||||
// Fetches data for populating dropdown options
|
||||
function updateFilterDropDown(filter, query)
|
||||
{
|
||||
// update tags dropdown select
|
||||
var uri = `?handler=reviews${query}`;
|
||||
var urlParams = new URLSearchParams(location.search);
|
||||
if (urlParams.has(query))
|
||||
|
@ -97,20 +95,20 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Update content of dropdown on page load
|
||||
// Fetch content of dropdown on page load
|
||||
$(document).ready(function() {
|
||||
updateFilterDropDown(languageFilter, "languages");
|
||||
updateFilterDropDown(languageFilter, "languages"); // Pulls languages data from DB
|
||||
addPaginationEventHandlers();
|
||||
});
|
||||
|
||||
|
||||
// Update when any dropdown is changed
|
||||
// Update list of reviews when any dropdown is changed
|
||||
[languageFilter, stateFilter, statusFilter, typeFilter].forEach(function(value, index) {
|
||||
value.on('hidden.bs.select', function() {
|
||||
updateListedReviews();
|
||||
});
|
||||
});
|
||||
|
||||
// Update list of reviews based on search input
|
||||
searchBox.on('input', _.debounce(function(e) {
|
||||
updateListedReviews();
|
||||
}, 600));
|
||||
|
@ -119,6 +117,7 @@
|
|||
updateListedReviews();
|
||||
});
|
||||
|
||||
// Reset list of reviews as well as filters
|
||||
resetButton.on('click', function(e) {
|
||||
(<any>languageFilter).selectpicker('deselectAll');
|
||||
(<any>stateFilter).selectpicker('deselectAll').selectpicker('val', 'Open');
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
using APIViewWeb.Models;
|
||||
using AutoMapper;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace APIViewWeb.Helpers
|
||||
{
|
||||
public class AutoMapperProfiles : Profile
|
||||
{
|
||||
public AutoMapperProfiles()
|
||||
{
|
||||
CreateMap<UserPreferenceModel, UserPreferenceModel>()
|
||||
.ForMember(dest => dest.UserName, opt => opt.MapFrom((src, dest) => src.UserName != null ? src.UserName : dest.UserName))
|
||||
.ForMember(dest => dest.Language, opt => opt.MapFrom((src, dest) => src.Language != null ? src.Language : dest.Language))
|
||||
.ForMember(dest => dest.FilterType, opt => opt.MapFrom((src, dest) => src.FilterType != null ? src.FilterType : dest.FilterType))
|
||||
.ForMember(dest => dest.State, opt => opt.MapFrom((src, dest) => src.State != null ? src.State : dest.State))
|
||||
.ForMember(dest => dest.Status, opt => opt.MapFrom((src, dest) => src.Status != null ? src.Status : dest.Status))
|
||||
.ForMember(dest => dest.HideLineNumbers, opt => opt.MapFrom((src, dest) => src.HideLineNumbers != null ? src.HideLineNumbers : dest.HideLineNumbers))
|
||||
.ForMember(dest => dest.HideLeftNavigation, opt => opt.MapFrom((src, dest) => src.HideLeftNavigation != null ? src.HideLeftNavigation : dest.HideLeftNavigation));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using CsvHelper.Configuration.Attributes;
|
||||
|
||||
namespace APIViewWeb.Models
|
||||
|
@ -12,5 +13,13 @@ namespace APIViewWeb.Models
|
|||
public IEnumerable<string> Language { get; set; }
|
||||
[Name("FilterType")]
|
||||
public IEnumerable<ReviewType> FilterType { get; set; }
|
||||
[Name("State")]
|
||||
public IEnumerable<string> State { get; set; }
|
||||
[Name("Status")]
|
||||
public IEnumerable<string> Status { get; set; }
|
||||
[Name("HideLineNumbers")]
|
||||
public bool? HideLineNumbers { get; set; }
|
||||
[Name("HideLeftNavigation")]
|
||||
public bool? HideLeftNavigation { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,20 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
List<string> search = null, List<string> languages=null, List<string> state =null,
|
||||
List<string> status =null, List<string> type =null, int pageNo=1, int pageSize=_defaultPageSize, string sortField=_defaultSortField)
|
||||
{
|
||||
if (search.Count == 0 && languages.Count == 0 && state.Count == 0 && status.Count == 0 && type.Count == 0)
|
||||
{
|
||||
UserPreferenceModel userPreference = _preferenceCache.GetUserPreferences(User.GetGitHubLogin());
|
||||
if (userPreference != null)
|
||||
{
|
||||
languages = userPreference.Language.ToList();
|
||||
state = userPreference.State.ToList();
|
||||
status = userPreference.Status.ToList();
|
||||
type = new List<string>();
|
||||
if (userPreference.FilterType.Contains(ReviewType.Manual)) { type.Add("Manual"); }
|
||||
if (userPreference.FilterType.Contains(ReviewType.Automatic)) { type.Add("Automatic"); }
|
||||
if (userPreference.FilterType.Contains(ReviewType.PullRequest)) { type.Add("PullRequest"); }
|
||||
}
|
||||
}
|
||||
await RunGetRequest(search, languages, state, status, type, pageNo, pageSize, sortField);
|
||||
}
|
||||
|
||||
|
@ -51,6 +65,14 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
|
||||
public async Task<PartialViewResult> OnGetReviewsLanguagesAsync(List<string> selectedLanguages = null)
|
||||
{
|
||||
if (selectedLanguages.Count == 0)
|
||||
{
|
||||
UserPreferenceModel userPreference = _preferenceCache.GetUserPreferences(User.GetGitHubLogin());
|
||||
if (userPreference != null)
|
||||
{
|
||||
selectedLanguages = userPreference.Language.ToList();
|
||||
}
|
||||
}
|
||||
ReviewsProperties.Languages.All = await _manager.GetReviewPropertiesAsync("Revisions[0].Files[0].Language");
|
||||
selectedLanguages = selectedLanguages.Select(x => HttpUtility.UrlDecode(x)).ToList();
|
||||
ReviewsProperties.Languages.Selected = selectedLanguages;
|
||||
|
@ -128,11 +150,12 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
if (type.Contains("Automatic")) { filterTypes.Add((int)ReviewType.Automatic); }
|
||||
if (type.Contains("PullRequest")) { filterTypes.Add((int)ReviewType.PullRequest); }
|
||||
|
||||
_preferenceCache.UpdateUserPreference(new UserPreferenceModel()
|
||||
{
|
||||
_preferenceCache.UpdateUserPreference(new UserPreferenceModel {
|
||||
UserName = User.GetGitHubLogin(),
|
||||
FilterType = filterTypes.Cast<ReviewType>().ToList(),
|
||||
Language = languages
|
||||
Language = languages,
|
||||
State = state,
|
||||
Status = status
|
||||
});
|
||||
|
||||
bool? isApproved = null;
|
||||
|
|
|
@ -6,268 +6,94 @@
|
|||
}
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row mt-2 mb-0 pl-1">
|
||||
<div class="col">
|
||||
<h3 class="mb-0">
|
||||
<div class="row mx-1 px-0 py-2 border-bottom">
|
||||
<div class="col-lg-12 d-flex px-0">
|
||||
@if (Model.Review.Language != null)
|
||||
{
|
||||
var imageSource = String.Empty;
|
||||
@switch (Model.Review.Language.ToLower())
|
||||
{
|
||||
case "c#":
|
||||
imageSource = "icons/csharp-original.svg";
|
||||
break;
|
||||
case "javascript":
|
||||
imageSource = "icons/javascript-original.svg";
|
||||
break;
|
||||
case "python":
|
||||
imageSource = "icons/python-original.svg";
|
||||
break;
|
||||
case "c":
|
||||
imageSource = "icons/c-original.svg";
|
||||
break;
|
||||
case "c++":
|
||||
imageSource = "icons/cplusplus-original.svg";
|
||||
break;
|
||||
case "go":
|
||||
imageSource = "icons/go-original.svg";
|
||||
break;
|
||||
case "java":
|
||||
imageSource = "icons/java-original.svg";
|
||||
break;
|
||||
case "swift":
|
||||
imageSource = "icons/swift-original.svg";
|
||||
break;
|
||||
case "kotlin":
|
||||
imageSource = "icons/kotlin-original.svg";
|
||||
break;
|
||||
case "json":
|
||||
imageSource = "icons/json-original.svg";
|
||||
break;
|
||||
case "swagger":
|
||||
imageSource = "icons/swagger-original.svg";
|
||||
break;
|
||||
}
|
||||
if (String.IsNullOrEmpty(imageSource))
|
||||
{
|
||||
<span class="badge badge-info"><em>@Model.Review.Language</em></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span><img class="mr-2 mt-1 p-1 border rounded" src="~/@imageSource" width="34" alt="@Model.Review.Language" /></span>
|
||||
}
|
||||
}
|
||||
<p class="h6 mb-0 mr-auto">
|
||||
@if (Model.Review.ServiceName != null)
|
||||
{
|
||||
@Model.Review.ServiceName
|
||||
<span> | </span>
|
||||
}
|
||||
<br>
|
||||
<small class="text-muted">@Model.Review.PackageDisplayName</small>
|
||||
@if (Model.Review.Language != null)
|
||||
</p>
|
||||
<div class="my-1">
|
||||
@if (Model.Revision.Approvers.Count > 0)
|
||||
{
|
||||
@switch (Model.Review.Language.ToLower())
|
||||
{
|
||||
case "c#":
|
||||
<span><img class="mx-1" src="~/icons/csharp-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "javascript":
|
||||
<span><img class="mx-1" src="~/icons/javascript-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "python":
|
||||
<span><img class="mx-1" src="~/icons/python-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "c":
|
||||
<span><img class="mx-1" src="~/icons/c-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "c++":
|
||||
<span><img class="mx-1" src="~/icons/cplusplus-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "go":
|
||||
<span><img class="mx-1" src="~/icons/go-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "java":
|
||||
<span><img class="mx-1" src="~/icons/java-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "swift":
|
||||
<span><img class="mx-1" src="~/icons/swift-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "kotlin":
|
||||
<span><img class="mx-1" src="~/icons/kotlin-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "json":
|
||||
<span><img class="mx-1" src="~/icons/json-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
case "swagger":
|
||||
<span><img class="mx-1" src="~/icons/swagger-original.svg" width="40" alt="@Model.Review.Language"></span>
|
||||
break;
|
||||
default:
|
||||
<span class="badge badge-info"><em>@Model.Review.Language</em></span>
|
||||
break;
|
||||
}
|
||||
var approvers = String.Join(", ", Model.Revision.Approvers);
|
||||
<button type="button" class="btn btn-sm shadow-sm btn-success" data-placement="bottom" data-trigger="focus" data-toggle="popover" data-title="Approvers" data-content="@approvers">
|
||||
<i class="fas fa-check-circle"></i> APPROVED
|
||||
<span class="badge badge-light">@Model.Revision.Approvers.Count</span>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-light btn-sm shadow-sm">
|
||||
PENDING
|
||||
</button>
|
||||
}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="col-lg-6 my-1">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-md-4 mt-1 p-0 mr-md-1">
|
||||
<div class="input-group input-group-sm m-0 p-0 shadow-sm" id="review-select-box">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="review-bootstraps-select">Review</label>
|
||||
</div>
|
||||
<select class="selectpicker show-tick p-0" data-style="btn-light btn-sm border rounded-left-0 m-0" data-live-search="true" data-size="10" data-width="calc(100% - 60px)" data-container="body" id="review-bootstraps-select">
|
||||
@foreach(var review in Model.ReviewsForPackage)
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = review.ReviewId
|
||||
});
|
||||
if (review.ReviewId == Model.Review.ReviewId)
|
||||
{
|
||||
<option selected value="@urlValue" data-subtext="Type: @review.FilterType | Language: @review.Language | Author: @review.Author">@review.DisplayName</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@urlValue" data-subtext="Type: @review.FilterType | Language: @review.Language | Author: @review.Author">@review.DisplayName</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mt-1 p-0 mx-md-1">
|
||||
<div class="input-group input-group-sm m-0 p-0 shadow-sm" id="revision-select-box">
|
||||
<div class="input-group-prepend">
|
||||
<label class="input-group-text" for="revisions-bootstraps-select">Revision</label>
|
||||
</div>
|
||||
<select class="selectpicker show-tick p-0" data-style="btn-light btn-sm border rounded-left-0 m-0" data-live-search="true" data-size="10" data-width="calc(100% - 68px)" data-container="body" id="revisions-bootstraps-select">
|
||||
@foreach (var revision in Model.Review.Revisions.Reverse())
|
||||
{
|
||||
var approvedBadge = "<i class='fas fa-check-circle text-success ml-2'></i>";
|
||||
var optionName = revision.IsApproved ? $"{@revision.DisplayName} {@approvedBadge}" : @revision.DisplayName;
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @revision.RevisionId,
|
||||
doc = @Model.ShowDocumentation
|
||||
});
|
||||
if (@revision.DisplayName == @Model.Revision.DisplayName)
|
||||
{
|
||||
<option selected value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mt-1 p-0 ml-md-1">
|
||||
@if (@Model.PreviousRevisions.Any())
|
||||
{
|
||||
<div class="input-group input-group-sm m-0 p-0 shadow-sm" id="diff-select-box">
|
||||
<div class="input-group-prepend" for="diff-bootstraps-select">
|
||||
@if (Model.DiffRevisionId != null)
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @Model.Revision.RevisionId,
|
||||
diffRevisionId = @Model.DiffRevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly
|
||||
});
|
||||
<button class="btn btn-outline-secondary diff-button" type="button" value="@urlValue" aria-label="Diff Button">Diff</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @Model.Revision.RevisionId,
|
||||
diffRevisionId = @Model.PreviousRevisions.Last().RevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly
|
||||
});
|
||||
<button class="btn btn-outline-secondary diff-button" type="button" value="@urlValue" aria-label="Diff Button">Diff</button>
|
||||
}
|
||||
</div>
|
||||
<select class="selectpicker show-tick" data-style="btn-light btn-sm border border-left rounded-left-0" data-size="10" data-width="calc(100% - 39px)" data-live-search="true" data-container="body" aria-label="Diff Review" id="diff-bootstraps-select">
|
||||
if (@Model.DiffRevisionId == null)
|
||||
{
|
||||
<option value="" selected></option>
|
||||
}
|
||||
@foreach (var revision in Model.PreviousRevisions.Reverse())
|
||||
{
|
||||
var approvedBadge = "<span class='badge badge-pill badge-success ml-1 p-1'><i class='fas fa-check-circle'></i> APPROVED</span>";
|
||||
var optionName = revision.IsApproved ? $"{@revision.DisplayName} {@approvedBadge}" : @revision.DisplayName;
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
diffRevisionId = @revision.RevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly,
|
||||
revisionId = @Model.Revision.RevisionId
|
||||
});
|
||||
if (@Model.DiffRevisionId != null)
|
||||
{
|
||||
if (@Model.DiffRevisionId == @revision.RevisionId)
|
||||
{
|
||||
<option value="@urlValue" selected data-content="@optionName"></option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (@Model.DiffRevisionId != @revision.RevisionId)
|
||||
{
|
||||
<option value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 my-1">
|
||||
@if (Model.Review.FilterType != ReviewType.Automatic)
|
||||
{
|
||||
<div class="float-right ml-2 my-1">
|
||||
<form asp-resource="@Model.Review" class="form-inline" method="post" asp-page-handler="ToggleClosed">
|
||||
@if (Model.Review.IsClosed)
|
||||
{
|
||||
<button type="submit" class="btn btn-sm border shadow-sm btn-light">
|
||||
<i class="fa fa-sm fa-undo" aria-hidden="true"></i> Reopen
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn btn-sm border shadow-sm btn-light">
|
||||
<i class="far fa-window-close" aria-hidden="true"></i> Close
|
||||
</button>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
<div class="float-right ml-2 my-1">
|
||||
<form asp-resource="@Model.Review" class="form-inline" method="post" asp-page-handler="ToggleSubscribed">
|
||||
@if (Model.Review.GetUserEmail(User) != null)
|
||||
<div class="my-1 ml-2">
|
||||
@{
|
||||
var popOverContent = $"<b>{Model.ActiveConversations}</b> active revision threads.<br><b>{Model.TotalActiveConversations}</b> total active threads.<br>"
|
||||
+ $"<b>Current Revision:</b> <em>{@Model.Revision.DisplayName}</em>";
|
||||
@if (Model.DiffRevisionId != null)
|
||||
{
|
||||
if (Model.Review.IsUserSubscribed(User))
|
||||
{
|
||||
<button type="submit" class="btn border btn-sm shadow-sm btn-light">
|
||||
<i class="far fa-minus-square" aria-hidden="true"></i> Unsubscribe
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn border btn-sm shadow-sm btn-light">
|
||||
<i class="far fa-plus-square" aria-hidden="true"></i> Subscribe
|
||||
</button>
|
||||
}
|
||||
popOverContent += $"<br><b>Current Diff:</b> <em>{@Model.DiffRevision?.DisplayName}</em>";
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn btn-sm shadow-sm btn-light" disabled data-placement="bottom" data-toggle="tooltip" title="Link a microsoft.com email to your Github account to subscribe">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"></i> Subscribe
|
||||
</button>
|
||||
}
|
||||
</form>
|
||||
<button type="button" class="btn btn-info btn-sm shadow-sm" data-placement="bottom" data-trigger="focus" data-toggle="popover" data-html="true" data-title="Page Info" data-content="@popOverContent">
|
||||
<i class="far fa-comment-alt mr-2"></i><span class="badge badge-light">@Model.ActiveConversations / @Model.TotalActiveConversations</span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="dropdown d-inline-block float-right ml-2 my-1">
|
||||
<a class="btn btn-light btn-sm border shadow-sm dropdown-toggle" href="#" role="button" data-toggle="dropdown">
|
||||
<i class="fas fa-sm fa-sliders-h"></i> Options
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
<input type="checkbox" checked="checked" id="show-comments-checkbox">
|
||||
Show Comments
|
||||
</label>
|
||||
</span>
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
<input type="checkbox" checked="checked" id="show-system-comments-checkbox">
|
||||
Show System Comments
|
||||
</label>
|
||||
</span>
|
||||
<span class="dropdown-item" id="show-documentation-component">
|
||||
<input asp-for="@Model.ShowDocumentation" class="show-doc-checkbox">
|
||||
<a class="text-dark show-document" asp-all-route-data=@Model.GetRoutingData(diffRevisionId: Model.DiffRevisionId, showDocumentation: !Model.ShowDocumentation, showDiffOnly: Model.ShowDiffOnly, revisionId: Model.Revision.RevisionId)>
|
||||
<label> Show Documentation</label>
|
||||
</a>
|
||||
</span>
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="hide-line-numbers">
|
||||
Hide Line Number
|
||||
</label>
|
||||
</span>
|
||||
@if (!String.IsNullOrEmpty(Model.DiffRevisionId))
|
||||
{
|
||||
<span class="dropdown-item">
|
||||
<input asp-for="@Model.ShowDiffOnly" class="show-diffonly-checkbox">
|
||||
<a class="text-dark show-diffonly" asp-all-route-data=@Model.GetRoutingData(diffRevisionId: Model.DiffRevisionId, showDocumentation: Model.ShowDocumentation, showDiffOnly: !Model.ShowDiffOnly, revisionId: Model.Revision.RevisionId)>
|
||||
<label> Show Only Diff</label>
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-right my-1">
|
||||
<div class="my-1">
|
||||
<form asp-resource="@Model.Review" class="form-inline" asp-page-handler="ToggleApproval" method="post" asp-requirement="@ApproverRequirement.Instance">
|
||||
<input type="hidden" name="revisionId" value="@Model.Revision.RevisionId" />
|
||||
@if (Model.DiffRevision == null || Model.DiffRevision.Approvers.Count > 0)
|
||||
|
@ -302,39 +128,237 @@
|
|||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="float-right ml-2 my-1">
|
||||
@{
|
||||
var popOverContent = $"<b>{Model.ActiveConversations}</b> active revision threads.<br><b>{Model.TotalActiveConversations}</b> total active threads.<br>"
|
||||
+ $"<b>Current Revision:</b> <em>{@Model.Revision.DisplayName}</em>";
|
||||
@if (Model.DiffRevisionId != null)
|
||||
<div class="dropdown d-inline-block my-1 ml-2">
|
||||
<a class="btn btn-light btn-sm border shadow-sm dropdown-toggle" href="#" role="button" data-toggle="dropdown">
|
||||
<i class="fas fa-sm fa-sliders-h"></i> Options
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
<input type="checkbox" checked="checked" id="show-comments-checkbox">
|
||||
Show Comments
|
||||
</label>
|
||||
</span>
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
<input type="checkbox" checked="checked" id="show-system-comments-checkbox">
|
||||
Show System Comments
|
||||
</label>
|
||||
</span>
|
||||
<span class="dropdown-item" id="show-documentation-component">
|
||||
<input asp-for="@Model.ShowDocumentation" class="show-doc-checkbox">
|
||||
<a class="text-dark show-document" asp-all-route-data=@Model.GetRoutingData(diffRevisionId: Model.DiffRevisionId, showDocumentation: !Model.ShowDocumentation, showDiffOnly: Model.ShowDiffOnly, revisionId: Model.Revision.RevisionId)>
|
||||
<label> Show Documentation</label>
|
||||
</a>
|
||||
</span>
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
@if (Model.GetUserPreference().HideLineNumbers == true)
|
||||
{
|
||||
<input type="checkbox" id="hide-line-numbers" checked>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" id="hide-line-numbers" >
|
||||
}
|
||||
Hide Line Number
|
||||
</label>
|
||||
</span>
|
||||
<span class="dropdown-item checkbox">
|
||||
<label>
|
||||
@if (Model.GetUserPreference().HideLeftNavigation == true)
|
||||
{
|
||||
<input type="checkbox" id="hide-left-navigation" checked>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" id="hide-left-navigation">
|
||||
}
|
||||
Hide Left Navigation
|
||||
</label>
|
||||
</span>
|
||||
@if (!String.IsNullOrEmpty(Model.DiffRevisionId))
|
||||
{
|
||||
popOverContent += $"<br><b>Current Diff:</b> <em>{@Model.DiffRevision?.DisplayName}</em>";
|
||||
<span class="dropdown-item">
|
||||
<input asp-for="@Model.ShowDiffOnly" class="show-diffonly-checkbox">
|
||||
<a class="text-dark show-diffonly" asp-all-route-data=@Model.GetRoutingData(diffRevisionId: Model.DiffRevisionId, showDocumentation: Model.ShowDocumentation, showDiffOnly: !Model.ShowDiffOnly, revisionId: Model.Revision.RevisionId)>
|
||||
<label> Show Only Diff</label>
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
<button type="button" class="btn btn-info btn-sm shadow-sm" data-placement="bottom" data-trigger="focus" data-toggle="popover" data-html="true" data-title="Page Info" data-content="@popOverContent">
|
||||
<i class="far fa-comment-alt mr-2"></i><span class="badge badge-light">@Model.ActiveConversations / @Model.TotalActiveConversations</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-1 ml-2">
|
||||
<form asp-resource="@Model.Review" class="form-inline" method="post" asp-page-handler="ToggleSubscribed">
|
||||
@if (Model.Review.GetUserEmail(User) != null)
|
||||
{
|
||||
if (Model.Review.IsUserSubscribed(User))
|
||||
{
|
||||
<button type="submit" class="btn border btn-sm shadow-sm btn-light">
|
||||
<i class="far fa-minus-square" aria-hidden="true"></i> Unsubscribe
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn border btn-sm shadow-sm btn-light">
|
||||
<i class="far fa-plus-square" aria-hidden="true"></i> Subscribe
|
||||
</button>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn btn-sm shadow-sm btn-light" disabled data-placement="bottom" data-toggle="tooltip" title="Link a microsoft.com email to your Github account to subscribe">
|
||||
<i class="fa fa-plus-square" aria-hidden="true"></i> Subscribe
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="float-right ml-2 my-1">
|
||||
@if (Model.Revision.Approvers.Count > 0)
|
||||
{
|
||||
var approvers = String.Join(", ", Model.Revision.Approvers);
|
||||
<button type="button" class="btn btn-sm shadow-sm btn-success" data-placement="bottom" data-trigger="focus" data-toggle="popover" data-title="Approvers" data-content="@approvers">
|
||||
<i class="fas fa-check-circle"></i> APPROVED
|
||||
<span class="badge badge-light">@Model.Revision.Approvers.Count</span>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-light btn-sm shadow-sm">
|
||||
PENDING
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
@if (Model.Review.FilterType != ReviewType.Automatic)
|
||||
{
|
||||
<div class="my-1 ml-2">
|
||||
<form asp-resource="@Model.Review" class="form-inline" method="post" asp-page-handler="ToggleClosed">
|
||||
@if (Model.Review.IsClosed)
|
||||
{
|
||||
<button type="submit" class="btn btn-sm border shadow-sm btn-light">
|
||||
<i class="fa fa-sm fa-undo" aria-hidden="true"></i> Reopen
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn btn-sm border shadow-sm btn-light">
|
||||
<i class="far fa-window-close" aria-hidden="true"></i> Close
|
||||
</button>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mx-1 px-0 pt-0 pb-2">
|
||||
<form>
|
||||
<div class="form-row">
|
||||
@* Hide until tags is implemented
|
||||
<div class="form-group col-md-4 mb-0">
|
||||
<label class="mb-0 ml-1"><small>REVIEW:</small></label>
|
||||
<select class="selectpicker show-tick show-menu-arrow shadow-sm" data-style="btn-light btn-sm border" data-selected-text-format="value" data-live-search="true" data-size="10" data-width="100%" data-container="body" id="review-bootstraps-select" data-tick-icon="fa-solid fa-check">
|
||||
@foreach(var review in Model.ReviewsForPackage)
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = review.ReviewId
|
||||
});
|
||||
if (review.ReviewId == Model.Review.ReviewId)
|
||||
{
|
||||
<option selected style="font-size: 0.8em;" value="@urlValue" data-subtext="Type: @review.FilterType | Language: @review.Language | Author: @review.Author">@review.DisplayName</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="@urlValue" data-subtext="Type: @review.FilterType | Language: @review.Language | Author: @review.Author">@review.DisplayName</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
*@
|
||||
<div class="form-group col-md-6 mb-0">
|
||||
<label class="mb-0 ml-1"><small>REVISION:</small></label>
|
||||
<select class="selectpicker show-tick show-menu-arrow shadow-sm" data-style="btn-light btn-sm border" data-selected-text-format="value" data-live-search="true" data-size="10" data-width="100%" data-container="body" id="revisions-bootstraps-select" data-tick-icon="fa-solid fa-check">
|
||||
@foreach (var revision in Model.Review.Revisions.Reverse())
|
||||
{
|
||||
var approvedBadge = "<i class='fas fa-check-circle text-success ml-2'></i>";
|
||||
var optionName = revision.IsApproved ? $"{@revision.DisplayName} {@approvedBadge}" : @revision.DisplayName;
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @revision.RevisionId,
|
||||
doc = @Model.ShowDocumentation
|
||||
});
|
||||
if (@revision.DisplayName == @Model.Revision.DisplayName)
|
||||
{
|
||||
<option selected style="font-size: 0.8em;" value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-6 mb-0">
|
||||
@if (@Model.PreviousRevisions.Any())
|
||||
{
|
||||
@if (Model.DiffRevisionId != null)
|
||||
{
|
||||
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @Model.Revision.RevisionId,
|
||||
diffRevisionId = @Model.DiffRevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly
|
||||
});
|
||||
<label class="mb-0 ml-1"><a href="@urlValue"><small>DIFF WITH:</small></a></label>
|
||||
}
|
||||
else
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
revisionId = @Model.Revision.RevisionId,
|
||||
diffRevisionId = @Model.PreviousRevisions.Last().RevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly
|
||||
});
|
||||
<label class="mb-0 ml-1"><a href="@urlValue"><small>DIFF:</small></a></label>
|
||||
}
|
||||
<select class="selectpicker show-tick show-menu-arrow shadow-sm" data-style="btn-light btn-sm border border-left" data-size="10" data-width="100%" data-live-search="true" data-container="body" aria-label="Diff Review" id="diff-bootstraps-select" data-tick-icon="fa-solid fa-check">
|
||||
if (@Model.DiffRevisionId == null)
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="" selected></option>
|
||||
}
|
||||
@foreach (var revision in Model.PreviousRevisions.Reverse())
|
||||
{
|
||||
var approvedBadge = "<i class='fas fa-check-circle text-success ml-2'></i>";
|
||||
var optionName = revision.IsApproved ? $"{@revision.DisplayName} {@approvedBadge}" : @revision.DisplayName;
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new {
|
||||
id = @Model.Review.ReviewId,
|
||||
diffRevisionId = @revision.RevisionId,
|
||||
doc = @Model.ShowDocumentation,
|
||||
diffOnly = @Model.ShowDiffOnly,
|
||||
revisionId = @Model.Revision.RevisionId
|
||||
});
|
||||
if (@Model.DiffRevisionId != null)
|
||||
{
|
||||
if (@Model.DiffRevisionId == @revision.RevisionId)
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="@urlValue" selected data-content="@optionName"></option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (@Model.DiffRevisionId != @revision.RevisionId)
|
||||
{
|
||||
<option style="font-size: 0.8em;" value="@urlValue" data-content="@optionName"></option>
|
||||
}
|
||||
}
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="row px-3" data-review-id="@Model.Review.ReviewId" data-revision-id="@Model.Revision.RevisionId" data-language="@Model.Review.Language">
|
||||
<div id="review-left" class="col-2 rounded-1 border">
|
||||
@{
|
||||
var reviewLeftDisplay = String.Empty;
|
||||
var reviewRightSize = "10";
|
||||
if (Model.GetUserPreference().HideLeftNavigation == true)
|
||||
{
|
||||
reviewLeftDisplay = "d-none";
|
||||
reviewRightSize = "12";
|
||||
}
|
||||
}
|
||||
<div id="review-left" class="col-2 rounded-1 border @reviewLeftDisplay">
|
||||
<div class="namespace-view">
|
||||
@if (Model.CodeFile != null)
|
||||
{
|
||||
|
@ -343,9 +367,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="review-right" class="col-10 rounded-1 border">
|
||||
<div id="review-right" class="col-@reviewRightSize rounded-1 border">
|
||||
<table class="code-window">
|
||||
<tbody>
|
||||
@{
|
||||
TempData["UserPreference"] = Model.GetUserPreference();
|
||||
}
|
||||
@foreach (var line in Model.Lines)
|
||||
{
|
||||
<partial name="_CodeLine" model="@line" />
|
||||
|
|
|
@ -239,6 +239,17 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
await _manager.ToggleApprovalAsync(User, id, revisionId);
|
||||
return RedirectToPage(new { id = id });
|
||||
}
|
||||
|
||||
public IActionResult OnGetUpdatePageSettings(bool hideLineNumbers = false, bool hideLeftNavigation = false)
|
||||
{
|
||||
_preferenceCache.UpdateUserPreference(new UserPreferenceModel() {
|
||||
UserName = User.GetGitHubLogin(),
|
||||
HideLeftNavigation = hideLeftNavigation,
|
||||
HideLineNumbers = hideLineNumbers
|
||||
});
|
||||
return new EmptyResult();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetRoutingData(string diffRevisionId = null, bool? showDocumentation = null, bool? showDiffOnly = null, string revisionId = null)
|
||||
{
|
||||
var routingData = new Dictionary<string, string>();
|
||||
|
@ -248,5 +259,10 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
routingData["diffOnly"] = (showDiffOnly ?? false).ToString();
|
||||
return routingData;
|
||||
}
|
||||
|
||||
public UserPreferenceModel GetUserPreference()
|
||||
{
|
||||
return _preferenceCache.GetUserPreferences(User.GetGitHubLogin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@using ApiView
|
||||
@using APIView.DIff
|
||||
@using System.Text.RegularExpressions
|
||||
@using APIViewWeb.Models;
|
||||
@model APIViewWeb.Models.CodeLineModel
|
||||
@{
|
||||
bool isRemoved = Model.Kind == DiffLineKind.Removed;
|
||||
|
@ -22,14 +23,23 @@
|
|||
isContent = foldableClassParts.Any(x => x.EndsWith("-content"));
|
||||
hiddenSectionClass = isContent ? "d-none" : "";
|
||||
}
|
||||
|
||||
var userPreference = TempData["UserPreference"] as UserPreferenceModel;
|
||||
}
|
||||
|
||||
<tr class="code-line @lineClass @foldableClass @hiddenSectionClass" data-line-id="@(isRemoved ? string.Empty : Model.CodeLine.ElementId)">
|
||||
<td class="line-details">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="line-number @lineClass"><span>@Model.LineNumber</span></td>
|
||||
<td class="line-details-button-cell">
|
||||
@if(userPreference.HideLineNumbers == true)
|
||||
{
|
||||
<td class="line-number @lineClass d-none"><span>@Model.LineNumber</span></td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td class="line-number @lineClass"><span>@Model.LineNumber</span></td>
|
||||
}
|
||||
<td class="line-details-button-cell @lineClass">
|
||||
@if (!isRemoved && Model.CodeLine.ElementId != null)
|
||||
{
|
||||
<a class="line-comment-button">+</a>
|
||||
|
@ -39,7 +49,7 @@
|
|||
<a class="line-comment-button" style="visibility: hidden;">+</a> // Added for visual consistency
|
||||
}
|
||||
</td>
|
||||
<td class="line-details-button-cell">
|
||||
<td class="line-details-button-cell @lineClass">
|
||||
@if (isHeading)
|
||||
{
|
||||
<span class="row-fold-caret"><i class="fa-solid fa-angle-right"></i></span>
|
||||
|
|
|
@ -3,21 +3,42 @@ using Microsoft.Extensions.Caching.Memory;
|
|||
using APIViewWeb.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AutoMapper;
|
||||
|
||||
namespace APIViewWeb.Repositories
|
||||
{
|
||||
public class UserPreferenceCache
|
||||
{
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public UserPreferenceCache(IMemoryCache cache)
|
||||
public UserPreferenceCache(IMemoryCache cache, IMapper mapper)
|
||||
{
|
||||
_cache = cache;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public void UpdateUserPreference(UserPreferenceModel preference)
|
||||
{
|
||||
_cache.Set(preference.UserName, preference);
|
||||
UserPreferenceModel existingPreference = GetUserPreferences(preference.UserName);
|
||||
if (existingPreference == null)
|
||||
{
|
||||
_cache.Set(preference.UserName, preference);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mapper.Map<UserPreferenceModel, UserPreferenceModel>(preference, existingPreference);
|
||||
_cache.Set(preference.UserName, existingPreference);
|
||||
}
|
||||
}
|
||||
|
||||
public UserPreferenceModel GetUserPreferences(string userName)
|
||||
{
|
||||
if (_cache.TryGetValue(userName, out UserPreferenceModel _preference))
|
||||
{
|
||||
return _preference;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetLangauge(string userName)
|
||||
|
|
|
@ -194,6 +194,7 @@ namespace APIViewWeb
|
|||
services.AddSingleton<IAuthorizationHandler, PullRequestPermissionRequirementHandler>();
|
||||
services.AddHostedService<ReviewBackgroundHostedService>();
|
||||
services.AddHostedService<PullRequestBackgroundHostedService>();
|
||||
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
||||
}
|
||||
|
||||
private static async Task<string> GetMicrosoftEmailAsync(OAuthCreatingTicketContext context)
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче