Module not showing Admin Template

Topics: Administration, Troubleshooting, Writing modules
Jul 24, 2012 at 5:22 PM

I am looking to create a module called Orchard.Tools that appears on the admin menu.  I have managed to get the module appearing in the menu and the link takes me to a page '/Admin/Site Tools'.  

However in the same module I have a content part called SiteAlertWidget and I want this to be a child of Tools in the menu.  Site Alert Widget currently appears in the menu (when enabled) as a child of Settings at url '/Admin/Settings/

Is there a way for me to redirect the Site Alert Widget code to go to '/Admin/Settings/Site Tools' or the admin menu link to connect to /Admin/Site Tools'   

AdminMenu.cs

 

using Orchard.Localization;
using Orchard.UI.Navigation;

namespace Orchard.Tools
{
    public class AdminMenu : INavigationProvider
    {
        public string MenuName
        {
            get { return "admin"; }
        }

        public AdminMenu()
        {
            T = NullLocalizer.Instance;
        }

        private Localizer T { get; set; }

        public void GetNavigation(NavigationBuilder builder)
        {
            builder

                // Image set
                .AddImageSet("sitetools")

                // "BSite Tools"
                .Add(item => item

                    .Caption(T("Site Tools"))
                    .Position("2")
                    .LinkToFirstChild(true)

                    // "Site Alert"
                    .Add(subItem => subItem
                        .Caption(T("Site Alert"))
                        .Position("2.1")
                        .Action("Index","Admin", new {area = "Orchard.Tools"})
                    )

                    // "Site Search"
                    .Add(subItem => subItem
                        .Caption(T("Site Settings"))
                        .Position("2.2")
                        .Action("Index", "Admin", new { area = "Orchard.Tools" })
                    )
                );
        }
    }
}

 

Route.cs

using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;


namespace Orchard.Tools
{
    public class Routes : IRouteProvider
    {
        public void GetRoutes(ICollection<RouteDescriptor> routes)
        {
            foreach (var routeDescriptor in GetRoutes())
                routes.Add(routeDescriptor);
        }

        public IEnumerable<RouteDescriptor> GetRoutes()
        {
            return new[] 
            {
                new RouteDescriptor 
                {
                    Priority = 5,
                    Route = new Route(
                        "Orchard.Tools",
                        new RouteValueDictionary {
                            {"area", "Orchard.Tools"},
                            {"controller", "SiteAlert"},
                            {"action", "SiteAlertWidget"}
                        },
                        new RouteValueDictionary(),
                        new RouteValueDictionary {
                            {"area", "Orchard.Tools"}
                        },
                        new MvcRouteHandler())
                }
            };
        }
    }
}

I've tried playing about with the AdminMenu, route, Site Alert Widget code etc but not sure what I'm doing wrong.  There is no error message so compiling ok, but there is a good chance I'm doing it all wrong so any advice/guidance would be appreciated thanks

 

 

Coordinator
Jul 24, 2012 at 5:35 PM

I'm sorry but nothing in here makes sense to me. I'll pick one at random: why do you have two menu items pointing to exactly the same action?

Jul 24, 2012 at 7:36 PM

Bad code I is the main reason.  Site Settings is something that I intend to do eventually but is only in at present as the Site Alert didnt show as a child unless I had 2 child elements. I had intended to look into that and commment Site Search out for now but forgot. 

Coordinator
Jul 26, 2012 at 2:08 PM

OK, so that's one thing, but the original post is still quite hard to follow. Can you please simplify and explain what you are trying to do, how you are trying to do it and how it doesn't work?

Jul 26, 2012 at 4:19 PM
Edited Jul 26, 2012 at 4:27 PM

thanks for the response,  I don't think I explained it very well, but I have made progress anyway as I thought I could achieve my goal without a controller which was a stupid believe.  Currently: 

  • My module is a new content part called SiteAlert that  takes in a text input and will display the alert message on all instances of the content part,  
  • Currently I can edit the message via settings section of admin menu but I want to be able to do this via a new menu link.

The menu is now appearing ok and is linking to url '/Tools/AlertAdmin' as I intended and is showing the SiteAlert code from my index.cshtml.  My current problem is that its showing only the html code from index.cshtml, none of the admin template or styles so its just a blank page with a label and a Text box but no submit button.

I've checked my code and trailled the forum and have tried some suggestions but my OnGroups match, the placement seems ok and I cant see any other glaring but I am likely overlooking something.

I'm hoping I've just missed something small and any advice will again be appreciated.  I've included the pages I think may be affecting the issue below 

SiteAlertWidgetRecordHandler.cs

namespace Orchard.Tools.Handlers
{
    [OrchardFeature("SiteAlertWidget")]
    public class SiteAlertWidgetRecordHandler : ContentHandler
    {
        public SiteAlertWidgetRecordHandler(IRepository<SiteAlertWidgetRecord> repository)
        {
            T = NullLocalizer.Instance;
            Filters.Add(StorageFilter.For(repository));
            Filters.Add(new ActivatingFilter<SiteAlertWidgetPart>("Site"));
        }

        public Localizer T { get; set; }

        protected override void GetItemMetadata(GetContentItemMetadataContext context) {
            if (context.ContentItem.ContentType != "Site")
                return;
             base.GetItemMetadata(context);
            context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Tools"))); // <== linked to Driver OnGroup
        }
    }
}

AlertAdminController.cs
namespace Orchard.Tools.Controllers
{

    public class AlertAdminController : Controller
    {
        public ActionResult Index()
        {
            // Create the viewmodel
           SiteAlertWidgetViewModel model = new SiteAlertWidgetViewModel();

           return View(model);
        }
    }

}

 

SiteAlertWidgetDrivers.cs

 

namespace Orchard.Tools.Drivers
{
    [OrchardFeature("SiteAlertWidget")]
    public class SiteAlertWidgetDriver : ContentPartDriver<Models.SiteAlertWidgetPart>
    {
        private readonly ISignals signals;
        private readonly ISiteAlertService alertService;

        public SiteAlertWidgetDriver(ISiteAlertService service, ISignals sig)
        {
            signals = sig;
            alertService = service;
        }

        protected override DriverResult Display(Models.SiteAlertWidgetPart part, string displayType, dynamic shapeHelper)
        {
            return ContentShape("Parts_SiteAlertWidget", () => shapeHelper.Parts_SiteAlertWidget(
                    SiteAlert: alertService.GetSiteAlert()
                ));
        }


        protected override DriverResult Editor(Models.SiteAlertWidgetPart part, dynamic shapeHelper)
        {
            return ContentShape("Parts_SiteAlertWidget_Edit",
                               () => shapeHelper.EditorTemplate(
                                   TemplateName: "Parts/SiteAlertWidget",
                                   Model: new SiteAlertWidgetViewModel
                                   {
                                       SiteAlert = part.SiteAlert
                                   },                                             
                                   Prefix: Prefix)).OnGroup("Tools"); // <==  // linked to the controller  
        }

        // displays the update message for when alert content changed
        protected override DriverResult Editor(Models.SiteAlertWidgetPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            updater.TryUpdateModel(part, Prefix, null, null);
            signals.Trigger("Orchard.Tools.SiteAlert.Changed");
            return Editor(part, shapeHelper);
        }
    }
}

 

index.cshtml
@model BG.SiteAlert.ViewModels.SiteAlertWidgetViewModel

<fieldset>
    <legend>Site Alert</legend>
    <!-- Site wide Alert -->
    <div>
        <label for="SiteAlert">@T("Site wide alert")</label>
        @Html.TextBoxFor(m=>m.SiteAlert, new { @class = "text-box single-line", style="width:500px" })
    </div>

    <hr />

</fieldset>
placement.info
<Placement>
	<Place Parts_SiteAlertWidget="Content:1" />
	<Place Parts_SiteAlertWidget_Edit="Content:1" />
</Placement>

Coordinator
Jul 26, 2012 at 4:44 PM

Ah, yes, I see, this is much clearer, thanks. I think all you need to do is decorate your controller class with the [Admin] attribute.

Jul 27, 2012 at 11:59 AM

Sorted, it seems so obvious now that you stated it.  Thanks