Initial bit of progress on the next rev of the global widget management UI.

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2011-03-14 15:15:21 -07:00
parent fed8e1c610
commit c17cdf41a5
5 changed files with 128 additions and 234 deletions
@@ -4,14 +4,15 @@ using System.Web.Mvc;
using System.Linq; using System.Linq;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Core.Contents.Controllers; using Orchard.Core.Contents.Controllers;
using Orchard.DisplayManagement;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Logging; using Orchard.Logging;
using Orchard.Mvc.Extensions;
using Orchard.UI.Admin; using Orchard.UI.Admin;
using Orchard.UI.Notify; using Orchard.UI.Notify;
using Orchard.Utility.Extensions; using Orchard.Utility.Extensions;
using Orchard.Widgets.Models; using Orchard.Widgets.Models;
using Orchard.Widgets.Services; using Orchard.Widgets.Services;
using Orchard.Widgets.ViewModels;
namespace Orchard.Widgets.Controllers { namespace Orchard.Widgets.Controllers {
@@ -24,57 +25,69 @@ namespace Orchard.Widgets.Controllers {
public AdminController( public AdminController(
IOrchardServices services, IOrchardServices services,
IWidgetsService widgetsService) { IWidgetsService widgetsService,
IShapeFactory shapeFactory) {
Services = services; Services = services;
_widgetsService = widgetsService; _widgetsService = widgetsService;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
Shape = shapeFactory;
} }
private IOrchardServices Services { get; set; } private IOrchardServices Services { get; set; }
public Localizer T { get; set; } public Localizer T { get; set; }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
dynamic Shape { get; set; }
public ActionResult Index(int? id) { public ActionResult Index(int? layerId) {
IEnumerable<LayerPart> layers = _widgetsService.GetLayers(); IEnumerable<LayerPart> layers = _widgetsService.GetLayers();
LayerPart currentLayer; LayerPart currentLayer;
IEnumerable<WidgetPart> currentLayerWidgets; IEnumerable<WidgetPart> widgets;
if (layers.Count() > 0) { if (layers.Count() > 0) {
currentLayer = id == null ? currentLayer = layerId == null ?
layers.First() : layers.First() :
layers.FirstOrDefault(layer => layer.Id == id); layers.FirstOrDefault(layer => layer.Id == layerId);
if (currentLayer == null && if (currentLayer == null &&
id != null) { layerId != null) {
// Incorrect layer id passed // Incorrect layer id passed
Services.Notifier.Error(T("Layer not found: {0}", id)); Services.Notifier.Error(T("Layer not found: {0}", layerId));
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
currentLayerWidgets = _widgetsService.GetWidgets(currentLayer.Id); widgets = _widgetsService.GetWidgets();
} }
else { else {
currentLayer = null; currentLayer = null;
currentLayerWidgets = new List<WidgetPart>(); widgets = new List<WidgetPart>();
} }
WidgetsIndexViewModel widgetsIndexViewModel = new WidgetsIndexViewModel { //WidgetsIndexViewModel widgetsIndexViewModel = new WidgetsIndexViewModel {
WidgetTypes = _widgetsService.GetWidgetTypes(), // WidgetTypes = _widgetsService.GetWidgetTypes(),
Layers = layers, // Layers = layers,
Zones = _widgetsService.GetZones(), // Zones = _widgetsService.GetZones(),
CurrentLayer = currentLayer, // CurrentLayer = currentLayer,
CurrentLayerWidgets = currentLayerWidgets // CurrentLayerWidgets = currentLayerWidgets
}; //};
return View(widgetsIndexViewModel); //return View(widgetsIndexViewModel);
dynamic viewModel = Shape.ViewModel()
.CurrentLayer(currentLayer)
.Layers(layers)
.Widgets(widgets)
.Zones(_widgetsService.GetZones());
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)viewModel);
} }
[HttpPost, ActionName("Index")] [HttpPost, ActionName("Index")]
public ActionResult IndexWidgetPOST(int? id) { public ActionResult IndexWidgetPOST(int? id, string returnUrl) {
const string moveDownString = "submit.MoveDown."; const string moveDownString = "submit.MoveDown.";
const string moveUpString = "submit.MoveUp."; const string moveUpString = "submit.MoveUp.";
@@ -98,7 +111,7 @@ namespace Orchard.Widgets.Controllers {
this.Error(exception, T("Moving widget failed: {0}", exception.Message), Logger, Services.Notifier); this.Error(exception, T("Moving widget failed: {0}", exception.Message), Logger, Services.Notifier);
} }
return RedirectToAction("Index", "Admin", new { id }); return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
} }
public ActionResult AddWidget(int layerId, string widgetType) { public ActionResult AddWidget(int layerId, string widgetType) {
@@ -216,7 +229,7 @@ namespace Orchard.Widgets.Controllers {
[HttpPost, ActionName("EditLayer")] [HttpPost, ActionName("EditLayer")]
[FormValueRequired("submit.Save")] [FormValueRequired("submit.Save")]
public ActionResult EditLayerSavePOST(int id) { public ActionResult EditLayerSavePOST(int id, string returnUrl) {
if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel)))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
@@ -238,7 +251,7 @@ namespace Orchard.Widgets.Controllers {
this.Error(exception, T("Editing layer failed: {0}", exception.Message), Logger, Services.Notifier); this.Error(exception, T("Editing layer failed: {0}", exception.Message), Logger, Services.Notifier);
} }
return RedirectToAction("Index", "Admin", new { id }); return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
} }
[HttpPost, ActionName("EditLayer")] [HttpPost, ActionName("EditLayer")]
@@ -71,7 +71,6 @@
<Compile Include="Services\RuleContext.cs" /> <Compile Include="Services\RuleContext.cs" />
<Compile Include="Services\WidgetsService.cs" /> <Compile Include="Services\WidgetsService.cs" />
<Compile Include="Shapes.cs" /> <Compile Include="Shapes.cs" />
<Compile Include="ViewModels\WidgetsIndexViewModel.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Content\Admin\images\edit.png" /> <Content Include="Content\Admin\images\edit.png" />
@@ -1,114 +1,57 @@
#main #widgets h2 { #layout-widgets-placement {
border-bottom:none;
}
h4.widgets-layer-header, h4.widgets-zone-header {
font-weight:600;
}
h4.widgets-layer-header {
float:left; float:left;
width:40%; width:65%;
} }
#widgets-placement { }
#layout-widgets-assistance {
.widgetsbag-editor h5 {
color:#4c4c4c;
font-weight:600;
}
.widgets-availableWidgets {
float:right; float:right;
float: left; width:35%;
width: 30%; }
margin: 0 0 0 2em; .widgets-container {
padding:10px;
} }
.widgets-availableWidgets table.items th #widgets-layers-control {
{ margin-bottom:-20px;
background: #f1f1f1;
padding:.5em 0 .3em .2em;
} }
#widgets-layers-control form, #widgets-layers-control fieldset {
.widgets-availableLayers { display:inline;
float: left;
margin: 0 0 0 2em;
width: 60%;
min-width: 40%;
} }
#widgets-layers-control select, #widgets-layers-control a {
.widgets-layerZones {
float: left;
float: right;
width: 60%;
border: 1px solid #eaeaea;
border:1px solid #ccc;
background: #fcfcfc;
}
.widgets-layerZones .widgets-zone {
background:#f5f5f5;
border: 1px solid #f1f1f1;
padding: 1em 2em 1em 2em;
margin: 0 0 .6em 0;
}
.widgets-layerZones .widgets-zoneWidget {
margin: .6em;
padding: 1em 2em 1em 3em;
background:#ffffff;
border: 1px solid #f1f1f1;
vertical-align:middle; vertical-align:middle;
} }
#widgets-layers-control a {
.widgets-availableLayers fieldset margin-left:10px;
{
border: 1px solid #eaeaea;
background: #f1f1f1;
background: -moz-linear-gradient(center top, #f1f1f1, #fcfcfc);
padding: .6em;
} }
.widgets-availableWidgets fieldset { #widgets-zones {
padding: 0; background:#F3F4F5;
border:1px solid #E4E5E6;
padding:0 5px;
} }
#widgets-zones ol {
.widgets-layers { list-style:decimal inside;
border:1px solid #ccc;
border-right:none;
} }
#widgets-zones li {
.widgets-layers ul { background:#FFF;
background: #f5f5f5; color:#AEC3CE;
border: 1px solid #f1f1f1; border:1px solid #EAEAEA;
margin:5px 0;
padding:0 10px;
} }
#widgets-zones h2 {
.widgets-layers ul li font-size:1.077em;
{
padding: .6em .4em;
border:1px solid #F1F1F1;
} }
#widgets-zones h2, #widgets-zones li li {
.widgets-layers .widgets-currentLayer {
background: #c3d9ff;
}
.widgets-layers .widgets-currentLayer a {
color:#333; color:#333;
font-weight: 600;
} }
#widgets-zones li li {
.widgets-layerZones ul li ul { background:#F3F4F5;
margin: 0; border:0;
padding: 0; margin:10px 0;
padding:5px 10px 5px 25px;
} }
#widgets-zones .widgets-mover {
.new-layer { margin-left:-18px;
padding: .6em; vertical-align:-2px;
background: #F5F5F5;
}
.new-layer a {
text-decoration: none;
font-weight: 600;
} }
@@ -1,33 +0,0 @@
using System.Collections.Generic;
using Orchard.Widgets.Models;
namespace Orchard.Widgets.ViewModels
{
public class WidgetsIndexViewModel
{
/// <summary>
/// The available widget content types.
/// </summary>
public IEnumerable<string> WidgetTypes { get; set; }
/// <summary>
/// The available layers.
/// </summary>
public IEnumerable<LayerPart> Layers { get; set; }
/// <summary>
/// The available zones in the page.
/// </summary>
public IEnumerable<string> Zones { get; set; }
/// <summary>
/// The current layer.
/// </summary>
public LayerPart CurrentLayer { get; set; }
/// <summary>
/// The current layer widgets.
/// </summary>
public IEnumerable<WidgetPart> CurrentLayerWidgets { get; set; }
}
}
@@ -1,41 +1,52 @@
@model WidgetsIndexViewModel @using Orchard.Utility.Extensions;
@using Orchard.Widgets.Models; @using Orchard.Widgets.Models;
@using Orchard.Widgets.ViewModels;
@{ @{
Style.Require("WidgetsAdmin"); Style.Require("WidgetsAdmin");
Layout.Title = T("Manage Widgets").ToString(); Layout.Title = T("Manage Widgets").ToString();
IEnumerable<LayerPart> layers = Model.Layers;
IEnumerable<WidgetPart> widgets = Model.Widgets;
IEnumerable<string> zones = Model.Zones;
var returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString();
} }
@using(Html.BeginFormAntiForgeryPost()) {
Html.ValidationSummary();
<div id="widgets" class="group"> <div id="widgets" class="group">
<div id="widgets-layers-control" class="widgets-container">
<div class="widgets-availableLayers"> @if (layers.Count() > 0) {
<h2>Widgets</h2> using (Html.BeginForm("index", "admin", FormMethod.Get, new {area = "Orchard.Widgets"})) {
<fieldset class="bulk-actions-auto">
<fieldset> <label for="layerId">@T("Current Layer:")</label>
<h4 class="widgets-layer-header">Layers</h4> <select id="layerId" name="layerId">
<h4 class="widgets-zone-header">Zones</h4> @foreach (var layer in Model.Layers) {
<div> @Html.SelectOption((int)Model.CurrentLayer.Id, (int)layer.Id, (string)layer.Name)
<ul class="widgets-layerZones"> }
@foreach (string zone in Model.Zones) { </select>
<button type="submit" class="apply-bulk-actions-auto">@T("Show")</button>
@Html.Link(T("Edit").Text, Url.Action("EditLayer", "Admin", new { area = "Orchard.Widgets", id = Model.CurrentLayer.Id, returnUrl }), new { @class = "button" })
</fieldset>
}
}
@Html.Link(T("Add a new layer...").Text, Url.Action("AddLayer", "Admin", new { area = "Orchard.Widgets", returnUrl }))
</div>
<div id="layout-widgets-placement">
<div id="widgets-placement">
<div id="widgets-layers" class="widgets-container">
<div id="widgets-zones">
<ol>
@foreach (string zone in zones) {
<li> <li>
<div class="widgets-zone">@zone</div> <h2>@zone</h2>
<ul> <ul class="widgets-zone-widgets">
@{ @{
int count = Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).Count() - 1; int count = widgets.Where(w => w.Zone == zone).Count() - 1;
int i = 0; int i = 0;
} }
@foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position, new Orchard.UI.FlatPositionComparer())) { @foreach (WidgetPart widget in widgets.Where(w => w.Zone == zone).OrderBy(w => w.Position, new Orchard.UI.FlatPositionComparer())) {
<li class="widgets-zoneWidget"> <li>
@if (i > 0) { @if (i > 0) {
<input type="image" name="submit.MoveUp.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/moveup.gif")" alt="Move up" value="@widget.Id" /> <input class="widgets-mover" type="image" name="submit.MoveUp.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/moveup.gif")" alt="Move up" value="@widget.Id" />
} }
@if (i < count) { @if (i < count) {
<input type="image" name="submit.MoveDown.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/movedown.gif")" alt="Move down" value="@widget.Id" /> <input class="widgets-mover" type="image" name="submit.MoveDown.@widget.Id" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/movedown.gif")" alt="Move down" value="@widget.Id" />
} }
@{ @{
i++; i++;
@@ -46,56 +57,17 @@
</ul> </ul>
</li> </li>
} }
</ul> </ol>
</div> </div>
</div>
<div class="widgets-layers"> </div>
<ul> </div>
@foreach (var layer in Model.Layers) { <div id="layout-widgets-assistance">
var layerClass = "widgets-editLayer"; <div id="widgets-assistance">
if (layer.Id == Model.CurrentLayer.Id) { <div class="widgets-container">
layerClass += " widgets-currentLayer"; <p>[theme preview image]</p>
} <p>[layer visibility]</p>
<li class="@layerClass">
<a href="@Url.Action("EditLayer", new { @layer.Id })" title="@T("Edit {0} layer", layer.Name)">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.png")" />
</a>
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
</li>
}
</ul>
<div class="new-layer">
@Html.ActionLink(T("+ Add a layer").ToString(), "AddLayer", new { })
</div> </div>
</div> </div>
</fieldset>
</div>
<div class="widgets-availableWidgets">
<h2>Available Widgets</h2>
<fieldset>
<table class="items" summary="@T("This is a table of the widgets currently available for use in your application.")">
<colgroup>
<col id="Col1" />
<col id="Col2" />
</colgroup>
<thead>
<tr>
<th scope="col">@T("Name")</th>
<th scope="col"></th>
</tr>
</thead>
@foreach (string widget in Model.WidgetTypes) {
<tr>
<td>@widget</td>
<td>@Html.ActionLink(T("Add to zone").ToString(), "AddWidget", new { layerId = Model.CurrentLayer.Id, widgetType = widget })</td>
</tr>
}
</table>
</fieldset>
</div> </div>
</div> </div>
}