mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-24 13:33:34 +08:00
Adding recently installed indication.
--HG-- branch : dev
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Orchard.Data.Migration;
|
using Orchard.Data.Migration;
|
||||||
@@ -52,12 +53,15 @@ namespace Orchard.Modules.Controllers {
|
|||||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage modules")))
|
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage modules")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
var modules = _extensionManager.AvailableExtensions().Where(x => DefaultExtensionTypes.IsModule(x.ExtensionType));
|
IEnumerable<Module> modules = _extensionManager.AvailableExtensions()
|
||||||
|
.Where(x => DefaultExtensionTypes.IsModule(x.ExtensionType))
|
||||||
|
.Select(extensionDescriptor => new Module(extensionDescriptor) {
|
||||||
|
IsRecentlyInstalled = _moduleService.UpdateIsRecentlyInstalled(extensionDescriptor)
|
||||||
|
});
|
||||||
|
|
||||||
return View(new ModulesIndexViewModel {
|
return View(new ModulesIndexViewModel {
|
||||||
Modules = modules,
|
Modules = modules,
|
||||||
InstallModules = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "PackagingServices") != null,
|
InstallModules = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "PackagingServices") != null
|
||||||
BrowseToGallery = _featureManager.GetEnabledFeatures().FirstOrDefault(f => f.Id == "Gallery") != null
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,12 +71,14 @@ namespace Orchard.Modules.Controllers {
|
|||||||
|
|
||||||
var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate();
|
var featuresThatNeedUpdate = _dataMigrationManager.GetFeaturesThatNeedUpdate();
|
||||||
|
|
||||||
var features = _featureManager.GetAvailableFeatures()
|
IEnumerable<ModuleFeature> features = _featureManager.GetAvailableFeatures()
|
||||||
.Where(f => !DefaultExtensionTypes.IsTheme(f.Extension.ExtensionType))
|
.Where(f => !DefaultExtensionTypes.IsTheme(f.Extension.ExtensionType))
|
||||||
.Select(f=>new ModuleFeature{Descriptor=f,
|
.Select(f => new ModuleFeature {
|
||||||
IsEnabled=_shellDescriptor.Features.Any(sf=>sf.Name==f.Id),
|
Descriptor = f,
|
||||||
NeedsUpdate=featuresThatNeedUpdate.Contains(f.Id)})
|
IsEnabled = _shellDescriptor.Features.Any(sf => sf.Name == f.Id),
|
||||||
.ToList();
|
IsRecentlyInstalled = _moduleService.UpdateIsRecentlyInstalled(f.Extension),
|
||||||
|
NeedsUpdate = featuresThatNeedUpdate.Contains(f.Id)
|
||||||
|
});
|
||||||
|
|
||||||
return View(new FeaturesViewModel { Features = features });
|
return View(new FeaturesViewModel { Features = features });
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,8 @@
|
|||||||
<Compile Include="Controllers\AdminController.cs" />
|
<Compile Include="Controllers\AdminController.cs" />
|
||||||
<Compile Include="Extensions\StringExtensions.cs" />
|
<Compile Include="Extensions\StringExtensions.cs" />
|
||||||
<Compile Include="Models\DoghouseComparer.cs" />
|
<Compile Include="Models\DoghouseComparer.cs" />
|
||||||
|
<Compile Include="Services\IModuleService.cs" />
|
||||||
|
<Compile Include="ViewModels\Module.cs" />
|
||||||
<Compile Include="ViewModels\ModuleFeature.cs" />
|
<Compile Include="ViewModels\ModuleFeature.cs" />
|
||||||
<Compile Include="ViewModels\FeaturesViewModel.cs" />
|
<Compile Include="ViewModels\FeaturesViewModel.cs" />
|
||||||
<Compile Include="Permissions.cs" />
|
<Compile Include="Permissions.cs" />
|
||||||
|
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Modules.Services {
|
||||||
|
public interface IModuleService : IDependency {
|
||||||
|
void EnableFeatures(IEnumerable<string> featureNames);
|
||||||
|
void EnableFeatures(IEnumerable<string> featureNames, bool force);
|
||||||
|
void DisableFeatures(IEnumerable<string> featureNames);
|
||||||
|
void DisableFeatures(IEnumerable<string> featureNames, bool force);
|
||||||
|
bool UpdateIsRecentlyInstalled(ExtensionDescriptor module);
|
||||||
|
}
|
||||||
|
}
|
@@ -5,44 +5,35 @@ using Orchard.Environment.Extensions;
|
|||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.Environment.Descriptor;
|
using Orchard.Environment.Descriptor;
|
||||||
using Orchard.Environment.Descriptor.Models;
|
using Orchard.Environment.Descriptor.Models;
|
||||||
|
using Orchard.FileSystems.VirtualPath;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Modules.ViewModels;
|
using Orchard.Modules.ViewModels;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
|
||||||
namespace Orchard.Modules.Services {
|
namespace Orchard.Modules.Services {
|
||||||
public interface IModuleService : IDependency {
|
|
||||||
void EnableFeatures(IEnumerable<string> featureNames);
|
|
||||||
void EnableFeatures(IEnumerable<string> featureNames, bool force);
|
|
||||||
void DisableFeatures(IEnumerable<string> featureNames);
|
|
||||||
void DisableFeatures(IEnumerable<string> featureNames, bool force);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ModuleService : IModuleService {
|
public class ModuleService : IModuleService {
|
||||||
|
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
private readonly IShellDescriptorManager _shellDescriptorManager;
|
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||||
|
|
||||||
public ModuleService(
|
public ModuleService(
|
||||||
IOrchardServices orchardServices,
|
IOrchardServices orchardServices,
|
||||||
|
IVirtualPathProvider virtualPathProvider,
|
||||||
IExtensionManager extensionManager,
|
IExtensionManager extensionManager,
|
||||||
IShellDescriptorManager shellDescriptorManager) {
|
IShellDescriptorManager shellDescriptorManager) {
|
||||||
|
|
||||||
Services = orchardServices;
|
Services = orchardServices;
|
||||||
|
|
||||||
|
_virtualPathProvider = virtualPathProvider;
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
_shellDescriptorManager = shellDescriptorManager;
|
_shellDescriptorManager = shellDescriptorManager;
|
||||||
|
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
public IOrchardServices Services { get; set; }
|
public IOrchardServices Services { get; set; }
|
||||||
|
|
||||||
//public IModule GetModuleByName(string moduleName) {
|
|
||||||
// return _extensionManager
|
|
||||||
// .AvailableExtensions()
|
|
||||||
// .Where(e => string.Equals(e.Name, moduleName, StringComparison.OrdinalIgnoreCase))
|
|
||||||
// .Where(e => string.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase))
|
|
||||||
// .Select(descriptor => AssembleModuleFromDescriptor(descriptor))
|
|
||||||
// .FirstOrDefault();
|
|
||||||
//}
|
|
||||||
|
|
||||||
public IEnumerable<ModuleFeature> GetAvailableFeatures() {
|
public IEnumerable<ModuleFeature> GetAvailableFeatures() {
|
||||||
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().Features;
|
var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().Features;
|
||||||
return _extensionManager.AvailableExtensions()
|
return _extensionManager.AvailableExtensions()
|
||||||
@@ -103,6 +94,31 @@ namespace Orchard.Modules.Services {
|
|||||||
shellDescriptor.Parameters);
|
shellDescriptor.Parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the recently installed flag by using the project's last written time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="descriptor">The extension descriptor.</param>
|
||||||
|
public bool UpdateIsRecentlyInstalled(ExtensionDescriptor descriptor) {
|
||||||
|
string projectFile = GetManifestPath(descriptor);
|
||||||
|
if (!string.IsNullOrEmpty(projectFile)) {
|
||||||
|
// If project file was modified less than 24 hours ago, the module was recently deployed
|
||||||
|
return DateTime.UtcNow.Subtract(_virtualPathProvider.GetFileLastWriteTimeUtc(projectFile)) < new TimeSpan(1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetManifestPath(ExtensionDescriptor descriptor) {
|
||||||
|
string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
|
||||||
|
"module.txt");
|
||||||
|
|
||||||
|
if (!_virtualPathProvider.FileExists(projectPath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectPath;
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable<string> EnableFeature(string featureName, IEnumerable<ModuleFeature> features, bool force) {
|
private IEnumerable<string> EnableFeature(string featureName, IEnumerable<ModuleFeature> features, bool force) {
|
||||||
var featuresList = features.ToList();
|
var featuresList = features.ToList();
|
||||||
var getDisabledDependencies =
|
var getDisabledDependencies =
|
||||||
|
@@ -4,5 +4,4 @@ namespace Orchard.Modules.ViewModels {
|
|||||||
public class FeaturesViewModel {
|
public class FeaturesViewModel {
|
||||||
public IEnumerable<ModuleFeature> Features { get; set; }
|
public IEnumerable<ModuleFeature> Features { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
src/Orchard.Web/Modules/Orchard.Modules/ViewModels/Module.cs
Normal file
36
src/Orchard.Web/Modules/Orchard.Modules/ViewModels/Module.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Modules.ViewModels {
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a module.
|
||||||
|
/// </summary>
|
||||||
|
public class Module {
|
||||||
|
/// <summary>
|
||||||
|
/// Default constructor.
|
||||||
|
/// </summary>
|
||||||
|
public Module() {}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a module based on an extension descriptor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extensionDescriptor">The extension descriptor.</param>
|
||||||
|
public Module(ExtensionDescriptor extensionDescriptor) {
|
||||||
|
Descriptor = extensionDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The module's extension descriptor.
|
||||||
|
/// </summary>
|
||||||
|
public ExtensionDescriptor Descriptor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the module needs a version update.
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedsVersionUpdate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the feature was recently installed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRecentlyInstalled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,9 +1,33 @@
|
|||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
namespace Orchard.Modules.ViewModels {
|
namespace Orchard.Modules.ViewModels {
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a module's feature.
|
||||||
|
/// </summary>
|
||||||
public class ModuleFeature {
|
public class ModuleFeature {
|
||||||
|
/// <summary>
|
||||||
|
/// The feature descriptor.
|
||||||
|
/// </summary>
|
||||||
public FeatureDescriptor Descriptor { get; set; }
|
public FeatureDescriptor Descriptor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the feature is enabled.
|
||||||
|
/// </summary>
|
||||||
public bool IsEnabled { get; set; }
|
public bool IsEnabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the feature needs a data update / migration.
|
||||||
|
/// </summary>
|
||||||
public bool NeedsUpdate { get; set; }
|
public bool NeedsUpdate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the module needs a version update.
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedsVersionUpdate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the feature was recently installed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRecentlyInstalled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,11 +1,8 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Orchard.Environment.Extensions.Models;
|
|
||||||
|
|
||||||
namespace Orchard.Modules.ViewModels {
|
namespace Orchard.Modules.ViewModels {
|
||||||
public class ModulesIndexViewModel {
|
public class ModulesIndexViewModel {
|
||||||
public bool InstallModules { get; set; }
|
public bool InstallModules { get; set; }
|
||||||
public bool BrowseToGallery { get; set; }
|
public IEnumerable<Module> Modules { get; set; }
|
||||||
public IEnumerable<ExtensionDescriptor> Modules { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -43,6 +43,11 @@
|
|||||||
if (feature == features.Last()) {
|
if (feature == features.Last()) {
|
||||||
featureClassName += " last";
|
featureClassName += " last";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (feature.IsRecentlyInstalled) {
|
||||||
|
featureClassName += " recentlyInstalledFeature";
|
||||||
|
}
|
||||||
|
|
||||||
var dependencies = (from d in feature.Descriptor.Dependencies
|
var dependencies = (from d in feature.Descriptor.Dependencies
|
||||||
select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
select (from f in Model.Features where f.Descriptor.Id == d select f).SingleOrDefault()).Where(f => f != null).OrderBy(f => f.Descriptor.Name);
|
||||||
var missingDependencies = feature.Descriptor.Dependencies
|
var missingDependencies = feature.Descriptor.Dependencies
|
||||||
|
@@ -14,23 +14,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@if (Model.Modules.Count() > 0) {
|
@if (Model.Modules.Count() > 0) {
|
||||||
<ul class="contentItems">
|
<ul class="contentItems">
|
||||||
@foreach (var module in Model.Modules.OrderBy(m => m.Name)) {
|
@foreach (var module in Model.Modules.OrderBy(m => m.Descriptor.Name)) {
|
||||||
<li>
|
string moduleClasses = module.IsRecentlyInstalled ? "recentlyInstalledModule" : string.Empty;
|
||||||
<div class="summary">
|
|
||||||
<div class="properties">
|
<li class="@moduleClasses">
|
||||||
<h2>@module.Name<span> - @T("Version: {0}", !string.IsNullOrEmpty(module.Version) ? module.Version : T("1.0").ToString())</span></h2>
|
<div class="summary">
|
||||||
@if (!string.IsNullOrEmpty(module.Description)) {
|
<div class="properties">
|
||||||
<p>@module.Description</p>}
|
<h2>@module.Descriptor.Name<span> - @T("Version: {0}", !string.IsNullOrEmpty(module.Descriptor.Version) ? module.Descriptor.Version : T("1.0").ToString())</span></h2>
|
||||||
<ul class="pageStatus" style="color:#666; margin:.6em 0 0 0;">
|
@if (!string.IsNullOrEmpty(module.Descriptor.Description)) {
|
||||||
<li>@T("Features: {0}", MvcHtmlString.Create(string.Join(", ", module.Features.Select(f => Html.Link(string.IsNullOrEmpty(f.Name) ? f.Id : f.Name, string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Id.AsFeatureId(n => T(n)))).ToString()).OrderBy(s => s).ToArray())))</li>
|
<p>@module.Descriptor.Description</p>}
|
||||||
<li> | @T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : T("Unknown").ToString())</li>
|
<ul class="pageStatus" style="color:#666; margin:.6em 0 0 0;">
|
||||||
<li> | @T("Website: ")
|
<li>@T("Features: {0}", MvcHtmlString.Create(string.Join(", ", module.Descriptor.Features.Select(f => Html.Link(string.IsNullOrEmpty(f.Name) ? f.Id : f.Name, string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Id.AsFeatureId(n => T(n)))).ToString()).OrderBy(s => s).ToArray())))</li>
|
||||||
@if (!string.IsNullOrEmpty(module.WebSite)) { <a href="@module.WebSite">@module.WebSite</a> }
|
<li> | @T("Author: {0}", !string.IsNullOrEmpty(module.Descriptor.Author) ? module.Descriptor.Author : T("Unknown").ToString())</li>
|
||||||
else { @T("Unknown").ToString() }
|
<li> | @T("Website: ")
|
||||||
</li>
|
@if (!string.IsNullOrEmpty(module.Descriptor.WebSite)) { <a href="@module.Descriptor.WebSite">@module.Descriptor.WebSite</a> }
|
||||||
</ul>
|
else { @T("Unknown").ToString() }
|
||||||
</div>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
</li>}
|
</div>
|
||||||
</ul>}
|
</div>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
@@ -136,4 +136,13 @@
|
|||||||
.features .feature .actions form.inline.link,
|
.features .feature .actions form.inline.link,
|
||||||
.features .feature .actions a {
|
.features .feature .actions a {
|
||||||
margin-left:.5em;
|
margin-left:.5em;
|
||||||
|
}
|
||||||
|
.recentlyInstalledFeature {
|
||||||
|
background-color: Green;
|
||||||
|
}
|
||||||
|
.recentlyInstalledModule {
|
||||||
|
background-color: Green;
|
||||||
|
}
|
||||||
|
.updateAvailable {
|
||||||
|
background-color: Lime;
|
||||||
}
|
}
|
@@ -47,15 +47,11 @@
|
|||||||
width: 171px;
|
width: 171px;
|
||||||
height: 128px;
|
height: 128px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ratings {
|
.ratings {
|
||||||
background:url(../Content/Images/stars.png) repeat-x;
|
background:url(../Content/Images/stars.png) repeat-x;
|
||||||
position: relative;
|
|
||||||
height: 14px;
|
height: 14px;
|
||||||
width: 75px;
|
width: 75px;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
|
||||||
clear: both;
|
|
||||||
}
|
}
|
||||||
.score {
|
.score {
|
||||||
background: url(../Content/Images/stars.png) repeat-x 0 -14px;
|
background: url(../Content/Images/stars.png) repeat-x 0 -14px;
|
||||||
|
@@ -65,10 +65,6 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</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="related">
|
<div class="related">
|
||||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary { { "packageId", item.PackageId }, { "version", item.Version }, { "sourceId", item.Source.Id }, { "redirectTo", "Modules" } })@T(" | ")
|
@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>
|
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||||
@@ -83,6 +79,11 @@
|
|||||||
<li> | @T("Website: ")
|
<li> | @T("Website: ")
|
||||||
@if (!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> } else { @T("Unknown").ToString() }
|
@if (!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> } else { @T("Unknown").ToString() }
|
||||||
</li>
|
</li>
|
||||||
|
<li> | @T("Rating")
|
||||||
|
<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>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -71,10 +71,6 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</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="related">
|
<div class="related">
|
||||||
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Themes"}})@T(" | ")
|
@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>
|
<a href="@item.PackageStreamUri">@T("Download")</a>
|
||||||
@@ -90,6 +86,11 @@
|
|||||||
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
|
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
|
||||||
else { @T("Unknown").ToString() }
|
else { @T("Unknown").ToString() }
|
||||||
</li>
|
</li>
|
||||||
|
<li> | @T("Rating")
|
||||||
|
<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>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -80,6 +80,7 @@ namespace Orchard.Themes.Controllers {
|
|||||||
})
|
})
|
||||||
.Select(extensionDescriptor => new ThemeEntry(extensionDescriptor) {
|
.Select(extensionDescriptor => new ThemeEntry(extensionDescriptor) {
|
||||||
NeedsUpdate = featuresThatNeedUpdate.Contains(extensionDescriptor.Id),
|
NeedsUpdate = featuresThatNeedUpdate.Contains(extensionDescriptor.Id),
|
||||||
|
IsRecentlyInstalled = _themeService.UpdateIsRecentlyInstalled(extensionDescriptor),
|
||||||
Enabled = _shellDescriptor.Features.Any(sf => sf.Name == extensionDescriptor.Id)
|
Enabled = _shellDescriptor.Features.Any(sf => sf.Name == extensionDescriptor.Id)
|
||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
@@ -1,19 +1,51 @@
|
|||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
namespace Orchard.Themes.Models {
|
namespace Orchard.Themes.Models {
|
||||||
public class ThemeEntry {
|
/// <summary>
|
||||||
|
/// Represents a theme.
|
||||||
|
/// </summary>
|
||||||
|
public class ThemeEntry {
|
||||||
|
/// <summary>
|
||||||
|
/// Default constructor.
|
||||||
|
/// </summary>
|
||||||
public ThemeEntry() {}
|
public ThemeEntry() {}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a theme based on an extension descriptor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extensionDescriptor">The extension descriptor.</param>
|
||||||
public ThemeEntry(ExtensionDescriptor extensionDescriptor) {
|
public ThemeEntry(ExtensionDescriptor extensionDescriptor) {
|
||||||
Descriptor = extensionDescriptor;
|
Descriptor = extensionDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The theme's extension descriptor.
|
||||||
|
/// </summary>
|
||||||
public ExtensionDescriptor Descriptor { get; set; }
|
public ExtensionDescriptor Descriptor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating wether the theme is enabled.
|
||||||
|
/// </summary>
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating wether the theme needs a data update / migration.
|
||||||
|
/// </summary>
|
||||||
public bool NeedsUpdate { get; set; }
|
public bool NeedsUpdate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the module needs a version update.
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedsVersionUpdate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Boolean value indicating if the feature was recently installed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRecentlyInstalled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The theme's name.
|
||||||
|
/// </summary>
|
||||||
public string Name { get { return Descriptor.Name; } }
|
public string Name { get { return Descriptor.Name; } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
<Compile Include="Preview\PreviewThemeFilter.cs" />
|
<Compile Include="Preview\PreviewThemeFilter.cs" />
|
||||||
<Compile Include="Preview\PreviewThemeSelector.cs" />
|
<Compile Include="Preview\PreviewThemeSelector.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Services\IThemeService.cs" />
|
||||||
<Compile Include="Services\SafeModeThemeSelector.cs" />
|
<Compile Include="Services\SafeModeThemeSelector.cs" />
|
||||||
<Compile Include="Services\SiteThemeSelector.cs" />
|
<Compile Include="Services\SiteThemeSelector.cs" />
|
||||||
<Compile Include="Services\SiteThemeService.cs" />
|
<Compile Include="Services\SiteThemeService.cs" />
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
using Orchard.Environment.Extensions.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Themes.Services {
|
||||||
|
public interface IThemeService : IDependency {
|
||||||
|
void DisableThemeFeatures(string themeName);
|
||||||
|
void EnableThemeFeatures(string themeName);
|
||||||
|
bool UpdateIsRecentlyInstalled(ExtensionDescriptor module);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,38 +3,30 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Orchard.Environment.Descriptor;
|
|
||||||
using Orchard.Environment.Descriptor.Models;
|
|
||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Environment.Extensions.Models;
|
using Orchard.Environment.Extensions.Models;
|
||||||
using Orchard.Environment.Features;
|
using Orchard.Environment.Features;
|
||||||
|
using Orchard.FileSystems.VirtualPath;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
|
|
||||||
namespace Orchard.Themes.Services {
|
namespace Orchard.Themes.Services {
|
||||||
public interface IThemeService : IDependency {
|
|
||||||
void DisableThemeFeatures(string themeName);
|
|
||||||
void EnableThemeFeatures(string themeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class ThemeService : IThemeService {
|
public class ThemeService : IThemeService {
|
||||||
private readonly IExtensionManager _extensionManager;
|
private readonly IExtensionManager _extensionManager;
|
||||||
private readonly IFeatureManager _featureManager;
|
private readonly IFeatureManager _featureManager;
|
||||||
private readonly IEnumerable<IThemeSelector> _themeSelectors;
|
private readonly IEnumerable<IThemeSelector> _themeSelectors;
|
||||||
|
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||||
|
|
||||||
public ThemeService(
|
public ThemeService(
|
||||||
IShellDescriptorManager shellDescriptorManager,
|
|
||||||
IExtensionManager extensionManager,
|
IExtensionManager extensionManager,
|
||||||
IFeatureManager featureManager,
|
IFeatureManager featureManager,
|
||||||
IEnumerable<IThemeSelector> themeSelectors,
|
IEnumerable<IThemeSelector> themeSelectors,
|
||||||
|
IVirtualPathProvider virtualPathProvider) {
|
||||||
IWorkContextAccessor workContextAccessor,
|
|
||||||
ShellDescriptor shellDescriptor,
|
|
||||||
IOrchardServices orchardServices) {
|
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
_featureManager = featureManager;
|
_featureManager = featureManager;
|
||||||
_themeSelectors = themeSelectors;
|
_themeSelectors = themeSelectors;
|
||||||
|
_virtualPathProvider = virtualPathProvider;
|
||||||
|
|
||||||
Logger = NullLogger.Instance;
|
Logger = NullLogger.Instance;
|
||||||
T = NullLocalizer.Instance;
|
T = NullLocalizer.Instance;
|
||||||
@@ -120,5 +112,30 @@ namespace Orchard.Themes.Services {
|
|||||||
}
|
}
|
||||||
return themes;
|
return themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the recently installed flag by using the project's last written time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="descriptor">The extension descriptor.</param>
|
||||||
|
public bool UpdateIsRecentlyInstalled(ExtensionDescriptor descriptor) {
|
||||||
|
string projectFile = GetManifestPath(descriptor);
|
||||||
|
if (!string.IsNullOrEmpty(projectFile)) {
|
||||||
|
// If project file was modified less than 24 hours ago, the module was recently deployed
|
||||||
|
return DateTime.UtcNow.Subtract(_virtualPathProvider.GetFileLastWriteTimeUtc(projectFile)) < new TimeSpan(1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetManifestPath(ExtensionDescriptor descriptor) {
|
||||||
|
string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
|
||||||
|
"theme.txt");
|
||||||
|
|
||||||
|
if (!_virtualPathProvider.FileExists(projectPath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,3 +51,6 @@
|
|||||||
.themePreviewImage {
|
.themePreviewImage {
|
||||||
height:300px;
|
height:300px;
|
||||||
}
|
}
|
||||||
|
.recentlyInstalledTheme {
|
||||||
|
background-color: Gray;
|
||||||
|
}
|
@@ -44,7 +44,9 @@
|
|||||||
} else {
|
} else {
|
||||||
<ul class="templates">
|
<ul class="templates">
|
||||||
@foreach (ThemeEntry theme in Model.Themes) {
|
@foreach (ThemeEntry theme in Model.Themes) {
|
||||||
<li>
|
string themeClasses = theme.IsRecentlyInstalled ? "recentlyInstalledTheme" : string.Empty;
|
||||||
|
|
||||||
|
<li class="@themeClasses">
|
||||||
<div>
|
<div>
|
||||||
<h3>@theme.Name</h3>
|
<h3>@theme.Name</h3>
|
||||||
@Html.Image(Href(Html.ThemePath(Model.CurrentTheme.Descriptor, "/Theme.png")), Html.Encode(Model.CurrentTheme.Name), null)
|
@Html.Image(Href(Html.ThemePath(Model.CurrentTheme.Descriptor, "/Theme.png")), Html.Encode(Model.CurrentTheme.Name), null)
|
||||||
|
Reference in New Issue
Block a user