1515// limitations under the License.
1616
1717using System ;
18+ using System . Collections . Generic ;
1819using System . Linq ;
1920using System . Threading ;
2021using System . Threading . Tasks ;
2122using Microsoft . AspNetCore . Authorization ;
2223using Microsoft . AspNetCore . Mvc ;
2324using Microsoft . EntityFrameworkCore ;
2425using Microsoft . Extensions . Options ;
26+ using NuGet . Frameworks ;
27+ using NuGet . Versioning ;
2528using SlimGet . Data . Configuration ;
29+ using SlimGet . Data . Database ;
2630using SlimGet . Models ;
2731using SlimGet . Services ;
2832
@@ -49,17 +53,74 @@ public async Task<IActionResult> Index(CancellationToken cancellationToken)
4953 return this . View ( new GalleryIndexModel ( pkgCount , verCount ) ) ;
5054 }
5155
52- [ HttpGet , SlimGetRoute ( Routing . GalleryPackageIndexRouteName ) ]
53- public IActionResult Packages ( )
54- => this . View ( ) ;
56+ [ HttpGet , SlimGetRoute ( Routing . GalleryListRouteName ) ]
57+ public async Task < IActionResult > Packages ( [ FromQuery ] int skip , CancellationToken cancellationToken )
58+ {
59+ if ( skip < 0 )
60+ return this . BadRequest ( ) ;
61+
62+ var dbpackages = this . Database . Packages
63+ . Include ( x => x . Tags )
64+ . Include ( x => x . Authors )
65+ . Include ( x => x . Versions )
66+ . OrderByDescending ( x => x . DownloadCount )
67+ . ThenBy ( x => x . Id ) ;
68+
69+ var count = await dbpackages . CountAsync ( cancellationToken ) ;
70+ var next = skip + 20 <= count ? skip + 20 : - 1 ;
71+
72+ return this . View ( new GalleryPackageListModel ( count , this . PreparePackages ( dbpackages . Skip ( skip ) . Take ( 20 ) ) , next , skip - 20 ) ) ;
73+ }
74+
75+ [ HttpGet , SlimGetRoute ( Routing . GalleryPackageRouteName ) ]
76+ public async Task < IActionResult > Package ( string id , string version , CancellationToken cancellationToken )
77+ {
78+ var dbpackage = await this . Database . Packages
79+ . Include ( x => x . Tags )
80+ . Include ( x => x . Versions )
81+ . ThenInclude ( x => x . Binaries )
82+ . ThenInclude ( x => x . PackageSymbols )
83+ . Include ( x => x . Versions )
84+ . ThenInclude ( x => x . Dependencies )
85+ . Include ( x => x . Authors )
86+ . FirstOrDefaultAsync ( x => x . Id == id , cancellationToken ) . ConfigureAwait ( false ) ;
87+
88+ if ( dbpackage == null )
89+ return this . NotFound ( ) ;
90+
91+ var dbversion = version != null
92+ ? dbpackage . Versions . FirstOrDefault ( x => x . Version == version )
93+ : dbpackage . Versions . OrderByDescending ( x => x . NuGetVersion ) . First ( ) ;
94+
95+ if ( dbversion == null )
96+ return this . NotFound ( ) ;
97+
98+ return this . View ( this . PreparePackage ( dbpackage , dbversion ) ) ;
99+ }
100+
101+ [ HttpGet , SlimGetRoute ( Routing . GallerySearchRouteName ) ]
102+ public async Task < IActionResult > Search ( [ FromQuery ] GallerySearchModel search , CancellationToken cancellationToken )
103+ {
104+ var query = search . Query ;
105+ var prerelease = search . Prerelease ;
106+ var skip = search . Skip ;
107+ var dbpackages = this . Database . Packages
108+ . Include ( x => x . Versions )
109+ . Include ( x => x . Tags )
110+ . Include ( x => x . Authors )
111+ . Where ( x => ( EF . Functions . Similarity ( x . Id , query ) >= 0.35 ||
112+ EF . Functions . Similarity ( x . Description , query ) >= 0.2 ||
113+ EF . Functions . Similarity ( x . Title , query ) >= 0.2 ||
114+ x . Tags . Any ( y => EF . Functions . Similarity ( y . Tag , query ) >= 0.35 ) ) &&
115+ x . Versions . Any ( y => ! y . IsPrerelase || prerelease ) )
116+ . OrderByDescending ( x => x . DownloadCount )
117+ . ThenBy ( x => x . Id ) ;
55118
56- [ HttpGet , SlimGetRoute ( Routing . GalleryPackageDetailsRouteName ) ]
57- public IActionResult Packages ( string id )
58- => this . View ( ) ;
119+ var count = await dbpackages . CountAsync ( cancellationToken ) ;
120+ var next = skip + 20 <= count ? skip + 20 : - 1 ;
59121
60- [ HttpGet , SlimGetRoute ( Routing . GalleryPackageVersionRouteName ) ]
61- public IActionResult Packages ( string id , string version )
62- => this . View ( ) ;
122+ return this . View ( new GallerySearchResultModel ( count , this . PreparePackages ( dbpackages . Skip ( skip ) . Take ( 20 ) , prerelease ) , next , skip - 20 , query , prerelease ) ) ;
123+ }
63124
64125 [ HttpGet , SlimGetRoute ( Routing . GalleryAboutRouteName ) ]
65126 public IActionResult About ( )
@@ -75,5 +136,87 @@ public IActionResult About()
75136 this . PackageStorageConfiguration . SymbolsEnabled ,
76137 ! this . PackageStorageConfiguration . ReadOnlyFeed ) ) ;
77138 }
139+
140+ private IEnumerable < GalleryPackageListItemModel > PreparePackages ( IEnumerable < Package > dbpackages , bool prerelease = true )
141+ {
142+ foreach ( var dbpackage in dbpackages )
143+ {
144+ var version = dbpackage . Versions
145+ . Where ( x => ! x . IsPrerelase || prerelease )
146+ . OrderByDescending ( x => x . NuGetVersion )
147+ . First ( ) ;
148+
149+ yield return new GalleryPackageListItemModel
150+ {
151+ Id = dbpackage . Id ,
152+ Title = dbpackage . Title ,
153+ IconUrl = dbpackage . IconUrl ,
154+ Authors = dbpackage . AuthorNames ,
155+ Tags = dbpackage . TagNames ,
156+ DownloadCount = dbpackage . DownloadCount ,
157+ PublishedAt = dbpackage . PublishedAt . Value ,
158+ LastUpdatedAt = version . PublishedAt . Value ,
159+ LatestVersion = version . NuGetVersion ,
160+ Description = dbpackage . Description
161+ } ;
162+ }
163+ }
164+
165+ private GalleryPackageInfoModel PreparePackage ( Package dbpackage , PackageVersion dbversion )
166+ => new GalleryPackageInfoModel
167+ {
168+ Id = dbpackage . Id ,
169+ Title = dbpackage . Title ,
170+ IconUrl = dbpackage . IconUrl ,
171+ ProjectUrl = dbpackage . ProjectUrl ,
172+ LicenseUrl = dbpackage . LicenseUrl ,
173+ RepositoryUrl = dbpackage . RepositoryUrl ,
174+ Authors = dbpackage . AuthorNames ,
175+ Tags = dbpackage . TagNames ,
176+ DownloadCount = dbpackage . DownloadCount ,
177+ VersionDownloadCount = dbversion . DownloadCount ,
178+ PublishedAt = dbversion . PublishedAt . Value ,
179+ Version = dbversion . NuGetVersion ,
180+ Description = dbpackage . Description ,
181+ DownloadUrl = this . Url . AbsoluteUrl ( Routing . DownloadPackageContentsRouteName , this . HttpContext , new
182+ {
183+ id = dbpackage . IdLowercase ,
184+ version = dbversion . VersionLowercase ,
185+ filename = $ "{ dbpackage . IdLowercase } .{ dbversion . VersionLowercase } "
186+ } ) ,
187+ ManifestUrl = this . Url . AbsoluteUrl ( Routing . DownloadPackageManifestRouteName , this . HttpContext , new
188+ {
189+ id = dbpackage . IdLowercase ,
190+ version = dbversion . VersionLowercase ,
191+ id2 = dbpackage . IdLowercase
192+ } ) ,
193+ // figure out symbols
194+ DependencyGroups = this . PrepareDependencyGroups ( dbversion ) ,
195+ OwnerId = dbpackage . OwnerId ,
196+ AllVersions = dbpackage . Versions . Select ( x => ( x . Version , x . DownloadCount , new DateTimeOffset ( x . PublishedAt . Value ) ) )
197+ } ;
198+
199+ private IEnumerable < GalleryPackageDependencyGroupModel > PrepareDependencyGroups ( PackageVersion dbversion )
200+ {
201+ foreach ( var depgroup in dbversion . Dependencies . GroupBy ( x => x . TargetFramework ) )
202+ yield return new GalleryPackageDependencyGroupModel
203+ {
204+ Framework = NuGetFramework . Parse ( depgroup . Key ) ,
205+ Dependencies = this . PrepareDependencies ( depgroup )
206+ } ;
207+ }
208+
209+ private IEnumerable < GalleryPackageDependencyModel > PrepareDependencies ( IEnumerable < PackageDependency > dbdeps )
210+ {
211+ foreach ( var dbdep in dbdeps )
212+ yield return new GalleryPackageDependencyModel
213+ {
214+ Id = dbdep . Id ,
215+ MinVersion = dbdep . MinVersion != null ? NuGetVersion . Parse ( dbdep . MinVersion ) : null ,
216+ MaxVersion = dbdep . MaxVersion != null ? NuGetVersion . Parse ( dbdep . MaxVersion ) : null ,
217+ MinInclusive = dbdep . IsMinVersionInclusive . HasValue && dbdep . IsMinVersionInclusive . HasValue ,
218+ MaxInclusive = dbdep . IsMaxVersionInclusive . HasValue && dbdep . IsMaxVersionInclusive . HasValue
219+ } ;
220+ }
78221 }
79222}
0 commit comments