mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Initial bit of progress on the next rev of the global widget management UI.
--HG-- branch : dev
This commit is contained in:
@@ -4,14 +4,15 @@ using System.Web.Mvc;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Contents.Controllers;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Mvc.Extensions;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Utility.Extensions;
|
||||
using Orchard.Widgets.Models;
|
||||
using Orchard.Widgets.Services;
|
||||
using Orchard.Widgets.ViewModels;
|
||||
|
||||
namespace Orchard.Widgets.Controllers {
|
||||
|
||||
@@ -24,57 +25,69 @@ namespace Orchard.Widgets.Controllers {
|
||||
|
||||
public AdminController(
|
||||
IOrchardServices services,
|
||||
IWidgetsService widgetsService) {
|
||||
IWidgetsService widgetsService,
|
||||
IShapeFactory shapeFactory) {
|
||||
|
||||
Services = services;
|
||||
_widgetsService = widgetsService;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
Shape = shapeFactory;
|
||||
}
|
||||
|
||||
private IOrchardServices Services { get; set; }
|
||||
public Localizer T { 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();
|
||||
|
||||
LayerPart currentLayer;
|
||||
IEnumerable<WidgetPart> currentLayerWidgets;
|
||||
IEnumerable<WidgetPart> widgets;
|
||||
|
||||
if (layers.Count() > 0) {
|
||||
currentLayer = id == null ?
|
||||
currentLayer = layerId == null ?
|
||||
layers.First() :
|
||||
layers.FirstOrDefault(layer => layer.Id == id);
|
||||
layers.FirstOrDefault(layer => layer.Id == layerId);
|
||||
|
||||
if (currentLayer == null &&
|
||||
id != null) {
|
||||
layerId != null) {
|
||||
// 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");
|
||||
}
|
||||
|
||||
currentLayerWidgets = _widgetsService.GetWidgets(currentLayer.Id);
|
||||
widgets = _widgetsService.GetWidgets();
|
||||
}
|
||||
else {
|
||||
currentLayer = null;
|
||||
currentLayerWidgets = new List<WidgetPart>();
|
||||
widgets = new List<WidgetPart>();
|
||||
}
|
||||
|
||||
WidgetsIndexViewModel widgetsIndexViewModel = new WidgetsIndexViewModel {
|
||||
WidgetTypes = _widgetsService.GetWidgetTypes(),
|
||||
Layers = layers,
|
||||
Zones = _widgetsService.GetZones(),
|
||||
CurrentLayer = currentLayer,
|
||||
CurrentLayerWidgets = currentLayerWidgets
|
||||
};
|
||||
//WidgetsIndexViewModel widgetsIndexViewModel = new WidgetsIndexViewModel {
|
||||
// WidgetTypes = _widgetsService.GetWidgetTypes(),
|
||||
// Layers = layers,
|
||||
// Zones = _widgetsService.GetZones(),
|
||||
// CurrentLayer = currentLayer,
|
||||
// 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")]
|
||||
public ActionResult IndexWidgetPOST(int? id) {
|
||||
public ActionResult IndexWidgetPOST(int? id, string returnUrl) {
|
||||
const string moveDownString = "submit.MoveDown.";
|
||||
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);
|
||||
}
|
||||
|
||||
return RedirectToAction("Index", "Admin", new { id });
|
||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||
}
|
||||
|
||||
public ActionResult AddWidget(int layerId, string widgetType) {
|
||||
@@ -216,7 +229,7 @@ namespace Orchard.Widgets.Controllers {
|
||||
|
||||
[HttpPost, ActionName("EditLayer")]
|
||||
[FormValueRequired("submit.Save")]
|
||||
public ActionResult EditLayerSavePOST(int id) {
|
||||
public ActionResult EditLayerSavePOST(int id, string returnUrl) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel)))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -238,7 +251,7 @@ namespace Orchard.Widgets.Controllers {
|
||||
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")]
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<Compile Include="Services\RuleContext.cs" />
|
||||
<Compile Include="Services\WidgetsService.cs" />
|
||||
<Compile Include="Shapes.cs" />
|
||||
<Compile Include="ViewModels\WidgetsIndexViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Admin\images\edit.png" />
|
||||
|
||||
@@ -1,114 +1,57 @@
|
||||
#main #widgets h2 {
|
||||
border-bottom:none;
|
||||
#layout-widgets-placement {
|
||||
float:left;
|
||||
width:65%;
|
||||
}
|
||||
#widgets-placement { }
|
||||
#layout-widgets-assistance {
|
||||
float:right;
|
||||
width:35%;
|
||||
}
|
||||
.widgets-container {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
h4.widgets-layer-header, h4.widgets-zone-header {
|
||||
font-weight:600;
|
||||
#widgets-layers-control {
|
||||
margin-bottom:-20px;
|
||||
}
|
||||
#widgets-layers-control form, #widgets-layers-control fieldset {
|
||||
display:inline;
|
||||
}
|
||||
#widgets-layers-control select, #widgets-layers-control a {
|
||||
vertical-align:middle;
|
||||
}
|
||||
#widgets-layers-control a {
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
h4.widgets-layer-header {
|
||||
float:left;
|
||||
width:40%;
|
||||
#widgets-zones {
|
||||
background:#F3F4F5;
|
||||
border:1px solid #E4E5E6;
|
||||
padding:0 5px;
|
||||
}
|
||||
|
||||
|
||||
.widgetsbag-editor h5 {
|
||||
color:#4c4c4c;
|
||||
font-weight:600;
|
||||
#widgets-zones ol {
|
||||
list-style:decimal inside;
|
||||
}
|
||||
|
||||
.widgets-availableWidgets {
|
||||
float: right;
|
||||
float: left;
|
||||
width: 30%;
|
||||
margin: 0 0 0 2em;
|
||||
#widgets-zones li {
|
||||
background:#FFF;
|
||||
color:#AEC3CE;
|
||||
border:1px solid #EAEAEA;
|
||||
margin:5px 0;
|
||||
padding:0 10px;
|
||||
}
|
||||
|
||||
.widgets-availableWidgets table.items th
|
||||
{
|
||||
background: #f1f1f1;
|
||||
padding:.5em 0 .3em .2em;
|
||||
#widgets-zones h2 {
|
||||
font-size:1.077em;
|
||||
}
|
||||
|
||||
.widgets-availableLayers {
|
||||
float: left;
|
||||
margin: 0 0 0 2em;
|
||||
width: 60%;
|
||||
min-width: 40%;
|
||||
#widgets-zones h2, #widgets-zones li li {
|
||||
color:#333;
|
||||
}
|
||||
|
||||
.widgets-layerZones {
|
||||
float: left;
|
||||
float: right;
|
||||
width: 60%;
|
||||
border: 1px solid #eaeaea;
|
||||
border:1px solid #ccc;
|
||||
background: #fcfcfc;
|
||||
#widgets-zones li li {
|
||||
background:#F3F4F5;
|
||||
border:0;
|
||||
margin:10px 0;
|
||||
padding:5px 10px 5px 25px;
|
||||
}
|
||||
|
||||
.widgets-layerZones .widgets-zone {
|
||||
background:#f5f5f5;
|
||||
border: 1px solid #f1f1f1;
|
||||
padding: 1em 2em 1em 2em;
|
||||
margin: 0 0 .6em 0;
|
||||
#widgets-zones .widgets-mover {
|
||||
margin-left:-18px;
|
||||
vertical-align:-2px;
|
||||
}
|
||||
|
||||
.widgets-layerZones .widgets-zoneWidget {
|
||||
margin: .6em;
|
||||
padding: 1em 2em 1em 3em;
|
||||
background:#ffffff;
|
||||
border: 1px solid #f1f1f1;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.widgets-availableLayers fieldset
|
||||
{
|
||||
border: 1px solid #eaeaea;
|
||||
background: #f1f1f1;
|
||||
background: -moz-linear-gradient(center top, #f1f1f1, #fcfcfc);
|
||||
padding: .6em;
|
||||
}
|
||||
|
||||
.widgets-availableWidgets fieldset {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.widgets-layers {
|
||||
border:1px solid #ccc;
|
||||
border-right:none;
|
||||
}
|
||||
|
||||
.widgets-layers ul {
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
.widgets-layers ul li
|
||||
{
|
||||
padding: .6em .4em;
|
||||
border:1px solid #F1F1F1;
|
||||
}
|
||||
|
||||
.widgets-layers .widgets-currentLayer {
|
||||
background: #c3d9ff;
|
||||
}
|
||||
|
||||
.widgets-layers .widgets-currentLayer a {
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.widgets-layerZones ul li ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.new-layer {
|
||||
padding: .6em;
|
||||
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.ViewModels;
|
||||
@{
|
||||
Style.Require("WidgetsAdmin");
|
||||
|
||||
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 class="widgets-availableLayers">
|
||||
<h2>Widgets</h2>
|
||||
|
||||
<fieldset>
|
||||
<h4 class="widgets-layer-header">Layers</h4>
|
||||
<h4 class="widgets-zone-header">Zones</h4>
|
||||
<div>
|
||||
<ul class="widgets-layerZones">
|
||||
@foreach (string zone in Model.Zones) {
|
||||
<div id="widgets" class="group">
|
||||
<div id="widgets-layers-control" class="widgets-container">
|
||||
@if (layers.Count() > 0) {
|
||||
using (Html.BeginForm("index", "admin", FormMethod.Get, new {area = "Orchard.Widgets"})) {
|
||||
<fieldset class="bulk-actions-auto">
|
||||
<label for="layerId">@T("Current Layer:")</label>
|
||||
<select id="layerId" name="layerId">
|
||||
@foreach (var layer in Model.Layers) {
|
||||
@Html.SelectOption((int)Model.CurrentLayer.Id, (int)layer.Id, (string)layer.Name)
|
||||
}
|
||||
</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>
|
||||
<div class="widgets-zone">@zone</div>
|
||||
<ul>
|
||||
<h2>@zone</h2>
|
||||
<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;
|
||||
}
|
||||
@foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position, new Orchard.UI.FlatPositionComparer())) {
|
||||
<li class="widgets-zoneWidget">
|
||||
@foreach (WidgetPart widget in widgets.Where(w => w.Zone == zone).OrderBy(w => w.Position, new Orchard.UI.FlatPositionComparer())) {
|
||||
<li>
|
||||
@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) {
|
||||
<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++;
|
||||
@@ -46,56 +57,17 @@
|
||||
</ul>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="widgets-layers">
|
||||
<ul>
|
||||
@foreach (var layer in Model.Layers) {
|
||||
var layerClass = "widgets-editLayer";
|
||||
if (layer.Id == Model.CurrentLayer.Id) {
|
||||
layerClass += " widgets-currentLayer";
|
||||
}
|
||||
<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>
|
||||
</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 id="layout-widgets-assistance">
|
||||
<div id="widgets-assistance">
|
||||
<div class="widgets-container">
|
||||
<p>[theme preview image]</p>
|
||||
<p>[layer visibility]</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user