Theme preview with black-bar style

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4046081
This commit is contained in:
loudej 2010-01-29 00:15:14 +00:00
parent 2a72d27e74
commit f96c27c1d8
9 changed files with 210 additions and 2 deletions

View File

@ -111,7 +111,10 @@
<Compile Include="Scheduling\Models\Task.cs" />
<Compile Include="Settings\Controllers\SiteSettingsDriver.cs" />
<Compile Include="Settings\Permissions.cs" />
<Compile Include="Themes\Preview\IPreviewTheme.cs" />
<Compile Include="Themes\Preview\PreviewThemeFilter.cs" />
<Compile Include="Themes\Services\AdminThemeSelector.cs" />
<Compile Include="Themes\Preview\PreviewTheme.cs" />
<Compile Include="Themes\Services\SafeModeThemeSelector.cs" />
<Compile Include="Settings\AdminMenu.cs" />
<Compile Include="Settings\Controllers\AdminController.cs" />
@ -130,6 +133,7 @@
<Compile Include="Themes\Records\ThemeSiteSettingsRecord.cs" />
<Compile Include="Themes\Services\SiteThemeSelector.cs" />
<Compile Include="Themes\Services\ThemeService.cs" />
<Compile Include="Themes\ViewModels\PreviewViewModel.cs" />
<Compile Include="Themes\ViewModels\ThemesIndexViewModel.cs" />
<Compile Include="XmlRpc\Controllers\HomeController.cs" />
<Compile Include="XmlRpc\Controllers\LiveWriterController.cs" />
@ -184,6 +188,7 @@
<Content Include="Themes\Theme.png" />
<Content Include="Themes\Theme.txt" />
<Content Include="Themes\Styles\site.css" />
<Content Include="Themes\Views\Admin\ThemePreview.ascx" />
<Content Include="Themes\Views\Admin\Install.aspx" />
<Content Include="Themes\Views\Header.ascx" />
<Content Include="Themes\Views\Document.aspx" />

View File

@ -1,6 +1,8 @@
using System;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using Orchard.Core.Themes.Preview;
using Orchard.Core.Themes.ViewModels;
using Orchard.Localization;
using Orchard.Security;
@ -12,11 +14,13 @@ namespace Orchard.Core.Themes.Controllers {
[ValidateInput(false)]
public class AdminController : Controller {
private readonly IThemeService _themeService;
private readonly IPreviewTheme _previewTheme;
private readonly IAuthorizer _authorizer;
private readonly INotifier _notifier;
public AdminController(IThemeService themeService, IAuthorizer authorizer, INotifier notifier) {
public AdminController(IThemeService themeService, IPreviewTheme previewTheme, IAuthorizer authorizer, INotifier notifier) {
_themeService = themeService;
_previewTheme = previewTheme;
_authorizer = authorizer;
_notifier = notifier;
T = NullLocalizer.Instance;
@ -37,6 +41,48 @@ namespace Orchard.Core.Themes.Controllers {
}
}
[HttpPost, FormValueAbsent("submit.Apply"), FormValueAbsent("submit.Cancel")]
public ActionResult Preview(string themeName, string returnUrl) {
try {
if (!_authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't preview the current theme")))
return new HttpUnauthorizedResult();
_previewTheme.SetPreviewTheme(themeName);
return Redirect(returnUrl ?? "~/");
}
catch (Exception exception) {
_notifier.Error(T("Previewing theme failed: " + exception.Message));
return RedirectToAction("Index");
}
}
[HttpPost, ActionName("Preview"), FormValueRequired("submit.Apply")]
public ActionResult ApplyPreview(string themeName, string returnUrl) {
try {
if (!_authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't preview the current theme")))
return new HttpUnauthorizedResult();
_previewTheme.SetPreviewTheme(null);
return Redirect(returnUrl ?? "~/");
}
catch (Exception exception) {
_notifier.Error(T("Previewing theme failed: " + exception.Message));
return RedirectToAction("Index");
}
}
[HttpPost, ActionName("Preview"), FormValueRequired("submit.Cancel")]
public ActionResult CancelPreview(string returnUrl) {
try {
if (!_authorizer.Authorize(Permissions.ApplyTheme, T("Couldn't preview the current theme")))
return new HttpUnauthorizedResult();
_previewTheme.SetPreviewTheme(null);
return RedirectToAction("Index");
}
catch (Exception exception) {
_notifier.Error(T("Previewing theme failed: " + exception.Message));
return RedirectToAction("Index");
}
}
[HttpPost]
public ActionResult Activate(string themeName) {
try {
@ -85,5 +131,32 @@ namespace Orchard.Core.Themes.Controllers {
return RedirectToAction("Index");
}
}
class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
private readonly string _submitButtonName;
public FormValueRequiredAttribute(string submitButtonName) {
_submitButtonName = submitButtonName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
var value = controllerContext.HttpContext.Request.Form[_submitButtonName];
return !string.IsNullOrEmpty(value);
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
class FormValueAbsentAttribute : ActionMethodSelectorAttribute {
private readonly string _submitButtonName;
public FormValueAbsentAttribute(string submitButtonName) {
_submitButtonName = submitButtonName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
var value = controllerContext.HttpContext.Request.Form[_submitButtonName];
return string.IsNullOrEmpty(value);
}
}
}
}

View File

@ -0,0 +1,6 @@
namespace Orchard.Core.Themes.Preview {
public interface IPreviewTheme : IDependency {
string GetPreviewTheme();
void SetPreviewTheme(string themeName);
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Web;
using System.Web.Routing;
using Orchard.Themes;
namespace Orchard.Core.Themes.Preview {
public class PreviewTheme : IPreviewTheme, IThemeSelector {
private static readonly string PreviewThemeKey = typeof(PreviewTheme).FullName;
private readonly HttpContextBase _httpContext;
public PreviewTheme(HttpContextBase httpContext) {
_httpContext = httpContext;
}
public string GetPreviewTheme() {
return Convert.ToString(_httpContext.Session[PreviewThemeKey]);
}
public void SetPreviewTheme(string themeName) {
if (string.IsNullOrEmpty(themeName)) {
_httpContext.Session.Remove(PreviewThemeKey);
}
else {
_httpContext.Session[PreviewThemeKey] = themeName;
}
}
public ThemeSelectorResult GetTheme(RequestContext context) {
var previewThemeName = GetPreviewTheme();
if (string.IsNullOrEmpty(previewThemeName))
return null;
return new ThemeSelectorResult { Priority = 90, ThemeName = previewThemeName };
}
}
}

View File

@ -0,0 +1,46 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.Core.Themes.ViewModels;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels;
using Orchard.Themes;
namespace Orchard.Core.Themes.Preview {
public class PreviewThemeFilter : FilterProvider, IResultFilter {
private readonly IThemeService _themeService;
private readonly IPreviewTheme _previewTheme;
public PreviewThemeFilter(IThemeService themeService, IPreviewTheme previewTheme) {
_themeService = themeService;
_previewTheme = previewTheme;
}
public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewResult = filterContext.Result as ViewResult;
if (viewResult == null)
return;
var baseViewModel = viewResult.ViewData.Model as BaseViewModel;
if (baseViewModel == null)
return;
var previewThemeName = _previewTheme.GetPreviewTheme();
if (string.IsNullOrEmpty(previewThemeName))
return;
var themes = _themeService.GetInstalledThemes();
var model = new PreviewViewModel {
Themes = themes.Select(theme => new SelectListItem {
Text = theme.DisplayName,
Value = theme.ThemeName,
Selected = theme.ThemeName == previewThemeName
})
};
baseViewModel.Zones.AddRenderPartial("body:before", "Admin/ThemePreview", model);
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
}
}
}

View File

@ -18,7 +18,7 @@ namespace Orchard.Core.Themes.Services {
if (!context.HttpContext.Request.Path.StartsWith(Path.Combine(siteUrl, "admin").Replace("\\", "/"), true, CultureInfo.InvariantCulture))
return null;
return new ThemeSelectorResult { Priority = 0, ThemeName = "TheAdmin" };
return new ThemeSelectorResult { Priority = 100, ThemeName = "TheAdmin" };
}
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Orchard.Core.Themes.ViewModels {
public class PreviewViewModel {
public IEnumerable<SelectListItem> Themes { get; set; }
}
}

View File

@ -31,6 +31,11 @@
<%=Html.Encode(theme.HomePage) %>
</p>
<div>
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) { %>
<fieldset>
<button type="submit" title="<%=_Encoded("Preview") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Preview") %></button>
</fieldset>
<% } %>
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) { %>
<fieldset>
<button type="submit" title="<%=_Encoded("Activate") %>" name="themeName" value="<%=theme.ThemeName %>"><%=_Encoded("Activate") %></button>

View File

@ -0,0 +1,25 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<PreviewViewModel>" %>
<%@ Import Namespace="Orchard.Core.Themes.ViewModels"%>
<style type="text/css">
#themepreview, #themepreview fieldset, #themepreview input, #themepreview select
{
margin: 0; padding: 0; border:none; font-size: 1em; width:auto; color: #000;
font-family:Frutiger,"Frutiger Linotype",Univers,Calibri,"Gill Sans","Gill Sans MT","Myriad Pro",Myriad,"DejaVu Sans Condensed","Liberation Sans","Nimbus Sans L",Tahoma,Geneva,"Helvetica Neue",Helvetica,Arial,sans-serif;
}
#themepreview { background: #000; font-size:15px; }
#themepreview span {color: #ccc; }
#themepreview fieldset { margin: 0; padding: 3px; }
#themepreview button { font-size: .8em; }
</style>
<div id="themepreview">
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Preview", new{Controller="Admin", Area="Themes"}), FormMethod.Post, new { @class = "inline" })) { %>
<fieldset>
<span><%=T("You are previewing ")%></span>
<%=Html.DropDownList("ThemeName", Model.Themes, new {onChange = "this.form.submit();"})%>
<button type="submit" title="<%=_Encoded("Preview")%>" name="submit.Preview" value="<%=_Encoded("Preview")%>"><%=_Encoded("Preview")%></button>
<button type="submit" title="<%=_Encoded("Apply")%>" name="submit.Apply" value="<%=_Encoded("Apply")%>"><%=_Encoded("Apply") %></button>
<button type="submit" title="<%=_Encoded("Cancel")%>" name="submit.Cancel" value="<%=_Encoded("Cancel")%>"><%=_Encoded("Cancel")%></button>
<%=Html.Hidden("ReturnUrl", Context.Request.Url)%>
</fieldset>
<% } %>
</div>