From a37f9675564e9a25b515bd4648d1eaa7cb67eca4 Mon Sep 17 00:00:00 2001 From: Andre Rodrigues Date: Mon, 11 Oct 2010 10:15:15 -0700 Subject: [PATCH] Widget and layer administration. --HG-- branch : dev --- .../Orchard.Tests.Modules.csproj | 1 + .../Widgets/Services/WidgetsServiceTest.cs | 226 +++++++++++++ .../Content/Admin/images/edit.gif | Bin 0 -> 123 bytes .../Content/Admin/images/movedown.gif | Bin 0 -> 963 bytes .../Content/Admin/images/moveup.gif | Bin 0 -> 958 bytes .../Controllers/AdminController.cs | 320 +++++++++++++++++- .../Drivers/LayerPartDriver.cs | 13 + .../Drivers/WidgetPartDriver.cs | 21 ++ .../Orchard.Widgets/Filters/WidgetFilter.cs | 3 +- .../Modules/Orchard.Widgets/Migrations.cs | 18 +- .../Orchard.Widgets/Models/LayerPart.cs | 38 ++- .../Orchard.Widgets/Models/WidgetPart.cs | 58 +++- .../Orchard.Widgets/Orchard.Widgets.csproj | 23 +- .../Orchard.Widgets/ResourceManifest.cs | 5 +- .../Orchard.Widgets/RuleEngine/RuleManager.cs | 2 +- .../Services/IWidgetsService.cs | 28 ++ .../Services/WidgetsService.cs | 135 ++++++++ .../Modules/Orchard.Widgets/Styles/admin.css | 58 +++- .../ViewModels/WidgetsIndexViewModel.cs | 33 ++ .../Views/Admin/AddLayer.cshtml | 5 + .../Views/Admin/AddWidget.cshtml | 5 + .../Views/Admin/EditLayer.cshtml | 9 + .../Views/Admin/EditWidget.cshtml | 9 + .../Orchard.Widgets/Views/Admin/Index.cshtml | 98 +++++- .../Parts/Widgets.Layer.cshtml | 16 + .../Parts/Widgets.Widget.cshtml | 11 + 26 files changed, 1107 insertions(+), 28 deletions(-) create mode 100644 src/Orchard.Tests.Modules/Widgets/Services/WidgetsServiceTest.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/edit.gif create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/movedown.gif create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/moveup.gif create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Services/IWidgetsService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Services/WidgetsService.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/ViewModels/WidgetsIndexViewModel.cs create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddLayer.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddWidget.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Layer.cshtml create mode 100644 src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Widget.cshtml diff --git a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj index c8e3adf1f..9602ca227 100644 --- a/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj +++ b/src/Orchard.Tests.Modules/Orchard.Tests.Modules.csproj @@ -132,6 +132,7 @@ + diff --git a/src/Orchard.Tests.Modules/Widgets/Services/WidgetsServiceTest.cs b/src/Orchard.Tests.Modules/Widgets/Services/WidgetsServiceTest.cs new file mode 100644 index 000000000..792aab17a --- /dev/null +++ b/src/Orchard.Tests.Modules/Widgets/Services/WidgetsServiceTest.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Autofac; +using Moq; +using NUnit.Framework; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.Records; +using Orchard.Core.Common.Models; +using Orchard.Core.Settings.Metadata.Records; +using Orchard.Data; +using Orchard.DisplayManagement; +using Orchard.DisplayManagement.Descriptors; +using Orchard.DisplayManagement.Implementation; +using Orchard.Environment; +using Orchard.Security; +using Orchard.Themes; +using Orchard.Themes.Models; +using Orchard.UI.Notify; +using Orchard.Widgets.Models; +using Orchard.Widgets.Services; + +namespace Orchard.Tests.Modules.Widgets.Services { + + [TestFixture] + public class WidgetsServiceTest : DatabaseEnabledTestsBase { + + private const string ThemeZoneName1 = "sidebar"; + private const string ThemeZoneName2 = "alternative"; + + private IWidgetsService _widgetService; + private IContentManager _contentManager; + + protected override IEnumerable DatabaseTypes { + get { + return new[] { + typeof(LayerPartRecord), + typeof(WidgetPartRecord), + typeof(CommonPartRecord), + typeof(BodyPartRecord), + typeof(ContentPartRecord), + typeof(ContentTypeRecord), + typeof(ContentItemRecord), + typeof(ContentItemVersionRecord), + typeof(ContentTypeDefinitionRecord), + typeof(ContentTypePartDefinitionRecord), + typeof(ContentPartDefinitionRecord), + typeof(ContentPartFieldDefinitionRecord), + typeof(ContentFieldDefinitionRecord) + }; + } + } + + public override void Init() { + base.Init(); + + _widgetService = _container.Resolve(); + _contentManager = _container.Resolve(); + } + + public override void Register(ContainerBuilder builder) { + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterInstance(new Mock().Object); + builder.RegisterInstance(new Mock().Object); + builder.RegisterInstance(new Mock().Object); + builder.RegisterInstance(new Mock().Object); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + + Theme theme1 = new Theme { Zones = ThemeZoneName1 }; + Theme theme2 = new Theme { Zones = ThemeZoneName2 }; + Mock themeServiceMock = new Mock(); + themeServiceMock.Setup(x => x.GetInstalledThemes()).Returns( + (new ITheme[] { theme1, theme2 })); + + builder.RegisterInstance(themeServiceMock.Object).As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); + } + + [Test] + public void GetLayersTest() { + const string layerName1 = "Test layer 1"; + const string layerDescription1 = "Test layer 1"; + const string layerName2 = "Test layer 2"; + const string layerDescription2 = "Test layer 2"; + + IEnumerable layers = _widgetService.GetLayers(); + Assert.That(layers.Count(), Is.EqualTo(0)); + + LayerPart layerPartFirst = _widgetService.CreateLayer(layerName1, layerDescription1, ""); + _contentManager.Flush(); + + layers = _widgetService.GetLayers(); + Assert.That(layers.Count(), Is.EqualTo(1)); + Assert.That(layers.First().Id, Is.EqualTo(layerPartFirst.Id)); + + _widgetService.CreateLayer(layerName2, layerDescription2, ""); + _contentManager.Flush(); + Assert.That(layers.Count(), Is.EqualTo(1)); + } + + [Test] + public void GetLayerTest() { + IEnumerable layers = _widgetService.GetLayers(); + Assert.That(layers.Count(), Is.EqualTo(0), "No layers yet"); + + _widgetService.CreateLayer("Test layer 1", "Test layer 1", ""); + _contentManager.Flush(); + + layers = _widgetService.GetLayers(); + Assert.That(layers.Count(), Is.EqualTo(1), "One layer was created"); + } + + [Test] + public void CreateLayerTest() { + const string layerName = "Test layer 1"; + const string layerDescription = "Test layer 1"; + + IEnumerable layers = _widgetService.GetLayers(); + Assert.That(layers.Count(), Is.EqualTo(0), "No layers yet"); + + _widgetService.CreateLayer(layerName, layerDescription, ""); + _contentManager.Flush(); + + layers = _widgetService.GetLayers(); + LayerPart layer = layers.First(); + Assert.That(layer.Record.Name, Is.EqualTo(layerName)); + Assert.That(layer.Record.Description, Is.EqualTo(layerDescription)); + } + + [Test, Ignore("Fix pending")] + public void GetWidgetTest() { + const string layerName = "Test layer 1"; + const string layerDescription = "Test layer 1"; + const string widgetTitle = "Test widget 1"; + + LayerPart layerPart = _widgetService.CreateLayer(layerName, layerDescription, ""); + _contentManager.Flush(); + + WidgetPart widgetResult = _widgetService.GetWidget(0); + Assert.That(widgetResult, Is.Null); + + WidgetPart widgetPart = _widgetService.CreateWidget(layerPart.Id, "HtmlWidget", widgetTitle, "1", ""); + Assert.That(widgetPart, Is.Not.Null); + + widgetResult = _widgetService.GetWidget(0); + Assert.That(widgetResult, Is.Null, "Still yields null on an invalid identifier"); + + widgetResult = _widgetService.GetWidget(widgetPart.Id); + Assert.That(widgetResult.Id, Is.EqualTo(widgetPart.Id), "Returns correct widget"); + } + + [Test, Ignore("Fix pending")] + public void GetWidgetsTest() { + const string layerName = "Test layer 1"; + const string layerDescription = "Test layer 1"; + const string widgetTitle1 = "Test widget 1"; + const string widgetTitle2 = "Test widget 2"; + + LayerPart layerPart = _widgetService.CreateLayer(layerName, layerDescription, ""); + _contentManager.Flush(); + + IEnumerable widgetResults = _widgetService.GetWidgets(); + Assert.That(widgetResults.Count(), Is.EqualTo(0)); + + WidgetPart widgetPart = _widgetService.CreateWidget(layerPart.Id, "HtmlWidget", widgetTitle1, "1", ""); + Assert.That(widgetPart, Is.Not.Null); + + widgetResults = _widgetService.GetWidgets(); + Assert.That(widgetResults.Count(), Is.EqualTo(1)); + Assert.That(widgetResults.First().Id, Is.EqualTo(widgetPart.Id)); + + _widgetService.CreateWidget(layerPart.Id, "HtmlWidget", widgetTitle2, "2", ""); + widgetResults = _widgetService.GetWidgets(); + Assert.That(widgetResults.Count(), Is.EqualTo(2)); + } + + [Test] + public void CreateWidgetTest() { + const string layerName = "Test layer 1"; + const string layerDescription = "Test layer 1"; + const string widgetTitle = "Test widget 1"; + + LayerPart layerPart = _widgetService.CreateLayer(layerName, layerDescription, ""); + _contentManager.Flush(); + + WidgetPart widgetPart = _widgetService.CreateWidget(layerPart.Id, "HtmlWidget", widgetTitle, "1", ""); + Assert.That(widgetPart, Is.Not.Null); + Assert.That(widgetPart.LayerPart.Id, Is.EqualTo(layerPart.Id)); + } + + [Test] + public void GetZonesTest() + { + IEnumerable zones = _widgetService.GetZones(); + Assert.That(zones.Count(), Is.EqualTo(2), "One zone on the mock list"); + Assert.That(zones.FirstOrDefault(zone => zone == ThemeZoneName1), Is.Not.Null); + Assert.That(zones.FirstOrDefault(zone => zone == ThemeZoneName2), Is.Not.Null); + } + + public class StubLayerPartHandler : ContentHandler { + public StubLayerPartHandler(IRepository layersRepository) { + Filters.Add(new ActivatingFilter("Layer")); + Filters.Add(new ActivatingFilter("Layer")); + Filters.Add(StorageFilter.For(layersRepository)); + } + } + + public class StubWidgetPartHandler : ContentHandler { + public StubWidgetPartHandler(IRepository widgetsRepository) { + Filters.Add(new ActivatingFilter("HtmlWidget")); + Filters.Add(new ActivatingFilter("HtmlWidget")); + Filters.Add(new ActivatingFilter("HtmlWidget")); + Filters.Add(StorageFilter.For(widgetsRepository)); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/edit.gif b/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..498aabfd6760a46f209d7b44c9e79997f87b378d GIT binary patch literal 123 zcmZ?wbhEHblwgoxSj51vbH|QVt5&^z{d(rinP0ztWq<+2pDbXe4u}M)Wngyj*mdWh z!70gRRi)Q^V;PtYdr~5+l$Wm4$!3*MPnXk}RdI`@>h=G%;W@`vwia22aGc0-YH^wQ RvCZaf)wwm_rZX^D0{|R>EpY$< literal 0 HcmV?d00001 diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/movedown.gif b/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/movedown.gif new file mode 100644 index 0000000000000000000000000000000000000000..7c177d8fb3ac1714fcb63c263ff4b64eb1f3b151 GIT binary patch literal 963 zcmW-fPlymi7{y;;&`JmC7I?6t(_}?ou!`UzD7UB}aVpw~Jop7A9RwwzWEP^Jg9btI z0!io(G87fdQW8Pp#lwR@8V^Af(P9M&f*{f1HM?^dX6A!=-}ifO-=mN0+I?^vw&BGS zxZ~d~HvuPb59Zoc%HKuuJl3e{*p3$#Qdn$V06^gvH^ zq6^&^zzB@QAcinJ|Aqrjn6Th^nc5M^00Ww}D2NhKG76(8ilZWGM9rv-s;G{JXb~-= zF`A+|I-*DPjLzta?ih#>F){{YD2BrbM>xX_D?Iy{V@DzrOlY>11z93XW?>d(aaLrF zteKTrmDSmhEwW`cW>Yq2NA}2`*_mD0odY={N9JG-A* z%96bigz3gaGW(jv8HECua7h=s$i=R34cBy~t6c2{w{S~0y2;J%a1Zx%r@P$k0gv!V z4|>RBLu>|Zx;>H4xi`f(Q@^?0at1dRwl95k=KQhmf4KJh`ja1>f8+XVr$65J_353< z*SB6;T|fE4cc=dOlNXlWedgk^wf&bLSp4znFIKMV_=7i&{QB5?Yi}+5@$l!rT>NnD zF!wC(-|_A7D+jh7Sa|i>CzkiVa@(!%9JzAt;BTM&yyc~nAM9MY`tsU;?;rhZ@$BxK z|6VGC(veR+6g_3Y8RetPqvr#`!T>Ap|Tox1n-L$B}B`kl)cw(ouZ@%wjR&;Rhj B(D48O literal 0 HcmV?d00001 diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/moveup.gif b/src/Orchard.Web/Modules/Orchard.Widgets/Content/Admin/images/moveup.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a7220c25f85b2eefc044d99716b8c6c305323bc GIT binary patch literal 958 zcmW-fPlymi7{%X$LYs#yJjDhX1jz&)zMw)1gvx9^1ThvA(OzDVNC!beNM;3%sDu9q zUUmq&P56gs4Y5mvw~wU5NJe!@_E6v@A)>=;cIPn6%m?$n@Aux`eJ?)!%*u9b$J@uS z^WQBCz%e|Ixi;QD+&CZr0s;~+3Qz)tC_+gTqXIQhi7M1YH5$+Yjc7tkG@}DO(1|Ye zL^lR70)rUBNDR-v;eZJXPIz9Xb_5tuAZINKqC^x%QIw40sE8U-8C6j;s-q!VL}N5X z%V>^{=n{|1PfWjk}PHgYp{}4 ztjTINumv00#FlJk2YaxSUF^wj4sZkqImD41ra=cyT6EGA!6Y661qnHcs6ZuDs3MhA zu_{zUm8w!rRjWZQ)Tk!4RI@tNL!IhUPjzcRBQ&TXjnuFVIb_O`Q=asv*^yvEiJWF+ zL6*qEEXtBuoE2FkE3+zVW_31Xi)_rMY?;m3kv+0AyRv6?=Rl6g!5qqwIh;m1(o8Fz zX>SB!x-pT=zGiVop}-|v=pvVNu`67|m9BD4SG&P2+~_8^bhA6$!=3JOPj`F3BRuFK zkM!6On?ajyPvmp%P4UgtZ*KRT$3KfpFJ1oP`;{y2?poq24?lZi{pi{s_2B7i$L~9| zw)>rJpI<$)c=rBpu5Y{j)QQDCHy`}@;-}Z%TR(8;tF0FgET8=E$$X t3#Wd+aOCc*X_V{qVt^_isJ&(chO=Ru>kq`+r_S%K88R literal 0 HcmV?d00001 diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs index 1d2cc8e31..39a1af490 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Controllers/AdminController.cs @@ -1,21 +1,323 @@ -using System.Web.Mvc; +using System; +using System.Collections.Generic; +using System.Web.Mvc; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.Core.Contents.Controllers; using Orchard.Localization; -using Orchard.Settings; +using Orchard.Mvc.Results; +using Orchard.UI.Admin; +using Orchard.UI.Notify; +using Orchard.Widgets.Models; +using Orchard.Widgets.Services; +using Orchard.Widgets.ViewModels; namespace Orchard.Widgets.Controllers { - [ValidateInput(false)] - public class AdminController : Controller { - public AdminController(IOrchardServices services) { + + [ValidateInput(false), Admin] + public class AdminController : Controller, IUpdateModel { + + private const string NotAuthorizedManageWidgetsLabel = "Not authorized to manage widgets"; + + private readonly IWidgetsService _widgetsService; + + public AdminController( + IOrchardServices services, + IWidgetsService widgetsService) { + Services = services; + _widgetsService = widgetsService; + T = NullLocalizer.Instance; } private IOrchardServices Services { get; set; } - protected virtual ISite CurrentSite { get; set; } public Localizer T { get; set; } - public ActionResult Index() { - return View(); + public ActionResult Index(int? id) { + IEnumerable layers = _widgetsService.GetLayers(); + + LayerPart currentLayer; + IEnumerable currentLayerWidgets; + + if (layers.Count() > 0) { + currentLayer = id == null ? + layers.First() : + layers.FirstOrDefault(layer => layer.Id == id); + + currentLayerWidgets = _widgetsService.GetWidgets().Where(widgetPart => widgetPart.LayerPart.Id == currentLayer.Id); + } + else { + currentLayer = null; + currentLayerWidgets = new List(); + } + + WidgetsIndexViewModel widgetsIndexViewModel = new WidgetsIndexViewModel { + WidgetTypes = _widgetsService.GetWidgetTypes(), + Layers = layers, + Zones = _widgetsService.GetZones(), + CurrentLayer = currentLayer, + CurrentLayerWidgets = currentLayerWidgets + }; + + return View(widgetsIndexViewModel); + } + + [HttpPost, ActionName("Index")] + public ActionResult IndexWidgetPOST(int? id) { + const string moveDownString = "submit.MoveDown."; + const string moveUpString = "submit.MoveUp."; + + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + string moveDownAction = HttpContext.Request.Form.AllKeys.FirstOrDefault(key => key.StartsWith(moveDownString)); + if (moveDownAction != null) { + moveDownAction = moveDownAction.Substring(moveDownString.Length, moveDownAction.IndexOf(".", moveDownString.Length) - moveDownString.Length); + _widgetsService.MoveWidgetDown(int.Parse(moveDownAction)); + } + else { + string moveUpAction = HttpContext.Request.Form.AllKeys.FirstOrDefault(key => key.StartsWith(moveUpString)); + if (moveUpAction != null) { + moveUpAction = moveUpAction.Substring(moveUpString.Length, moveUpAction.IndexOf(".", moveUpString.Length) - moveUpString.Length); + _widgetsService.MoveWidgetUp(int.Parse(moveUpAction)); + } + } + } catch (Exception exception) { + Services.Notifier.Error(T("Moving widget failed: {0}", exception.Message)); + } + + return RedirectToAction("Index", "Admin", new { id }); + } + + public ActionResult AddWidget(int layerId, string widgetType) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try + { + WidgetPart widgetPart = Services.ContentManager.New(widgetType); + if (widgetPart == null) + return new NotFoundResult(); + + dynamic model = Services.ContentManager.BuildEditor(widgetPart); + return View(model); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Creating widget failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("AddWidget")] + public ActionResult AddWidgetPOST(int layerId, string widgetType) + { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + int widgetPosition = _widgetsService.GetWidgets(layerId).Count() + 1; + WidgetPart widgetPart = _widgetsService.CreateWidget(layerId, widgetType, "", widgetPosition.ToString(), ""); + if (widgetPart == null) + return new NotFoundResult(); + + var model = Services.ContentManager.UpdateEditor(widgetPart, this); + if (!ModelState.IsValid) { + Services.TransactionManager.Cancel(); + return View(model); + } + + Services.Notifier.Information(T("Your {0} has been created.", widgetPart.TypeDefinition.DisplayName)); + return RedirectToAction("Index"); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Creating widget failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + public ActionResult AddLayer() { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + LayerPart layerPart = Services.ContentManager.New("Layer"); + if (layerPart == null) + return new NotFoundResult(); + + dynamic model = Services.ContentManager.BuildEditor(layerPart); + return View(model); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Creating layer failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("AddLayer")] + public ActionResult AddLayerPOST() { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + LayerPart layerPart = _widgetsService.CreateLayer("", "", ""); + if (layerPart == null) + return new NotFoundResult(); + + var model = Services.ContentManager.UpdateEditor(layerPart, this); + if (!ModelState.IsValid) { + Services.TransactionManager.Cancel(); + return View(model); + } + + Services.Notifier.Information(T("Your {0} has been created.", layerPart.TypeDefinition.DisplayName)); + return RedirectToAction("Index"); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Creating layer failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + public ActionResult EditLayer(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + LayerPart layerPart = _widgetsService.GetLayer(id); + if (layerPart == null) { + return new NotFoundResult(); + } + + dynamic model = Services.ContentManager.BuildEditor(layerPart); + return View(model); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Editing layer failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("EditLayer")] + [FormValueRequired("submit.Save")] + public ActionResult EditLayerSavePOST(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + LayerPart layerPart = _widgetsService.GetLayer(id); + if (layerPart == null) + return new NotFoundResult(); + + var model = Services.ContentManager.UpdateEditor(layerPart, this); + if (!ModelState.IsValid) { + Services.TransactionManager.Cancel(); + return View(model); + } + + Services.Notifier.Information(T("Your {0} has been saved.", layerPart.TypeDefinition.DisplayName)); + return RedirectToAction("Index"); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Editing layer failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("EditLayer")] + [FormValueRequired("submit.Delete")] + public ActionResult EditLayerDeletePOST(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + _widgetsService.DeleteLayer(id); + Services.Notifier.Information(T("Layer was successfully deleted")); + } + catch (Exception exception) { + Services.Notifier.Error(T("Removing Layer failed: {0}", exception.Message)); + } + + return RedirectToAction("Index"); + } + + public ActionResult EditWidget(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + WidgetPart widgetPart = _widgetsService.GetWidget(id); + if (widgetPart == null) { + Services.Notifier.Error(T("Widget not found: {1}", id)); + return RedirectToAction("Index"); + } + + dynamic model = Services.ContentManager.BuildEditor(widgetPart); + return View(model); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Editing widget failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("EditWidget")] + [FormValueRequired("submit.Save")] + public ActionResult EditWidgetSavePOST(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + WidgetPart widgetPart = _widgetsService.GetWidget(id); + if (widgetPart == null) + return new NotFoundResult(); + + var model = Services.ContentManager.UpdateEditor(widgetPart, this); + if (!ModelState.IsValid) { + Services.TransactionManager.Cancel(); + return View(model); + } + + Services.Notifier.Information(T("Your {0} has been saved.", widgetPart.TypeDefinition.DisplayName)); + return RedirectToAction("Index"); + } + catch (Exception exception) + { + Services.Notifier.Error(T("Editing widget failed: {0}", exception.Message)); + return RedirectToAction("Index"); + } + } + + [HttpPost, ActionName("EditWidget")] + [FormValueRequired("submit.Delete")] + public ActionResult EditWidgetDeletePOST(int id) { + if (!Services.Authorizer.Authorize(Permissions.ManageWidgets, T(NotAuthorizedManageWidgetsLabel))) + return new HttpUnauthorizedResult(); + + try { + _widgetsService.DeleteWidget(id); + Services.Notifier.Information(T("Widget was successfully deleted")); + } catch (Exception exception) { + Services.Notifier.Error(T("Removing Widget failed: {0}", exception.Message)); + } + + return RedirectToAction("Index"); + } + + bool IUpdateModel.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { + return base.TryUpdateModel(model, prefix, includeProperties, excludeProperties); + } + + void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) { + ModelState.AddModelError(key, errorMessage.ToString()); } } -} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs index d98496d5f..119115891 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/LayerPartDriver.cs @@ -1,9 +1,22 @@ using JetBrains.Annotations; +using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.Core.ContentsLocation.Models; using Orchard.Widgets.Models; namespace Orchard.Widgets.Drivers { + [UsedImplicitly] public class LayerPartDriver : ContentPartDriver { + + protected override DriverResult Editor(LayerPart layerPart, dynamic shapeHelper) { + ContentLocation location = layerPart.GetLocation("Editor"); + return ContentPartTemplate(layerPart, "Parts/Widgets.Layer").Location(location); + } + + protected override DriverResult Editor(LayerPart layerPart, IUpdateModel updater, dynamic shapeHelper) { + updater.TryUpdateModel(layerPart, Prefix, null, null); + return Editor(layerPart, shapeHelper); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs index 4201afcb0..84683fa01 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Drivers/WidgetPartDriver.cs @@ -1,9 +1,30 @@ using JetBrains.Annotations; +using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.Core.ContentsLocation.Models; using Orchard.Widgets.Models; +using Orchard.Widgets.Services; namespace Orchard.Widgets.Drivers { + [UsedImplicitly] public class WidgetPartDriver : ContentPartDriver { + private readonly IWidgetsService _widgetsService; + + public WidgetPartDriver(IWidgetsService widgetsService) { + _widgetsService = widgetsService; + } + + protected override DriverResult Editor(WidgetPart widgetPart, dynamic shapeHelper) { + widgetPart.AvailableZones = _widgetsService.GetZones(); + + ContentLocation location = widgetPart.GetLocation("Editor"); + return ContentPartTemplate(widgetPart, "Parts/Widgets.Widget").Location(location); + } + + protected override DriverResult Editor(WidgetPart widgetPart, IUpdateModel updater, dynamic shapeHelper) { + updater.TryUpdateModel(widgetPart, Prefix, null, null); + return Editor(widgetPart, shapeHelper); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs index bfaa27810..27a293744 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Filters/WidgetFilter.cs @@ -1,5 +1,4 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.Web.Mvc; using Orchard.ContentManagement; using Orchard.ContentManagement.Aspects; diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs index 1eade65e5..19ac7520b 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs @@ -62,12 +62,14 @@ namespace Orchard.Widgets { ContentDefinitionManager.AlterTypeDefinition("Layer", cfg => cfg .WithPart("LayerPart") + .WithPart("CommonPart") ); ContentDefinitionManager.AlterTypeDefinition("HtmlWidget", cfg => cfg .WithPart("WidgetPart") .WithPart("BodyPart") + .WithPart("CommonPart") .WithSetting("stereotype", "widget") ); @@ -77,7 +79,21 @@ namespace Orchard.Widgets { } public int UpdateFrom1() { - ContentDefinitionManager.AlterPartDefinition("WidgetBagPart", + ContentDefinitionManager.AlterPartDefinition(typeof(LayerPart).Name, + cfg => cfg + .WithLocation(new Dictionary { + {"Editor", new ContentLocation { Zone = "primary", Position = "1" }} + }) + ); + + ContentDefinitionManager.AlterPartDefinition(typeof(WidgetPart).Name, + cfg => cfg + .WithLocation(new Dictionary { + {"Editor", new ContentLocation { Zone = "primary", Position = "1" }} + }) + ); + + ContentDefinitionManager.AlterPartDefinition(typeof(WidgetBagPart).Name, cfg => cfg .WithLocation(new Dictionary { {"Editor", new ContentLocation {Zone = "primary", Position = "5"}} diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs index 22b743b5f..6131fe34b 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Models/LayerPart.cs @@ -1,6 +1,42 @@ -using Orchard.ContentManagement; +using System.ComponentModel.DataAnnotations; +using System.Web.Mvc; +using Orchard.ContentManagement; namespace Orchard.Widgets.Models { public class LayerPart : ContentPart { + + /// + /// The layer's identifier. + /// + [HiddenInput(DisplayValue = false)] + public int Id { + get { return ContentItem.Id; } + } + + /// + /// The layer's name. + /// + [Required] + public string Name { + get { return Record.Name; } + set { Record.Name = value; } + } + + /// + /// The layer's description. + /// + public string Description { + get { return Record.Description; } + set { Record.Description = value; } + } + + /// + /// The layer's rule. + /// The rule defines when the layer is active (should or not be displayed). + /// + public string LayerRule { + get { return Record.LayerRule; } + set { Record.LayerRule = value; } + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs index 36845eb70..2f9a4b8e4 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Models/WidgetPart.cs @@ -1,6 +1,60 @@ -using Orchard.ContentManagement; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; namespace Orchard.Widgets.Models { public class WidgetPart : ContentPart { + + /// + /// The widget's identifier. + /// + [HiddenInput(DisplayValue = false)] + public int Id { + get { return ContentItem.Id; } + } + + /// + /// The widget's title. + /// + [Required] + public string Title { + get { return Record.Title; } + set { Record.Title = value; } + } + + /// + /// The zone where the widget is to be displayed. + /// + [Required] + public string Zone { + get { return Record.Zone; } + set { Record.Zone = value; } + } + + /// + /// The widget's position within the zone. + /// + [HiddenInput(DisplayValue = false)] + public string Position + { + get { return Record.Position; } + set { Record.Position = value; } + } + + /// + /// The layerPart where the widget belongs. + /// + public LayerPart LayerPart { + get { return this.As().Container.As(); } + set { this.As().Container = value; } + } + + /// + /// The available page zones. + /// + [HiddenInput(DisplayValue = false)] + public IEnumerable AvailableZones { get; set; } } -} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj index 8eb9891ed..c06df512c 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Orchard.Widgets.csproj @@ -33,8 +33,13 @@ 4 + + False + ..\..\..\..\lib\claysharp\ClaySharp.dll + + @@ -59,15 +64,15 @@ - + - + @@ -77,8 +82,14 @@ + + + + + + @@ -96,7 +107,15 @@ + + Designer + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/ResourceManifest.cs b/src/Orchard.Web/Modules/Orchard.Widgets/ResourceManifest.cs index d7e09aa23..818280685 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/ResourceManifest.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/ResourceManifest.cs @@ -1,10 +1,9 @@ -using Orchard.UI.Resources; +using Orchard.UI.Resources; namespace Orchard.Widgets { public class ResourceManifest : IResourceManifestProvider { public void BuildManifests(ResourceManifestBuilder builder) { - var manifest = builder.Add(); - manifest.DefineStyle("WidgetsAdmin").SetUrl("admin.css"); + builder.Add().DefineStyle("WidgetsAdmin").SetUrl("admin.css"); } } } diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/RuleEngine/RuleManager.cs b/src/Orchard.Web/Modules/Orchard.Widgets/RuleEngine/RuleManager.cs index 5df76b16c..fb1ca7f60 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/RuleEngine/RuleManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/RuleEngine/RuleManager.cs @@ -35,7 +35,7 @@ namespace Orchard.Widgets.RuleEngine { public class CallbackApi { private readonly RuleManager _ruleManager; - + public CallbackApi(RuleManager ruleManager) { _ruleManager = ruleManager; } diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Services/IWidgetsService.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Services/IWidgetsService.cs new file mode 100644 index 000000000..337dba2ae --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Services/IWidgetsService.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Orchard.Widgets.Models; + +namespace Orchard.Widgets.Services { + public interface IWidgetsService : IDependency { + + IEnumerable GetZones(); + + IEnumerable GetLayers(); + + IEnumerable GetWidgetTypes(); + IEnumerable GetWidgets(); + IEnumerable GetWidgets(int layerId); + + WidgetPart GetWidget(int widgetId); + WidgetPart CreateWidget(int layerId, string widgetType, string title, string position, string zone); + void UpdateWidget(int widgetId, string title, string position, string zone); + void DeleteWidget(int widgetId); + + LayerPart GetLayer(int layerId); + LayerPart CreateLayer(string name, string description, string layerRule); + void UpdateLayer(int layerId, string name, string description, string layerRule); + void DeleteLayer(int layerId); + + void MoveWidgetUp(int widgetId); + void MoveWidgetDown(int widgetId); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Services/WidgetsService.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Services/WidgetsService.cs new file mode 100644 index 000000000..d1972b618 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Services/WidgetsService.cs @@ -0,0 +1,135 @@ +using System.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Themes; +using Orchard.Widgets.Models; + +namespace Orchard.Widgets.Services { + + [UsedImplicitly] + public class WidgetsService : IWidgetsService { + private readonly IThemeService _themeService; + private readonly IContentManager _contentManager; + + public WidgetsService( + IContentManager contentManager, + IThemeService themeService) { + + _contentManager = contentManager; + _themeService = themeService; + } + + public IEnumerable GetWidgetTypes() { + return _contentManager.GetContentTypeDefinitions() + .Where(contentTypeDefinition => contentTypeDefinition.Settings.ContainsKey("stereotype") && contentTypeDefinition.Settings["stereotype"] == "widget") + .Select(contentTypeDefinition => contentTypeDefinition.Name); + } + + public IEnumerable GetLayers() { + return _contentManager + .Query() + .List(); + } + + public IEnumerable GetWidgets() { + return _contentManager + .Query() + .List(); + } + + public IEnumerable GetZones() { + HashSet zones = new HashSet(); + + foreach (var theme in _themeService.GetInstalledThemes().Where(theme => theme.Zones != null && !theme.Zones.Trim().Equals(string.Empty))) { + foreach (string zone in theme.Zones.Split(',').Where(zone => !zones.Contains(zone))) { + zones.Add(zone.Trim()); + } + } + + return zones; + } + + public IEnumerable GetWidgets(int layerId) { + return GetWidgets().Where(widgetPart => widgetPart.As().Container.ContentItem.Id == layerId); + } + + public LayerPart GetLayer(int layerId) { + return GetLayers().FirstOrDefault(layer => layer.Id == layerId); + } + + public LayerPart CreateLayer(string name, string description, string layerRule) { + LayerPart layerPart = _contentManager.Create("Layer", + layer => { + layer.Record.Name = name; + layer.Record.Description = description; + layer.Record.LayerRule = layerRule; + }); + + return layerPart; + } + + public void UpdateLayer(int layerId, string name, string description, string layerRule) { + LayerPart layerPart = GetLayer(layerId); + layerPart.Record.Name = name; + layerPart.Record.Description = description; + layerPart.Record.LayerRule = layerRule; + } + + public void DeleteLayer(int layerId) { + _contentManager.Remove(GetLayer(layerId).ContentItem); + } + + public WidgetPart GetWidget(int widgetId) { + return GetWidgets().FirstOrDefault(widgetPart => widgetPart.Id == widgetId); + } + + public WidgetPart CreateWidget(int layerId, string widgetType, string title, string position, string zone) { + LayerPart layerPart = GetLayer(layerId); + + WidgetPart widgetPart = _contentManager.Create(widgetType, + widget => { + widget.Record.Title = title; + widget.Record.Position = position; + widget.Record.Zone = zone; + widget.LayerPart = layerPart; + }); + + return widgetPart; + } + + public void UpdateWidget(int widgetId, string title, string position, string zone) { + WidgetPart widgetPart = GetWidget(widgetId); + widgetPart.Record.Title = title; + widgetPart.Record.Position = position; + widgetPart.Record.Zone = zone; + } + + public void DeleteWidget(int widgetId) { + _contentManager.Remove(GetWidget(widgetId).ContentItem); + } + + public void MoveWidgetUp(int widgetId) { + WidgetPart widgetPart = GetWidget(widgetId); + + int currentPosition = int.Parse(widgetPart.Record.Position); + if (currentPosition > 0) { + WidgetPart widgetBefore = GetWidgets(widgetPart.LayerPart.Id).FirstOrDefault(widgetPartBefore => widgetPartBefore.Record.Position == (currentPosition - 1).ToString()); + widgetBefore.Record.Position = currentPosition.ToString(); + widgetPart.Record.Position = (currentPosition - 1).ToString(); + } + } + + public void MoveWidgetDown(int widgetId) { + WidgetPart widgetPart = GetWidget(widgetId); + + int currentPosition = int.Parse(widgetPart.Record.Position); + if (currentPosition < GetWidgets(widgetPart.LayerPart.Id).Count()) { + WidgetPart widgetAfter = GetWidgets(widgetPart.LayerPart.Id).FirstOrDefault(widgetPartAfter => widgetPartAfter.Record.Position == (currentPosition + 1).ToString()); + widgetAfter.Record.Position = currentPosition.ToString(); + widgetPart.Record.Position = (currentPosition + 1).ToString(); + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css b/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css index 2e263c949..b373f4783 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Styles/admin.css @@ -1,4 +1,60 @@ -.widgetsbag-editor h5 { +.widgetsbag-editor h5 { color:#4c4c4c; font-weight:bold; +} + +.availableWidgets { + float: left; + width: 35%; +} + +.availableLayers { + float: left; + margin: 0 0 0 2em; + width: 45%; +} + +.layerZones { + float: left; + width: 75%; +} + +.layerZones .zone { + font-weight:700; + background:#f5f5f5; + border: 1px solid #f1f1f1; + padding: 1em 2em 1em 2em; + margin: 0 0 1em 0; +} + +.layerZones .zoneWidget { + margin: 0 0 1em 0; + padding: 1em 2em 1em 3em; + background:#ffffff; + border: 1px solid #f1f1f1; + vertical-align: middle; +} + +.layers { + margin: 1em 0 0 0; + float: left; +} + +.layers ul { + background: #f5f5f5; + border: 1px solid #f1f1f1; +} + +.layers .currentLayer { + background: #c3d9ff; +} + +.layers .editLayer img { + float: right; + margin: 0 0 0 1em; +} + +.layerZones ul li ul { + margin: 0; + padding: 0; } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/ViewModels/WidgetsIndexViewModel.cs b/src/Orchard.Web/Modules/Orchard.Widgets/ViewModels/WidgetsIndexViewModel.cs new file mode 100644 index 000000000..fb24ec294 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/ViewModels/WidgetsIndexViewModel.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Orchard.Widgets.Models; + +namespace Orchard.Widgets.ViewModels +{ + public class WidgetsIndexViewModel + { + /// + /// The available widget content types. + /// + public IEnumerable WidgetTypes { get; set; } + + /// + /// The available layers. + /// + public IEnumerable Layers { get; set; } + + /// + /// The available zones in the page. + /// + public IEnumerable Zones { get; set; } + + /// + /// The current layer. + /// + public LayerPart CurrentLayer { get; set; } + + /// + /// The current layer widgets. + /// + public IEnumerable CurrentLayerWidgets { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddLayer.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddLayer.cshtml new file mode 100644 index 000000000..8cadd5d83 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddLayer.cshtml @@ -0,0 +1,5 @@ +

@Html.TitleForPage(T("Add Layer").ToString())

+@using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() + @Display(Model) +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddWidget.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddWidget.cshtml new file mode 100644 index 000000000..0647070aa --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/AddWidget.cshtml @@ -0,0 +1,5 @@ +

@Html.TitleForPage(T("Add Widget").ToString())

+@using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() + @Display(Model) +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml new file mode 100644 index 000000000..87aa30d15 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditLayer.cshtml @@ -0,0 +1,9 @@ +

@Html.TitleForPage(T("Edit Layer").ToString())

+ @using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() + @Display(Model) + +
+ +
+} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml new file mode 100644 index 000000000..8d7f36a5c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/EditWidget.cshtml @@ -0,0 +1,9 @@ +

@Html.TitleForPage(T("Edit Widget").ToString())

+ @using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() + @Display(Model) + +
+ +
+} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/Index.cshtml index 312dbe70f..7678e0e42 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/Admin/Index.cshtml @@ -1,6 +1,92 @@ -

@Html.TitleForPage(T("Manage Layers").ToString())

-@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
@Html.ActionLink(T("Add a new layer").ToString(), "Create", new { }, new { @class = "button primaryAction" })
-

Layers ...

-} \ No newline at end of file +@model WidgetsIndexViewModel; +@using Orchard.Widgets.Models; +@using Orchard.Widgets.ViewModels; +@{ Style.Require("WidgetsAdmin"); } + +

@Html.TitleForPage(T("Manage Widgets").ToString())

+ +@using(Html.BeginFormAntiForgeryPost()) { + Html.ValidationSummary(); + +
@Html.ActionLink(T("Add a layer").ToString(), "AddLayer", new { }, new { @class = "button primaryAction" })
+ +
+ +
+

Available Widgets

+ +
+ + + + + + + + + + + + @foreach (string widget in Model.WidgetTypes) { + + + + + } +
@T("Name")
@widget@Html.ActionLink(T("Add").ToString(), "AddWidget", new { layerId = Model.CurrentLayer.Id, widgetType = widget })
+ +
+
+ +
+

Widget Layers

+ +
+
+
    + @foreach (string zone in Model.Zones) { +
  • +
    @zone
    +
      + @foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position)) { +
    • + @if (widget.Position != "1") { + + } + @if (int.Parse(widget.Position) < Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).Count()) { + + } + @Html.ActionLink(@widget.Title, "EditWidget", new { @widget.Id }) +
    • + } +
    +
  • + } +
+
+ +
+
    + @foreach (var layer in Model.Layers) { + if (layer.Id == Model.CurrentLayer.Id) { +
  • + @Html.ActionLink(@layer.Name, "Index", new { @layer.Id }) + + + +
  • + } else { +
  • + @Html.ActionLink(@layer.Name, "Index", new { @layer.Id }) + + + +
  • + } + } +
      +
+
+
+
+} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Layer.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Layer.cshtml new file mode 100644 index 000000000..be3256074 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Layer.cshtml @@ -0,0 +1,16 @@ +@model Orchard.Widgets.Models.LayerPart + +
+ @Html.LabelFor(layer => layer.Name) + @Html.TextBoxFor(layer => layer.Name) +
+ +
+ @Html.LabelFor(layer => layer.Description) + @Html.TextAreaFor(layer => layer.Description) +
+ +
+ @Html.LabelFor(layer => layer.LayerRule) + @Html.TextAreaFor(layer => layer.LayerRule) +
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Widget.cshtml b/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Widget.cshtml new file mode 100644 index 000000000..2e9125f3b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Views/EditorTemplates/Parts/Widgets.Widget.cshtml @@ -0,0 +1,11 @@ +@model Orchard.Widgets.Models.WidgetPart + +
+ @Html.LabelFor(widget => widget.Zone) + @Html.DropDownListFor(widget => widget.Zone, new SelectList(Model.AvailableZones)) +
+ +
+ @Html.LabelFor(widget => widget.Title) + @Html.TextBoxFor(widget => widget.Title) +
\ No newline at end of file