mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 02:44:52 +08:00
@@ -143,7 +143,6 @@
|
||||
<Compile Include="Indexing\LuceneIndexProviderTests.cs" />
|
||||
<Compile Include="Indexing\LuceneSearchBuilderTests.cs" />
|
||||
<Compile Include="Media\Services\MediaServiceTests.cs" />
|
||||
<Compile Include="Packaging\Services\PackagingServicesTests.cs" />
|
||||
<Compile Include="Scripting.Dlr\EvaluatorTests.cs" />
|
||||
<Compile Include="Scripting\EvaluatorTestsBase.cs" />
|
||||
<Compile Include="Scripting\EvaluatorTests.cs" />
|
||||
|
@@ -1,146 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.MetaData.Services;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Core.Settings.Handlers;
|
||||
using Orchard.Core.Settings.Metadata;
|
||||
using Orchard.Core.Settings.Models;
|
||||
using Orchard.Core.Settings.Services;
|
||||
using Orchard.Data;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Packaging.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.Security.Providers;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Tests.Modules.Users;
|
||||
using Orchard.Tests.Stubs;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Users.Handlers;
|
||||
using Orchard.Users.Models;
|
||||
using Orchard.Users.Services;
|
||||
|
||||
namespace Orchard.Tests.Modules.Packaging.Services {
|
||||
public class PackagingServicesTests : DatabaseEnabledTestsBase {
|
||||
private Mock<IAuthorizer> _authorizer;
|
||||
private Mock<WorkContext> _workContext;
|
||||
private IUser _currentUser;
|
||||
|
||||
public override void Register(ContainerBuilder builder) {
|
||||
builder.RegisterType<SiteService>().As<ISiteService>();
|
||||
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
||||
builder.RegisterType(typeof(SettingsFormatter))
|
||||
.As(typeof(IMapper<XElement, SettingsDictionary>))
|
||||
.As(typeof(IMapper<SettingsDictionary, XElement>));
|
||||
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
|
||||
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
|
||||
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency();
|
||||
builder.RegisterType<MembershipService>().As<IMembershipService>();
|
||||
builder.RegisterType<UserService>().As<IUserService>();
|
||||
builder.RegisterType<UserPartHandler>().As<IContentHandler>();
|
||||
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
||||
builder.RegisterType<TransactionManager>().As<ITransactionManager>();
|
||||
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
|
||||
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
|
||||
builder.RegisterType<StubExtensionManager>().As<IExtensionManager>();
|
||||
builder.RegisterType<SiteSettingsPartHandler>().As<IContentHandler>();
|
||||
builder.RegisterType<PackagingServices>().As<IPackagingServices>();
|
||||
|
||||
builder.RegisterInstance(new Mock<INotifier>().Object);
|
||||
builder.RegisterInstance(new Mock<IContentDisplay>().Object);
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterType<Signals>().As<ISignals>();
|
||||
|
||||
builder.RegisterType<DefaultEncryptionService>().As<IEncryptionService>();
|
||||
builder.RegisterInstance(ShellSettingsUtility.CreateEncryptionEnabled());
|
||||
|
||||
_authorizer = new Mock<IAuthorizer>();
|
||||
builder.RegisterInstance(_authorizer.Object);
|
||||
|
||||
_workContext = new Mock<WorkContext>();
|
||||
_workContext.Setup(w => w.GetState<ISite>(It.Is<string>(s => s == "CurrentSite"))).Returns(() => _container.Resolve<ISiteService>().GetSiteSettings());
|
||||
_workContext.Setup(w => w.GetState<IUser>(It.Is<string>(s => s == "CurrentUser"))).Returns(() => _currentUser);
|
||||
|
||||
var _workContextAccessor = new Mock<IWorkContextAccessor>();
|
||||
_workContextAccessor.Setup(w => w.GetContext()).Returns(_workContext.Object);
|
||||
builder.RegisterInstance(_workContextAccessor.Object).As<IWorkContextAccessor>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] { typeof(UserPartRecord),
|
||||
typeof(SiteSettingsPartRecord),
|
||||
typeof(RegistrationSettingsPartRecord),
|
||||
typeof(ContentTypeRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanManagePackagesTest() {
|
||||
const string superUsername = "admin";
|
||||
const string regularUsername = "user1";
|
||||
|
||||
IPackagingServices packagingServices = _container.Resolve<IPackagingServices>();
|
||||
IOrchardServices orchardServices = _container.Resolve<IOrchardServices>();
|
||||
ShellSettings shellSettings = _container.Resolve<ShellSettings>();
|
||||
shellSettings.Name = ShellSettings.DefaultName;
|
||||
|
||||
IUser regularUser = CreateUser(regularUsername);
|
||||
IUser superUser = CreateUser(superUsername);
|
||||
|
||||
orchardServices.WorkContext.CurrentSite.As<SiteSettingsPart>().SuperUser = superUsername;
|
||||
_currentUser = regularUser;
|
||||
_session.Flush();
|
||||
|
||||
// Setup authorizer to return false
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(false);
|
||||
|
||||
// Test regular user without permission explicit assigned and which is not the default admin
|
||||
Assert.That(packagingServices.CanManagePackages(), Is.False);
|
||||
|
||||
// Test regular user with permission explicit assigned and which is not the default admin
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
|
||||
Assert.That(packagingServices.CanManagePackages(), Is.True);
|
||||
|
||||
// Test super user that even without permission explicit assigned should be able to manage packages
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(false);
|
||||
Assert.That(packagingServices.CanManagePackages(), Is.False);
|
||||
_currentUser = superUser;
|
||||
Assert.That(packagingServices.CanManagePackages(), Is.True);
|
||||
|
||||
// Test with super user from another tenant site
|
||||
shellSettings.Name = "tenantsite2";
|
||||
_session.Flush();
|
||||
|
||||
Assert.That(packagingServices.CanManagePackages(), Is.False);
|
||||
}
|
||||
|
||||
private IUser CreateUser(string username) {
|
||||
var manager = _container.Resolve<IContentManager>();
|
||||
|
||||
UserPart userPart = manager.New<UserPart>("User");
|
||||
userPart.Record = new UserPartRecord { UserName = username, NormalizedUserName = username, Email = string.Format("{0}@orcharproject.com", username) };
|
||||
manager.Create(userPart.ContentItem);
|
||||
|
||||
return userPart;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 564 B |
@@ -3,16 +3,21 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Packaging.GalleryServer;
|
||||
using Orchard.Packaging.Models;
|
||||
using Orchard.Packaging.Services;
|
||||
using Orchard.Packaging.ViewModels;
|
||||
using Orchard.Security;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.UI.Notify;
|
||||
using IPackageManager = Orchard.Packaging.Services.IPackageManager;
|
||||
|
||||
@@ -20,23 +25,18 @@ namespace Orchard.Packaging.Controllers {
|
||||
[OrchardFeature("Gallery")]
|
||||
[Themed, Admin]
|
||||
public class GalleryController : Controller {
|
||||
|
||||
private readonly IPackagingServices _packagingServices;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly IPackageManager _packageManager;
|
||||
private readonly IPackagingSourceManager _packagingSourceManager;
|
||||
private readonly INotifier _notifier;
|
||||
|
||||
public GalleryController(
|
||||
IPackagingServices packagingServices,
|
||||
ShellSettings shellSettings,
|
||||
IPackageManager packageManager,
|
||||
IPackagingSourceManager packagingSourceManager,
|
||||
INotifier notifier,
|
||||
IOrchardServices services) {
|
||||
|
||||
_packagingServices = packagingServices;
|
||||
_shellSettings = shellSettings;
|
||||
_packageManager = packageManager;
|
||||
_packagingSourceManager = packagingSourceManager;
|
||||
_notifier = notifier;
|
||||
Services = services;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
@@ -48,7 +48,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ActionResult Sources() {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list sources")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return View(new PackagingSourcesViewModel {
|
||||
@@ -57,16 +57,16 @@ namespace Orchard.Packaging.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Remove(int id) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove sources")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
_packagingSourceManager.RemoveSource(id);
|
||||
_notifier.Information(T("The feed has been removed successfully."));
|
||||
Services.Notifier.Information(T("The feed has been removed successfully."));
|
||||
return RedirectToAction("Sources");
|
||||
}
|
||||
|
||||
public ActionResult AddSource() {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return View(new PackagingAddSourceViewModel());
|
||||
@@ -74,7 +74,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult AddSource(string url) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
try {
|
||||
@@ -109,29 +109,34 @@ namespace Orchard.Packaging.Controllers {
|
||||
return View(new PackagingAddSourceViewModel { Url = url });
|
||||
|
||||
_packagingSourceManager.AddSource(title, url);
|
||||
_notifier.Information(T("The feed has been added successfully."));
|
||||
Services.Notifier.Information(T("The feed has been added successfully."));
|
||||
|
||||
return RedirectToAction("Sources");
|
||||
}
|
||||
catch (Exception exception) {
|
||||
_notifier.Error(T("Adding feed failed: {0}", exception.Message));
|
||||
Services.Notifier.Error(T("Adding feed failed: {0}", exception.Message));
|
||||
return View(new PackagingAddSourceViewModel { Url = url });
|
||||
}
|
||||
}
|
||||
|
||||
public ActionResult Modules(int? sourceId) {
|
||||
return ListExtensions(sourceId, DefaultExtensionTypes.Module, "Modules", source => _packagingSourceManager.GetModuleList(source).ToArray());
|
||||
}
|
||||
|
||||
public ActionResult Themes(int? sourceId) {
|
||||
return ListExtensions(sourceId, DefaultExtensionTypes.Theme, "Themes", source => _packagingSourceManager.GetThemeList(source).ToArray());
|
||||
}
|
||||
|
||||
protected ActionResult ListExtensions(int? sourceId, string extensionType, string returnView, Func<PackagingSource, PackagingEntry[]> getList) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
public ActionResult Modules(PackagingExtensionsOptions options, PagerParameters pagerParameters) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list Modules")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
|
||||
var pager = new Pager(Services.WorkContext.CurrentSite, pagerParameters);
|
||||
return ListExtensions(options, DefaultExtensionTypes.Module, pager);
|
||||
}
|
||||
|
||||
public ActionResult Themes(PackagingExtensionsOptions options, PagerParameters pagerParameters) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list Themes")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var pager = new Pager(Services.WorkContext.CurrentSite, pagerParameters);
|
||||
return ListExtensions(options, DefaultExtensionTypes.Theme, pager);
|
||||
}
|
||||
|
||||
protected ActionResult ListExtensions(PackagingExtensionsOptions options, string packageType, Pager pager) {
|
||||
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == options.SourceId).FirstOrDefault();
|
||||
|
||||
var sources = selectedSource != null
|
||||
? new[] { selectedSource }
|
||||
@@ -139,26 +144,86 @@ namespace Orchard.Packaging.Controllers {
|
||||
;
|
||||
|
||||
IEnumerable<PackagingEntry> extensions = null;
|
||||
int totalCount = 0;
|
||||
foreach (var source in sources) {
|
||||
try {
|
||||
var sourceExtensions = getList(source);
|
||||
var sourceExtensions = _packagingSourceManager.GetExtensionList(
|
||||
source,
|
||||
packages => {
|
||||
packages = packages.Where(p => p.PackageType == packageType);
|
||||
|
||||
switch (options.Order) {
|
||||
case PackagingExtensionsOrder.Downloads:
|
||||
packages = packages.OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Title);
|
||||
break;
|
||||
case PackagingExtensionsOrder.Ratings:
|
||||
packages = packages.OrderByDescending(p => p.Rating).ThenBy(p => p.Title);
|
||||
break;
|
||||
case PackagingExtensionsOrder.Alphanumeric:
|
||||
packages = packages.OrderBy(p => p.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
if(pager.PageSize != 0) {
|
||||
packages = packages.Skip((pager.Page - 1)*pager.PageSize).Take(pager.PageSize);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
).ToArray();
|
||||
|
||||
// count packages separately to prevent loading everything just to count
|
||||
totalCount += _packagingSourceManager.GetExtensionCount(
|
||||
source,
|
||||
packages => packages.Where(p => p.PackageType == packageType)
|
||||
);
|
||||
|
||||
extensions = extensions == null ? sourceExtensions : extensions.Concat(sourceExtensions);
|
||||
|
||||
// apply another paging rule in case there were multiple sources
|
||||
if (sources.Count() > 1) {
|
||||
switch (options.Order) {
|
||||
case PackagingExtensionsOrder.Downloads:
|
||||
extensions = extensions.OrderByDescending(p => p.DownloadCount).ThenBy(p => p.Title);
|
||||
break;
|
||||
case PackagingExtensionsOrder.Ratings:
|
||||
extensions = extensions.OrderByDescending(p => p.Rating).ThenBy(p => p.Title);
|
||||
break;
|
||||
case PackagingExtensionsOrder.Alphanumeric:
|
||||
extensions = extensions.OrderBy(p => p.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pager.PageSize != 0) {
|
||||
extensions = extensions.Take(pager.PageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, ex.Message);
|
||||
_notifier.Error(T("Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, ex.Message));
|
||||
Services.Notifier.Error(T("Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
return View(returnView, new PackagingExtensionsViewModel {
|
||||
Extensions = extensions ?? new PackagingEntry[] { },
|
||||
extensions = extensions ?? new PackagingEntry[0];
|
||||
var pagerShape = Services.New.Pager(pager).TotalItemCount(totalCount);
|
||||
|
||||
// maintain previous route data when generating page links
|
||||
var routeData = new RouteData();
|
||||
routeData.Values.Add("Options.Order", options.Order);
|
||||
pagerShape.RouteData(routeData);
|
||||
|
||||
return View(packageType == DefaultExtensionTypes.Theme ? "Themes" : "Modules", new PackagingExtensionsViewModel {
|
||||
Extensions = extensions,
|
||||
Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
|
||||
SelectedSource = selectedSource
|
||||
SelectedSource = selectedSource,
|
||||
Pager = pagerShape,
|
||||
Options = options
|
||||
});
|
||||
}
|
||||
|
||||
public ActionResult Install(string packageId, string version, int sourceId, string redirectTo) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add sources")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var source = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
|
||||
@@ -171,16 +236,16 @@ namespace Orchard.Packaging.Controllers {
|
||||
_packageManager.Install(packageId, version, source.FeedUrl, HostingEnvironment.MapPath("~/"));
|
||||
|
||||
if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme))) {
|
||||
_notifier.Information(T("The theme has been successfully installed. It can be enabled in the \"Themes\" page accessible from the menu."));
|
||||
Services.Notifier.Information(T("The theme has been successfully installed. It can be enabled in the \"Themes\" page accessible from the menu."));
|
||||
}
|
||||
else if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module))) {
|
||||
_notifier.Information(T("The module has been successfully installed. Its features can be enabled in the \"Configuration | Features\" page accessible from the menu."));
|
||||
Services.Notifier.Information(T("The module has been successfully installed. Its features can be enabled in the \"Configuration | Features\" page accessible from the menu."));
|
||||
}
|
||||
}
|
||||
catch (Exception exception) {
|
||||
_notifier.Error(T("Package installation failed."));
|
||||
Services.Notifier.Error(T("Package installation failed."));
|
||||
for (Exception scan = exception; scan != null; scan = scan.InnerException) {
|
||||
_notifier.Error(T("{0}", scan.Message));
|
||||
Services.Notifier.Error(T("{0}", scan.Message));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,12 +4,14 @@ using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Mvc;
|
||||
using NuGet;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Mvc.Extensions;
|
||||
using Orchard.Packaging.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
@@ -21,19 +23,19 @@ namespace Orchard.Packaging.Controllers {
|
||||
[Themed, Admin]
|
||||
public class PackagingServicesController : Controller {
|
||||
|
||||
private readonly IPackagingServices _packagingServices;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly IPackageManager _packageManager;
|
||||
private readonly IAppDataFolderRoot _appDataFolderRoot;
|
||||
private readonly INotifier _notifier;
|
||||
|
||||
public PackagingServicesController(
|
||||
IPackagingServices packagingServices,
|
||||
ShellSettings shellSettings,
|
||||
IPackageManager packageManager,
|
||||
INotifier notifier,
|
||||
IAppDataFolderRoot appDataFolderRoot,
|
||||
IOrchardServices services) {
|
||||
|
||||
_packagingServices = packagingServices;
|
||||
_shellSettings = shellSettings;
|
||||
_packageManager = packageManager;
|
||||
_notifier = notifier;
|
||||
_appDataFolderRoot = appDataFolderRoot;
|
||||
@@ -46,7 +48,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult AddTheme(string returnUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add themes")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return View();
|
||||
@@ -54,7 +56,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
|
||||
[HttpPost, ActionName("AddTheme")]
|
||||
public ActionResult AddThemePOST(string returnUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add themes")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return InstallPackage(returnUrl, Request.RawUrl);
|
||||
@@ -62,14 +64,14 @@ namespace Orchard.Packaging.Controllers {
|
||||
|
||||
[HttpPost, ActionName("RemoveTheme")]
|
||||
public ActionResult RemoveThemePOST(string themeId, string returnUrl, string retryUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove themes")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return UninstallPackage(PackageBuilder.BuildPackageId(themeId, DefaultExtensionTypes.Theme), returnUrl, retryUrl);
|
||||
}
|
||||
|
||||
public ActionResult AddModule(string returnUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add modules")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return View();
|
||||
@@ -77,14 +79,14 @@ namespace Orchard.Packaging.Controllers {
|
||||
|
||||
[HttpPost, ActionName("AddModule")]
|
||||
public ActionResult AddModulePOST(string returnUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to add modules")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return InstallPackage(returnUrl, Request.RawUrl);
|
||||
}
|
||||
|
||||
public ActionResult InstallPackage(string returnUrl, string retryUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to install packages")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
try {
|
||||
@@ -117,7 +119,7 @@ namespace Orchard.Packaging.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult UninstallPackage(string id, string returnUrl, string retryUrl) {
|
||||
if (!_packagingServices.CanManagePackages())
|
||||
if (_shellSettings.Name != ShellSettings.DefaultName || !Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to uninstall packages")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
try {
|
||||
|
@@ -77,7 +77,6 @@
|
||||
<Compile Include="Services\IPackageBuilder.cs" />
|
||||
<Compile Include="Services\IPackageInstaller.cs" />
|
||||
<Compile Include="Services\IPackageManager.cs" />
|
||||
<Compile Include="Services\IPackagingServices.cs" />
|
||||
<Compile Include="Services\IPackagingSourceManager.cs" />
|
||||
<Compile Include="Services\NugetLogger.cs" />
|
||||
<Compile Include="Services\PackageBuilder.cs" />
|
||||
@@ -85,7 +84,6 @@
|
||||
<Compile Include="Services\PackageInstaller.cs" />
|
||||
<Compile Include="Services\PackageManager.cs" />
|
||||
<Compile Include="Services\PackagingEntry.cs" />
|
||||
<Compile Include="Services\PackagingServices.cs" />
|
||||
<Compile Include="Services\PackagingSourceManager.cs" />
|
||||
<Compile Include="ViewModels\PackagingAddSourceViewModel.cs" />
|
||||
<Compile Include="ViewModels\PackagingHarvestViewModel.cs" />
|
||||
@@ -96,6 +94,7 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Images\imagePlaceholder.png" />
|
||||
<Content Include="Content\Images\moduleDefaultIcon.png" />
|
||||
<Content Include="Content\Images\stars.png" />
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="Service References\GalleryServer\Reference.datasvcmap">
|
||||
<Generator>DataServiceClientGenerator</Generator>
|
||||
|
@@ -1,13 +0,0 @@
|
||||
namespace Orchard.Packaging.Services {
|
||||
/// <summary>
|
||||
/// Provides generic packaging related methods.
|
||||
/// </summary>
|
||||
public interface IPackagingServices : IDependency {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies if the current user is allowed to manage packages. The super user of the default tenant site is always allowed.
|
||||
/// </summary>
|
||||
/// <returns>True if the allowed; false otherwise.</returns>
|
||||
bool CanManagePackages();
|
||||
}
|
||||
}
|
@@ -1,4 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Orchard.Packaging.GalleryServer;
|
||||
using Orchard.Packaging.Models;
|
||||
|
||||
namespace Orchard.Packaging.Services {
|
||||
@@ -7,7 +11,7 @@ namespace Orchard.Packaging.Services {
|
||||
void AddSource(string feedTitle, string feedUrl);
|
||||
void RemoveSource(int id);
|
||||
|
||||
IEnumerable<PackagingEntry> GetModuleList(PackagingSource packagingSource = null);
|
||||
IEnumerable<PackagingEntry> GetThemeList(PackagingSource packagingSource = null);
|
||||
IEnumerable<PackagingEntry> GetExtensionList(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null);
|
||||
int GetExtensionCount(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null);
|
||||
}
|
||||
}
|
@@ -17,5 +17,6 @@ namespace Orchard.Packaging.Services {
|
||||
public string IconUrl { get; set; }
|
||||
public double Rating { get; set; }
|
||||
public int RatingsCount { get; set; }
|
||||
public int DownloadCount { get; set; }
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Localization;
|
||||
|
||||
namespace Orchard.Packaging.Services {
|
||||
/// <summary>
|
||||
/// Provides generic packaging related methods.
|
||||
/// </summary>
|
||||
public class PackagingServices : IPackagingServices {
|
||||
private readonly IOrchardServices _orchardServices;
|
||||
private readonly ShellSettings _shellSettings;
|
||||
|
||||
public PackagingServices(IOrchardServices orchardServices,
|
||||
ShellSettings shellSettings) {
|
||||
_orchardServices = orchardServices;
|
||||
_shellSettings = shellSettings;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Verifies if the current user is allowed to manage packages. The super user of the default tenant site is always allowed.
|
||||
/// </summary>
|
||||
/// <returns>True if the allowed; False otherwise.</returns>
|
||||
public bool CanManagePackages() {
|
||||
// Check if super user for default tenant site
|
||||
if (_shellSettings.Name == ShellSettings.DefaultName
|
||||
&& _orchardServices.WorkContext.CurrentUser.UserName == _orchardServices.WorkContext.CurrentSite.SuperUser) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it has permission explicitly assigned
|
||||
return _orchardServices.Authorizer.Authorize(Permissions.ManagePackages, T("Not authorized to manage packages."));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Packaging.GalleryServer;
|
||||
using Orchard.Packaging.Models;
|
||||
@@ -42,30 +42,42 @@ namespace Orchard.Packaging.Services {
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<PackagingEntry> GetModuleList(PackagingSource packagingSource = null) {
|
||||
return GetExtensionList(DefaultExtensionTypes.Module, packagingSource);
|
||||
}
|
||||
public IEnumerable<PackagingEntry> GetThemeList(PackagingSource packagingSource = null) {
|
||||
return GetExtensionList(DefaultExtensionTypes.Theme, packagingSource);
|
||||
}
|
||||
|
||||
private IEnumerable<PackagingEntry> GetExtensionList(string filter = null, PackagingSource packagingSource = null) {
|
||||
public IEnumerable<PackagingEntry> GetExtensionList(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) {
|
||||
return (packagingSource == null ? GetSources() : new[] {packagingSource})
|
||||
.SelectMany(
|
||||
source => {
|
||||
GalleryFeedContext galleryFeedContext = new GalleryFeedContext(new Uri(source.FeedUrl));
|
||||
return galleryFeedContext.Packages
|
||||
.Where(p => p.PackageType == filter)
|
||||
.ToList()
|
||||
.Select(p => {
|
||||
PublishedScreenshot firstScreenshot = galleryFeedContext.Screenshots
|
||||
.Where(s => s.PublishedPackageId == p.Id && s.PublishedPackageVersion == p.Version)
|
||||
.ToList()
|
||||
.FirstOrDefault();
|
||||
return CreatePackageEntry(p, firstScreenshot, packagingSource, galleryFeedContext.GetReadStreamUri(p));
|
||||
});
|
||||
var galleryFeedContext = new GalleryFeedContext(new Uri(source.FeedUrl));
|
||||
IQueryable<PublishedPackage> packages = galleryFeedContext.Packages;
|
||||
|
||||
if (query != null) {
|
||||
packages = query(packages);
|
||||
}
|
||||
|
||||
return packages.ToList().Select(
|
||||
p => {
|
||||
PublishedScreenshot firstScreenshot = galleryFeedContext.Screenshots
|
||||
.Where(s => s.PublishedPackageId == p.Id && s.PublishedPackageVersion == p.Version)
|
||||
.ToList()
|
||||
.FirstOrDefault();
|
||||
return CreatePackageEntry(p, firstScreenshot, packagingSource, galleryFeedContext.GetReadStreamUri(p));
|
||||
});
|
||||
}
|
||||
).ToArray();
|
||||
);
|
||||
}
|
||||
|
||||
public int GetExtensionCount(PackagingSource packagingSource = null, Func<IQueryable<PublishedPackage>, IQueryable<PublishedPackage>> query = null) {
|
||||
return (packagingSource == null ? GetSources() : new[] { packagingSource })
|
||||
.Sum( source => {
|
||||
var galleryFeedContext = new GalleryFeedContext(new Uri(source.FeedUrl));
|
||||
IQueryable<PublishedPackage> packages = galleryFeedContext.Packages;
|
||||
|
||||
if (query != null) {
|
||||
packages = query(packages);
|
||||
}
|
||||
|
||||
return packages.Count();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static PackagingEntry CreatePackageEntry(PublishedPackage package, PublishedScreenshot screenshot, PackagingSource source, Uri downloadUri) {
|
||||
@@ -91,7 +103,8 @@ namespace Orchard.Packaging.Services {
|
||||
IconUrl = iconUrl,
|
||||
FirstScreenshot = firstScreenshot,
|
||||
Rating = package.Rating,
|
||||
RatingsCount = package.RatingsCount
|
||||
RatingsCount = package.RatingsCount,
|
||||
DownloadCount = package.DownloadCount
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -46,4 +46,19 @@
|
||||
.screenshotThumbnail .thumbnail {
|
||||
width: 171px;
|
||||
height: 128px;
|
||||
}
|
||||
|
||||
.ratings {
|
||||
background:url(../Content/Images/stars.png) repeat-x;
|
||||
position: relative;
|
||||
height: 14px;
|
||||
width: 75px;
|
||||
display: block;
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.score {
|
||||
background: url(../Content/Images/stars.png) repeat-x 0 -14px;
|
||||
position: absolute;
|
||||
width: 45px;
|
||||
}
|
@@ -7,5 +7,18 @@ namespace Orchard.Packaging.ViewModels {
|
||||
public IEnumerable<PackagingEntry> Extensions { get; set; }
|
||||
public IEnumerable<PackagingSource> Sources { get; set; }
|
||||
public PackagingSource SelectedSource { get; set; }
|
||||
public PackagingExtensionsOptions Options { get; set; }
|
||||
public dynamic Pager { get; set; }
|
||||
}
|
||||
|
||||
public class PackagingExtensionsOptions {
|
||||
public int? SourceId { get; set; }
|
||||
public PackagingExtensionsOrder Order { get; set; }
|
||||
}
|
||||
|
||||
public enum PackagingExtensionsOrder {
|
||||
Downloads,
|
||||
Ratings,
|
||||
Alphanumeric
|
||||
}
|
||||
}
|
@@ -1,7 +1,17 @@
|
||||
@model Orchard.Packaging.ViewModels.PackagingExtensionsViewModel
|
||||
@using Orchard.Packaging.ViewModels;
|
||||
@using System.Linq;
|
||||
|
||||
@{ Style.Require("PackagingAdmin"); }
|
||||
@{
|
||||
Style.Require("PackagingAdmin");
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if(!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<h1>@Html.TitleForPage(T("Browse Gallery - Modules").Text)</h1>
|
||||
|
||||
@@ -14,56 +24,77 @@
|
||||
@Html.SelectOption(source.Id, Model.SelectedSource != null && Model.SelectedSource.Id == source.Id, source.FeedTitle)
|
||||
}
|
||||
</select>
|
||||
</fieldset>
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Downloads, T("Downloads").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Ratings, T("Ratings").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Alphanumeric, T("Alphanumeric").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach(int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
<select>
|
||||
<button type="submit">@T("Apply")</button>
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
@if (Model.Extensions.Count() > 0) {
|
||||
<ul class="contentItems">
|
||||
@foreach (var item in Model.Extensions) {
|
||||
<li>
|
||||
@{
|
||||
string iconUrl = @item.IconUrl;
|
||||
if (string.IsNullOrWhiteSpace(iconUrl)) {
|
||||
iconUrl = Href("../../Content/Images/ModuleDefaultIcon.png");
|
||||
}
|
||||
}
|
||||
if (Model.Extensions.Count() > 0) {
|
||||
<ul class="contentItems">
|
||||
@foreach (var item in Model.Extensions) {
|
||||
<li>
|
||||
@{
|
||||
string iconUrl = @item.IconUrl;
|
||||
if (string.IsNullOrWhiteSpace(iconUrl)) {
|
||||
iconUrl = Href("../../Content/Images/ModuleDefaultIcon.png");
|
||||
}
|
||||
}
|
||||
|
||||
<div class="iconThumbnail">
|
||||
<div class="extensionDetails column">
|
||||
<div class="extensionName">
|
||||
@if (!string.IsNullOrWhiteSpace(item.GalleryDetailsUrl)) {
|
||||
<a href="@item.GalleryDetailsUrl">
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
</a>
|
||||
} else {
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
}
|
||||
</div>
|
||||
<div class="iconThumbnail">
|
||||
<div class="extensionDetails column">
|
||||
<div class="extensionName">
|
||||
@if (!string.IsNullOrWhiteSpace(item.GalleryDetailsUrl)) {
|
||||
<a href="@item.GalleryDetailsUrl">
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
</a>
|
||||
} else {
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="related">
|
||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary { { "packageId", item.PackageId }, { "version", item.Version }, { "sourceId", item.Source.Id }, { "redirectTo", "Modules" } })@T(" | ")
|
||||
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||
</div>
|
||||
<div class="ratings" style="width:@(15*5)px" title="@T("Ratings: {0} ({1})", item.Rating, item.RatingsCount)">
|
||||
<div class="score" style="width:@(15*(item.Rating))px"> </div>
|
||||
</div>
|
||||
|
||||
<div class="properties">
|
||||
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
|
||||
<ul class="pageStatus">
|
||||
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
|
||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
|
||||
<li> | @T("Rating: {0}", item.Rating)</li>
|
||||
<li> | @T("Ratings Count: {0}", item.RatingsCount)</li>
|
||||
<li> | @T("Website: ")
|
||||
@if (!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> } else { @T("Unknown").ToString() }
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="related">
|
||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary { { "packageId", item.PackageId }, { "version", item.Version }, { "sourceId", item.Source.Id }, { "redirectTo", "Modules" } })@T(" | ")
|
||||
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||
</div>
|
||||
|
||||
<div class="extensionThumbnail column">
|
||||
<img src="@iconUrl" class="thumbnail" alt="module" />
|
||||
</div>
|
||||
</div>
|
||||
</li>}
|
||||
</ul>
|
||||
<div class="properties">
|
||||
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
|
||||
<ul class="pageStatus">
|
||||
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
|
||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
|
||||
<li> | @T("Downloads: {0}", item.DownloadCount)</li>
|
||||
<li> | @T("Website: ")
|
||||
@if (!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> } else { @T("Unknown").ToString() }
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extensionThumbnail column">
|
||||
<img src="@iconUrl" class="thumbnail" alt="module" />
|
||||
</div>
|
||||
</div>
|
||||
</li>}
|
||||
</ul>
|
||||
}
|
||||
|
||||
@Display(Model.Pager)
|
||||
}
|
@@ -1,7 +1,17 @@
|
||||
@model Orchard.Packaging.ViewModels.PackagingExtensionsViewModel
|
||||
@using Orchard.Packaging.ViewModels;
|
||||
@using System.Linq;
|
||||
|
||||
@{ Style.Require("PackagingAdmin"); }
|
||||
@{
|
||||
Style.Require("PackagingAdmin");
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if(!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<h1>@Html.TitleForPage(T("Browse Gallery - Themes").Text)</h1>
|
||||
|
||||
@@ -14,63 +24,82 @@
|
||||
@Html.SelectOption(source.Id, Model.SelectedSource != null && Model.SelectedSource.Id == source.Id, source.FeedTitle)
|
||||
}
|
||||
</select>
|
||||
</fieldset>
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Downloads, T("Downloads").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Ratings, T("Ratings").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, PackagingExtensionsOrder.Alphanumeric, T("Alphanumeric").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach(int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
<select>
|
||||
<button type="submit">@T("Apply")</button>
|
||||
</fieldset>
|
||||
}
|
||||
|
||||
@if (Model.Extensions.Count() > 0) {
|
||||
<ul class="contentItems theme">
|
||||
@foreach (var item in Model.Extensions) {
|
||||
<li>
|
||||
@{
|
||||
string extensionClass = "iconThumbnail";
|
||||
string iconUrl = @item.IconUrl;
|
||||
if (!string.IsNullOrWhiteSpace(@item.FirstScreenshot)) {
|
||||
iconUrl = @item.FirstScreenshot;
|
||||
extensionClass = "screenshotThumbnail";
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(iconUrl)) {
|
||||
iconUrl = Href("../../Content/Images/imagePlaceholder.png");
|
||||
extensionClass = "screenshotThumbnail";
|
||||
}
|
||||
}
|
||||
if (Model.Extensions.Count() > 0) {
|
||||
<ul class="contentItems theme">
|
||||
@foreach (var item in Model.Extensions) {
|
||||
<li>
|
||||
@{
|
||||
string extensionClass = "iconThumbnail";
|
||||
string iconUrl = @item.IconUrl;
|
||||
if (!string.IsNullOrWhiteSpace(@item.FirstScreenshot)) {
|
||||
iconUrl = @item.FirstScreenshot;
|
||||
extensionClass = "screenshotThumbnail";
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(iconUrl)) {
|
||||
iconUrl = Href("../../Content/Images/imagePlaceholder.png");
|
||||
extensionClass = "screenshotThumbnail";
|
||||
}
|
||||
}
|
||||
|
||||
<div class="@extensionClass">
|
||||
<div class="extensionDetails column">
|
||||
<div class="extensionName">
|
||||
@if (!string.IsNullOrWhiteSpace(item.GalleryDetailsUrl)) {
|
||||
<a href="@item.GalleryDetailsUrl">
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
</a>
|
||||
} else {
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
}
|
||||
</div>
|
||||
<div class="@extensionClass">
|
||||
<div class="extensionDetails column">
|
||||
<div class="extensionName">
|
||||
@if (!string.IsNullOrWhiteSpace(item.GalleryDetailsUrl)) {
|
||||
<a href="@item.GalleryDetailsUrl">
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
</a>
|
||||
} else {
|
||||
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="related">
|
||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Themes"}})@T(" | ")
|
||||
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||
</div>
|
||||
<div class="ratings" style="width:@(15*5)px" title="@T("Ratings: {0} ({1})", item.Rating, item.RatingsCount)">
|
||||
<div class="score" style="width:@(15*(item.Rating))px"> </div>
|
||||
</div>
|
||||
|
||||
<div class="properties">
|
||||
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
|
||||
<ul class="pageStatus">
|
||||
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
|
||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
|
||||
<li> | @T("Rating: {0}", item.Rating)</li>
|
||||
<li> | @T("Ratings Count: {0}", item.RatingsCount)</li>
|
||||
<li> | @T("Website: ")
|
||||
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
|
||||
else { @T("Unknown").ToString() }
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="related">
|
||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Themes"}})@T(" | ")
|
||||
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||
</div>
|
||||
|
||||
<div class="extensionThumbnail column">
|
||||
<img src="@iconUrl" class="thumbnail" alt="theme" />
|
||||
</div>
|
||||
</div>
|
||||
</li>}
|
||||
</ul>
|
||||
<div class="properties">
|
||||
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
|
||||
<ul class="pageStatus">
|
||||
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
|
||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
|
||||
<li> | @T("Downloads: {0}", item.DownloadCount)</li>
|
||||
<li> | @T("Website: ")
|
||||
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
|
||||
else { @T("Unknown").ToString() }
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="extensionThumbnail column">
|
||||
<img src="@iconUrl" class="thumbnail" alt="theme" />
|
||||
</div>
|
||||
</div>
|
||||
</li>}
|
||||
</ul>
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user