--HG--
branch : dev
This commit is contained in:
Andre Rodrigues
2010-10-11 11:28:04 -07:00
26 changed files with 1096 additions and 28 deletions

View File

@@ -132,6 +132,7 @@
<Compile Include="Values.cs" />
<Compile Include="Users\Controllers\AdminControllerTests.cs" />
<Compile Include="Users\Services\MembershipServiceTests.cs" />
<Compile Include="Widgets\Services\WidgetsServiceTest.cs" />
<Compile Include="Widgets\WidgetsTests.cs" />
<Compile Include="XmlRpc\Controllers\HomeControllerTests.cs" />
<Compile Include="XmlRpc\Services\XmlRpcReaderTests.cs" />

View File

@@ -0,0 +1,225 @@
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<Type> 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<IWidgetsService>();
_contentManager = _container.Resolve<IContentManager>();
}
public override void Register(ContainerBuilder builder) {
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
builder.RegisterInstance(new Mock<ITransactionManager>().Object);
builder.RegisterInstance(new Mock<IAuthorizer>().Object);
builder.RegisterInstance(new Mock<INotifier>().Object);
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
builder.RegisterType<ShapeHelperFactory>().As<IShapeHelperFactory>();
builder.RegisterType<WidgetsService>().As<IWidgetsService>();
Theme theme1 = new Theme { Zones = ThemeZoneName1 };
Theme theme2 = new Theme { Zones = ThemeZoneName2 };
Mock<IThemeService> themeServiceMock = new Mock<IThemeService>();
themeServiceMock.Setup(x => x.GetInstalledThemes()).Returns(
(new ITheme[] { theme1, theme2 }));
builder.RegisterInstance(themeServiceMock.Object).As<IThemeService>();
builder.RegisterType<StubWidgetPartHandler>().As<IContentHandler>();
builder.RegisterType<StubLayerPartHandler>().As<IContentHandler>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>();
}
[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<LayerPart> 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<LayerPart> 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<LayerPart> 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<WidgetPart> 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<string> 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<LayerPartRecord> layersRepository) {
Filters.Add(new ActivatingFilter<LayerPart>("Layer"));
Filters.Add(new ActivatingFilter<CommonPart>("Layer"));
Filters.Add(StorageFilter.For(layersRepository));
}
}
public class StubWidgetPartHandler : ContentHandler {
public StubWidgetPartHandler(IRepository<WidgetPartRecord> widgetsRepository) {
Filters.Add(new ActivatingFilter<WidgetPart>("HtmlWidget"));
Filters.Add(new ActivatingFilter<CommonPart>("HtmlWidget"));
Filters.Add(new ActivatingFilter<BodyPart>("HtmlWidget"));
Filters.Add(StorageFilter.For(widgetsRepository));
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

View File

@@ -1,21 +1,315 @@
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<LayerPart> layers = _widgetsService.GetLayers();
LayerPart currentLayer;
IEnumerable<WidgetPart> 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<WidgetPart>();
}
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<WidgetPart>(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<LayerPart>("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>(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());
}
}
}
}

View File

@@ -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<LayerPart> {
protected override DriverResult Editor(LayerPart layerPart, dynamic shapeHelper) {
ContentLocation location = layerPart.GetLocation("Editor");
return ContentPartTemplate(layerPart, "Parts/Widgets.LayerPart").Location(location);
}
protected override DriverResult Editor(LayerPart layerPart, IUpdateModel updater, dynamic shapeHelper) {
updater.TryUpdateModel(layerPart, Prefix, null, null);
return Editor(layerPart, shapeHelper);
}
}
}

View File

@@ -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<WidgetPart> {
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.WidgetPart").Location(location);
}
protected override DriverResult Editor(WidgetPart widgetPart, IUpdateModel updater, dynamic shapeHelper) {
updater.TryUpdateModel(widgetPart, Prefix, null, null);
return Editor(widgetPart, shapeHelper);
}
}
}

View File

@@ -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;

View File

@@ -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<string, ContentLocation> {
{"Editor", new ContentLocation { Zone = "primary", Position = "1" }}
})
);
ContentDefinitionManager.AlterPartDefinition(typeof(WidgetPart).Name,
cfg => cfg
.WithLocation(new Dictionary<string, ContentLocation> {
{"Editor", new ContentLocation { Zone = "primary", Position = "1" }}
})
);
ContentDefinitionManager.AlterPartDefinition(typeof(WidgetBagPart).Name,
cfg => cfg
.WithLocation(new Dictionary<string, ContentLocation> {
{"Editor", new ContentLocation {Zone = "primary", Position = "5"}}

View File

@@ -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<LayerPartRecord> {
/// <summary>
/// The layer's identifier.
/// </summary>
[HiddenInput(DisplayValue = false)]
public int Id {
get { return ContentItem.Id; }
}
/// <summary>
/// The layer's name.
/// </summary>
[Required]
public string Name {
get { return Record.Name; }
set { Record.Name = value; }
}
/// <summary>
/// The layer's description.
/// </summary>
public string Description {
get { return Record.Description; }
set { Record.Description = value; }
}
/// <summary>
/// The layer's rule.
/// The rule defines when the layer is active (should or not be displayed).
/// </summary>
public string LayerRule {
get { return Record.LayerRule; }
set { Record.LayerRule = value; }
}
}
}

View File

@@ -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<WidgetPartRecord> {
/// <summary>
/// The widget's identifier.
/// </summary>
[HiddenInput(DisplayValue = false)]
public int Id {
get { return ContentItem.Id; }
}
/// <summary>
/// The widget's title.
/// </summary>
[Required]
public string Title {
get { return Record.Title; }
set { Record.Title = value; }
}
/// <summary>
/// The zone where the widget is to be displayed.
/// </summary>
[Required]
public string Zone {
get { return Record.Zone; }
set { Record.Zone = value; }
}
/// <summary>
/// The widget's position within the zone.
/// </summary>
[HiddenInput(DisplayValue = false)]
public string Position
{
get { return Record.Position; }
set { Record.Position = value; }
}
/// <summary>
/// The layerPart where the widget belongs.
/// </summary>
public LayerPart LayerPart {
get { return this.As<ICommonPart>().Container.As<LayerPart>(); }
set { this.As<ICommonPart>().Container = value; }
}
/// <summary>
/// The available page zones.
/// </summary>
[HiddenInput(DisplayValue = false)]
public IEnumerable<string> AvailableZones { get; set; }
}
}
}

View File

@@ -33,8 +33,13 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClaySharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\claysharp\ClaySharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
@@ -59,15 +64,15 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Drivers\WidgetBagPartDriver.cs" />
<Compile Include="Drivers\LayerPartDriver.cs" />
<Compile Include="Drivers\WidgetBagPartDriver.cs" />
<Compile Include="Drivers\WidgetPartDriver.cs" />
<Compile Include="Migrations.cs" />
<Compile Include="Handlers\LayerPartHandler.cs" />
<Compile Include="Handlers\WidgetPartHandler.cs" />
<Compile Include="Models\WidgetBagPart.cs" />
<Compile Include="Models\LayerPart.cs" />
<Compile Include="Models\LayerPartRecord.cs" />
<Compile Include="Models\WidgetBagPart.cs" />
<Compile Include="Models\WidgetPart.cs" />
<Compile Include="Models\WidgetPartRecord.cs" />
<Compile Include="Permissions.cs" />
@@ -77,8 +82,14 @@
<Compile Include="RuleEngine\AuthenticatedRuleProvider.cs" />
<Compile Include="RuleEngine\RuleManager.cs" />
<Compile Include="RuleEngine\UrlRuleProvider.cs" />
<Compile Include="Services\IWidgetsService.cs" />
<Compile Include="Services\WidgetsService.cs" />
<Compile Include="ViewModels\WidgetsIndexViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Admin\images\edit.gif" />
<Content Include="Content\Admin\images\moveup.gif" />
<Content Include="Content\Admin\images\movedown.gif" />
<Content Include="Module.txt" />
<Content Include="Styles\admin.css" />
<Content Include="Web.config" />
@@ -96,7 +107,13 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Views\Admin\AddLayer.cshtml" />
<None Include="Views\Admin\AddWidget.cshtml" />
<None Include="Views\Admin\EditWidget.cshtml" />
<None Include="Views\Admin\EditLayer.cshtml" />
<None Include="Views\Admin\Index.cshtml" />
<None Include="Views\EditorTemplates\Parts\Widgets.WidgetPart.cshtml" />
<None Include="Views\EditorTemplates\Parts\Widgets.LayerPart.cshtml" />
<None Include="Views\EditorTemplates\Parts\Widgets.WidgetBagPart.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

View File

@@ -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");
}
}
}

View File

@@ -35,7 +35,7 @@ namespace Orchard.Widgets.RuleEngine {
public class CallbackApi {
private readonly RuleManager _ruleManager;
public CallbackApi(RuleManager ruleManager) {
_ruleManager = ruleManager;
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using Orchard.Widgets.Models;
namespace Orchard.Widgets.Services {
public interface IWidgetsService : IDependency {
IEnumerable<string> GetZones();
IEnumerable<LayerPart> GetLayers();
IEnumerable<string> GetWidgetTypes();
IEnumerable<WidgetPart> GetWidgets();
IEnumerable<WidgetPart> 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);
}
}

View File

@@ -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<string> GetWidgetTypes() {
return _contentManager.GetContentTypeDefinitions()
.Where(contentTypeDefinition => contentTypeDefinition.Settings.ContainsKey("stereotype") && contentTypeDefinition.Settings["stereotype"] == "widget")
.Select(contentTypeDefinition => contentTypeDefinition.Name);
}
public IEnumerable<LayerPart> GetLayers() {
return _contentManager
.Query<LayerPart, LayerPartRecord>()
.List();
}
public IEnumerable<WidgetPart> GetWidgets() {
return _contentManager
.Query<WidgetPart, WidgetPartRecord>()
.List();
}
public IEnumerable<string> GetZones() {
HashSet<string> zones = new HashSet<string>();
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<WidgetPart> GetWidgets(int layerId) {
return GetWidgets().Where(widgetPart => widgetPart.As<ICommonPart>().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<LayerPart>("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<WidgetPart>(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();
}
}
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,33 @@
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; }
}
}

View File

@@ -0,0 +1,5 @@
<h1>@Html.TitleForPage(T("Add Layer").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model)
}

View File

@@ -0,0 +1,5 @@
<h1>@Html.TitleForPage(T("Add Widget").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model)
}

View File

@@ -0,0 +1,9 @@
<h1>@Html.TitleForPage(T("Edit Layer").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model)
<fieldset>
<input type="submit" name="submit.Delete" class="button" value="@T("Delete")" />
</fieldset>
}

View File

@@ -0,0 +1,9 @@
<h1>@Html.TitleForPage(T("Edit Widget").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model)
<fieldset>
<input type="submit" name="submit.Delete" class="button" value="@T("Delete")" />
</fieldset>
}

View File

@@ -1,6 +1,92 @@
<h1>@Html.TitleForPage(T("Manage Layers").ToString()) </h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
<div class="manage">@Html.ActionLink(T("Add a new layer").ToString(), "Create", new { }, new { @class = "button primaryAction" })</div>
<p>Layers ...</p>
}
@model WidgetsIndexViewModel;
@using Orchard.Widgets.Models;
@using Orchard.Widgets.ViewModels;
@{ Style.Require("WidgetsAdmin"); }
<h1>@Html.TitleForPage(T("Manage Widgets").ToString())</h1>
@using(Html.BeginFormAntiForgeryPost()) {
Html.ValidationSummary();
<div class="manage">@Html.ActionLink(T("Add a layer").ToString(), "AddLayer", new { }, new { @class = "button primaryAction" })</div>
<div id="widgets" class="widgets">
<div class="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").ToString(), "AddWidget", new { layerId = Model.CurrentLayer.Id, widgetType = widget })</td>
</tr>
}
</table>
</fieldset>
</div>
<div class="availableLayers">
<h2>Widget Layers</h2>
<fieldset>
<div class="layerZonesWidgets">
<ul class="layerZones">
@foreach (string zone in Model.Zones) {
<li>
<div class="zone">@zone</div>
<ul>
@foreach (WidgetPart widget in Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).OrderBy(widgetPart => widgetPart.Position)) {
<li class="zoneWidget">
@if (widget.Position != "1") {
<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" />
}
@if (int.Parse(widget.Position) < Model.CurrentLayerWidgets.Where(widgetPart => widgetPart.Zone == zone).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" />
}
@Html.ActionLink(@widget.Title, "EditWidget", new { @widget.Id })
</li>
}
</ul>
</li>
}
</ul>
</div>
<div class="layers">
<ul>
@foreach (var layer in Model.Layers) {
if (layer.Id == Model.CurrentLayer.Id) {
<li class="currentLayer editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
} else {
<li class="editLayer">
@Html.ActionLink(@layer.Name, "Index", new { @layer.Id })
<a href="@Url.Action("EditLayer", new { @layer.Id })">
<img width="15" height="15" src="@Url.Content("~/modules/orchard.widgets/Content/Admin/images/edit.gif")" />
</a>
</li>
}
}
<ul>
</div>
</fieldset>
</div>
</div>
}

View File

@@ -0,0 +1,16 @@
@model Orchard.Widgets.Models.LayerPart
<fieldset>
@Html.LabelFor(layer => layer.Name)
@Html.TextBoxFor(layer => layer.Name)
</fieldset>
<fieldset>
@Html.LabelFor(layer => layer.Description)
@Html.TextAreaFor(layer => layer.Description)
</fieldset>
<fieldset>
@Html.LabelFor(layer => layer.LayerRule)
@Html.TextAreaFor(layer => layer.LayerRule)
</fieldset>

View File

@@ -0,0 +1,11 @@
@model Orchard.Widgets.Models.WidgetPart
<fieldset>
@Html.LabelFor(widget => widget.Zone)
@Html.DropDownListFor(widget => widget.Zone, new SelectList(Model.AvailableZones))
</fieldset>
<fieldset>
@Html.LabelFor(widget => widget.Title)
@Html.TextBoxFor(widget => widget.Title)
</fieldset>