Skip to content

Commit 5ebe53e

Browse files
authored
Merge pull request #8202 from NuGet/dev
[ReleasePrep][2020.09.09]RI of dev to master
2 parents 7e6f309 + 225a065 commit 5ebe53e

9 files changed

Lines changed: 205 additions & 38 deletions

File tree

src/Bootstrap/dist/css/bootstrap-theme.css

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Bootstrap/less/theme/base.less

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,7 @@ img.reserved-indicator-icon {
425425
z-index: 99999;
426426
right: 0;
427427
}
428+
429+
.sortable {
430+
cursor: pointer;
431+
}

src/NuGetGallery/Controllers/PackagesController.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,10 @@ public HttpStatusCodeResult DisplayPackage()
828828
[HttpGet]
829829
public virtual async Task<ActionResult> DisplayPackage(string id, string version)
830830
{
831+
// Attempt to normalize the version but allow version strings that are not actually SemVer strings. For
832+
// example, "absoluteLatest" is allowed as the version string as a reference to the absolute latest version
833+
// including prerelease versions. In this case, the resulting normalized version will be left as the
834+
// original string.
831835
string normalized = NuGetVersionFormatter.Normalize(version);
832836
if (!string.Equals(version, normalized))
833837
{
@@ -890,7 +894,11 @@ public virtual async Task<ActionResult> DisplayPackage(string id, string version
890894
model.GitHubDependenciesInformation = _contentObjectService.GitHubUsageConfiguration.GetPackageInformation(id);
891895
}
892896

893-
if (normalized != null && !string.Equals(package.NormalizedVersion, normalized, StringComparison.OrdinalIgnoreCase))
897+
// If the normalized version is actually a SemVer but does not match the resolved package version, show a
898+
// warning. It's possible that the normalized version is not a SemVer string (like "absoluteLatest").
899+
if (normalized != null
900+
&& !string.Equals(package.NormalizedVersion, normalized, StringComparison.OrdinalIgnoreCase)
901+
&& NuGetVersion.TryParse(normalized, out var parsed))
894902
{
895903
model.VersionRequested = normalized;
896904
model.VersionRequestedWasNotFound = true;

src/NuGetGallery/Controllers/UsersController.cs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Web.Mvc;
1313
using NuGet.Services.Entities;
1414
using NuGet.Services.Messaging.Email;
15+
using NuGet.Versioning;
1516
using NuGetGallery.Areas.Admin;
1617
using NuGetGallery.Areas.Admin.ViewModels;
1718
using NuGetGallery.Authentication;
@@ -521,16 +522,12 @@ public virtual ActionResult Packages()
521522
var wasAADLoginOrMultiFactorAuthenticated = User.WasMultiFactorAuthenticated() || User.WasAzureActiveDirectoryAccountUsedForSignin();
522523

523524
var packages = PackageService.FindPackagesByAnyMatchingOwner(currentUser, includeUnlisted: true);
524-
var listedPackages = packages
525-
.Where(p => p.Listed && p.PackageStatusKey == PackageStatus.Available)
526-
.Select(p => _listPackageItemRequiredSignerViewModelFactory.Create(p, currentUser, wasAADLoginOrMultiFactorAuthenticated))
527-
.OrderBy(p => p.Id)
528-
.ToList();
529-
var unlistedPackages = packages
530-
.Where(p => !p.Listed || p.PackageStatusKey != PackageStatus.Available)
531-
.Select(p => _listPackageItemRequiredSignerViewModelFactory.Create(p, currentUser, wasAADLoginOrMultiFactorAuthenticated))
532-
.OrderBy(p => p.Id)
533-
.ToList();
525+
526+
var listedPackages = GetPackages(packages, currentUser, wasAADLoginOrMultiFactorAuthenticated,
527+
p => p.Listed && p.PackageStatusKey == PackageStatus.Available);
528+
529+
var unlistedPackages = GetPackages(packages, currentUser, wasAADLoginOrMultiFactorAuthenticated,
530+
p => !p.Listed || p.PackageStatusKey != PackageStatus.Available);
534531

535532
// find all received ownership requests
536533
var userReceived = _packageOwnerRequestService.GetPackageOwnershipRequests(newOwner: currentUser);
@@ -567,6 +564,36 @@ public virtual ActionResult Packages()
567564
return View(model);
568565
}
569566

567+
/// <summary>
568+
/// Returns all packages based on the predicate, with the VersionSortOrder populated
569+
/// </summary>
570+
/// <param name="packages"></param>
571+
/// <param name="currentUser"></param>
572+
/// <param name="wasAADLoginOrMultiFactorAuthenticated"></param>
573+
/// <param name="predicate"></param>
574+
/// <returns></returns>
575+
private List<ListPackageItemRequiredSignerViewModel> GetPackages(
576+
IEnumerable<Package> packages,
577+
User currentUser,
578+
bool wasAADLoginOrMultiFactorAuthenticated,
579+
Func<Package, bool> predicate)
580+
{
581+
var listedPackages = packages
582+
.Where(p => predicate(p))
583+
.Select(p => _listPackageItemRequiredSignerViewModelFactory.Create(p, currentUser, wasAADLoginOrMultiFactorAuthenticated))
584+
.OrderBy(p => NuGetVersion.Parse(p.FullVersion))
585+
.ToList();
586+
587+
for (int i = 0; i < listedPackages.Count; i++)
588+
{
589+
listedPackages[i].VersionSortOrder = i;
590+
}
591+
592+
listedPackages.Sort((x, y) => string.Compare(x.Id, y.Id, StringComparison.OrdinalIgnoreCase));
593+
594+
return listedPackages;
595+
}
596+
570597
[HttpGet]
571598
[UIAuthorize]
572599
public virtual ActionResult Organizations()

src/NuGetGallery/Scripts/gallery/page-manage-packages.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
this.CanEdit = packageItem.CanEdit;
3939
this.CanManageOwners = packageItem.CanManageOwners;
4040
this.CanDelete = packageItem.CanDelete;
41+
this.VersionSortOrder = packageItem.VersionSortOrder;
4142

4243
this.FormattedDownloadCount = ko.pureComputed(function () {
4344
return ko.unwrap(this.DownloadCount).toLocaleString();
@@ -355,6 +356,49 @@
355356
this.RequestsSent = new OwnerRequestsListViewModel(this, initialData.RequestsSent, false, true);
356357
}
357358

359+
function setupColumnSorting() {
360+
$('.sortable').click(function () {
361+
362+
var table = $(this).parents('table').eq(0);
363+
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
364+
this.asc = !this.asc;
365+
if (!this.asc) {
366+
rows = rows.reverse();
367+
}
368+
for (var i = 0; i < rows.length; i++) {
369+
table.append(rows[i]);
370+
}
371+
372+
table.find('.sortable').each(function () {
373+
var currentText = $(this).text();
374+
var newText = currentText.replace(' ▲', '').replace(' ▼', '');
375+
$(this).text(newText);
376+
});
377+
378+
var columnText = $(this).text();
379+
$(this).text(columnText + " " + (this.asc ? "▼" : "▲"));
380+
381+
})
382+
function comparer(index) {
383+
return function (a, b) {
384+
var valA = getCellValue(a, index), valB = getCellValue(b, index);
385+
return $.isNumeric(valA) && $.isNumeric(valB) ? valB - valA : valA.toString().localeCompare(valB);
386+
}
387+
}
388+
function getCellValue(row, index) {
389+
var td = $(row).children('td').eq(index);
390+
391+
// check for the data-sortby attribute, if found, use that data to sort by
392+
var sortby = td.data('sortby');
393+
394+
if (typeof sortby !== 'undefined') {
395+
return sortby;
396+
}
397+
398+
return td.text();
399+
}
400+
}
401+
358402
// Immediately load initial expander data
359403
showInitialPackagesData("#listed-data", initialData.ListedPackages);
360404
showInitialPackagesData("#unlisted-data", initialData.UnlistedPackages);
@@ -365,6 +409,9 @@
365409
// Set up the data binding.
366410
var managePackagesViewModel = new ManagePackagesViewModel(initialData);
367411
ko.applyBindings(managePackagesViewModel, document.body);
412+
413+
setupColumnSorting();
414+
368415
});
369416

370417
})();

src/NuGetGallery/ViewModels/ListPackageItemViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class ListPackageItemViewModel : PackageViewModel
2525
public string ShortDescription { get; private set; }
2626
public bool IsDescriptionTruncated { get; set; }
2727
public bool? IsVerified { get; set; }
28+
public int VersionSortOrder { get; set; }
2829
public string SignatureInformation
2930
{
3031
get

src/NuGetGallery/Views/Users/Packages.cshtml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
ViewBag.Title = "Manage My Package";
55
ViewBag.Tab = "Packages";
66
}
7-
87
<section role="main" class="container main-container page-manage-packages">
98
@ViewHelpers.AjaxAntiForgeryToken(Html)
109

@@ -113,14 +112,14 @@
113112
<thead>
114113
<tr class="manage-package-headings">
115114
<th class="hidden-xs"><span class="hidden">Package Icon</span></th>
116-
<th>Package ID</th>
117-
<th>Owners</th>
115+
<th class="sortable">Package ID</th>
116+
<th class="sortable">Owners</th>
118117
@if (Model.IsCertificatesUIEnabled)
119118
{
120-
<th>Signing Owner</th>
119+
<th class="sortable">Signing Owner</th>
121120
}
122-
<th>Downloads</th>
123-
<th>Latest Version</th>
121+
<th class="sortable">Downloads</th>
122+
<th class="sortable">Latest Version</th>
124123
<th><span class="hidden">Icon</span></th>
125124
</tr>
126125
</thead>
@@ -166,10 +165,10 @@
166165
<!-- /ko -->
167166
</td>
168167
}
169-
<td class="align-middle text-nowrap">
168+
<td class="align-middle text-nowrap" data-bind="attr: { 'data-sortby': DownloadCount }">
170169
<span data-bind="text: FormattedDownloadCount"></span>
171170
</td>
172-
<td class="align-middle text-nowrap">
171+
<td class="align-middle text-nowrap" data-bind="attr: { 'data-sortby': VersionSortOrder }">
173172
<span data-bind="text: LatestVersion"></span>
174173
</td>
175174
<td class="text-right align-middle package-controls">
@@ -353,7 +352,8 @@
353352
CanDelete = p.CanUnlistOrRelist,
354353
p.CanEditRequiredSigner,
355354
p.ShowRequiredSigner,
356-
p.ShowTextBox
355+
p.ShowTextBox,
356+
p.VersionSortOrder
357357
};
358358
}
359359

tests/NuGetGallery.Facts/Controllers/PackagesControllerFacts.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,7 @@ public async Task GivenAnAbsoluteLatestVersionItReturnsTheFirstLatestSemVer2()
896896
// The page should select the first package that is IsLatestSemVer2
897897
Assert.Equal(latestPackage.NormalizedVersion, model.Version);
898898
Assert.True(model.LatestVersionSemVer2);
899+
Assert.False(model.VersionRequestedWasNotFound);
899900

900901
deprecationService.Verify();
901902
}

0 commit comments

Comments
 (0)