How to create an dynamic Menu in Serenity? - c#

I'm trying to make an dynamic menu for Dashboards,
I have an register of Dashboards, this will just have an Description and Link.
After register this, it has to appear in menu.
My new menu page will contain an frame to open this link inside the new page.
Has an easy way to alter the menu in serenity to has this behavior?

I have make this altering the NavigationModel.cs
After search alot, don't found any example doing that.
I have create a DynamicNavigation like this:
public class DynamicDashboards : INavigationItemSource
{
public List<NavigationItemAttribute> GetItems()
{
var items = new List<NavigationItemAttribute>
{
new NavigationMenuAttribute(1000, "Dashboards", "icon-speedometer")
};
using (var connection = SqlConnections.NewByKey("Default"))
{
var dashboards = connection.List<DashboardsRow>();
foreach (var dashboard in dashboards)
items.Add(new NavigationLinkAttribute(1000,
path: "Dashboards/" + dashboard.Descricao.Replace("/", "//"),
url: "~/Dashboards/DefaultDashboard?link=" + dashboard.Link,
permission: CadastrosPermissionKeys.General,
icon: "icon-speedometer"));
}
return items;
}
}
Them on NavigationModel.cs, i'm calling this class for insert it on Items
var dy = new DynamicDashboards();
var dashboardMenu = NavigationHelper.ConvertToNavigationItems(NavigationHelper.ByCategory(dy.GetItems()), x => x != null && x.StartsWith("~/") ? VirtualPathUtility.ToAbsolute(x) : x);
Items[0] = dashboardMenu[0]
In my case i have an default menu inside Dashboard, so i just adding this again on position [0], you can manipulate this like you want.

Related

How to load a specific dialog and it's resources without loading every dialog in the sample code?

Github link for the sample code I'm using
In the AdaptiveBot.cs file,
It creates a list of all the prompts available and takes user input and runs the specified prompt.
I want to modify it such that it loads only one dialog(There are 7 prompts in the sample folder and it gives a choice to load any one )
How would I go about to load only one dialog, for example just the MultiTurnPromptBot is needed to be loaded and the rest are not needed.
private void LoadDialogs()
{
System.Diagnostics.Trace.TraceInformation("Loading resources...");
//For this sample we enumerate all of the .main.dialog files and build a ChoiceInput as our rootidialog.
this.dialogManager = new DialogManager(CreateChoiceInputForAllMainDialogs());
this.dialogManager.UseResourceExplorer(this.resourceExplorer);
this.dialogManager.UseLanguageGeneration();
System.Diagnostics.Trace.TraceInformation("Done loading resources.");
}
private AdaptiveDialog CreateChoiceInputForAllMainDialogs()
{
var dialogChoices = new List<Choice>();
var dialogCases = new List<Case>();
foreach (var resource in this.resourceExplorer.GetResources(".dialog").Where(r => r.Id.EndsWith(".main.dialog")))
{
var name = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(resource.Id));
dialogChoices.Add(new Choice(name));
var subDialog = resourceExplorer.LoadType<AdaptiveDialog>(resource);
dialogCases.Add(new Case($"{name}", new List<Dialog>() { subDialog }));
}
var dialog = new AdaptiveDialog()
{
AutoEndDialog = false,
Triggers = new List<OnCondition>() {
new OnBeginDialog() {
Actions = new List<Dialog>() {
new ChoiceInput() {
Prompt = new ActivityTemplate("What declarative sample do you want to run?"),
Property = "conversation.dialogChoice",
AlwaysPrompt = true,
Style = ListStyle.List,
Choices = new ChoiceSet(dialogChoices)
},
new SendActivity("# Running ${conversation.dialogChoice}.main.dialog"),
new SwitchCondition(){
Condition = "conversation.dialogChoice",
Cases = dialogCases
},
new RepeatDialog()
}
}
}
};
return dialog;
}
You can see that LoadDialogs is instantiating a dialog manager by passing an adaptive dialog into its constructor. So instead of creating the root dialog that starts all the other dialogs, you can just pass in one of those dialogs as the root dialog since they're all adaptive dialogs anyway. You can see that the declarative dialog files are loaded like this:
this.resourceExplorer.GetResources(".dialog")
And then the adaptive dialog instances are created out of them like this:
var subDialog = resourceExplorer.LoadType<AdaptiveDialog>(resource);
So you can do something like this:
private void LoadDialogs()
{
System.Diagnostics.Trace.TraceInformation("Loading resources...");
//For this sample we enumerate all of the .main.dialog files and build a ChoiceInput as our rootidialog.
//this.dialogManager = new DialogManager(CreateChoiceInputForAllMainDialogs());
this.dialogManager = new DialogManager(this.resourceExplorer.LoadType<AdaptiveDialog>(this.resourceExplorer.GetResource("MultiTurnPrompt.main.dialog")));
this.dialogManager.UseResourceExplorer(this.resourceExplorer);
this.dialogManager.UseLanguageGeneration();
System.Diagnostics.Trace.TraceInformation("Done loading resources.");
}
TL;DR: Replace this line:
this.dialogManager = new DialogManager(CreateChoiceInputForAllMainDialogs());
With this line:
this.dialogManager = new DialogManager(this.resourceExplorer.LoadType<AdaptiveDialog>(this.resourceExplorer.GetResource("MultiTurnPrompt.main.dialog")));

Sitecore access layout definition programmatically

I want to access the layout definition of an item so that I can access the renderings added to the item, and then access the datasources attached to said renderings. I can't seem to find a way to do this. The best I could do is access the __renderings field but I then found out that this is going to access the original rendering definition item rather than the specific, datasourced instance stored in the Design Layout.
This is on Sitecore 7.5 MVC
If it helps, this is what I tried doing:
// Get the default device
DeviceRecords devices = item.Database.Resources.Devices;
DeviceItem defaultDevice = devices.GetAll().Where(d => d.Name.ToLower() == "default").First();
// Get the rendering references for the default device
Sitecore.Data.Fields.LayoutField layoutField = item.Fields["__renderings"];
Sitecore.Layouts.RenderingReference[] renderings = layoutField.GetReferences(defaultDevice);
// Get the required renderings
RenderingItem headerRenderingItem = null;
RenderingItem aboutRenderingItem = null;
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingItem = rendering.RenderingItem;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingItem = rendering.RenderingItem;
}
Assert.IsNotNull(headerRenderingItem, "no header rendering item found");
Assert.IsNotNull(aboutRenderingItem, "no about rendering item found");
// Get their datasources
ID headerDatasourceId = ID.Parse(headerRenderingItem.DataSource); // The datasource string is null as it is accessing the datasource definition item itself
ID aboutDatasourceId = ID.Parse(aboutRenderingItem.DataSource); // Same as above
The RenderingReference.RenderingItem refers to the rendering item in the /layout section. What you could do is use RenderingReference.Settings.Datasource.
So your code would look something like:
foreach (var rendering in renderings)
{
if (rendering.Placeholder == "headerPlaceholder")
headerRenderingDatasourceId = rendering.Settings.Datasource;
else if (rendering.Placeholder == "/aboutSectionPlaceholder/textPlaceholder")
aboutRenderingDatasourceId = rendering.Settings.Datasource;
}
Item headerRenderingDatasourceItem;
if (!string.IsNullOrEmpty(headerRenderingDatasourceId)
headerRenderingDatasourceItem = item.Database.GetItem(headerRenderingDatasourceId);

Sitecore Rendering, how to get rendering definition item?

We are using a hybrid razor engine to create components in Sitecore.
I need to get the rendering definition id, but i am not able to get it.
This is our baseComponent class that inherits from Sitecore.Web.UI.WebControl
protected override void DoRender(HtmlTextWriter output)
{
string razorpath = RazorPath;
Model = GetViewModel();
var itemId = ID; //renderingID || getitem() also not working
HttpContext.Current.Response.Write(itemId);
Guid itemGuid;
if (Guid.TryParse(itemId, out itemGuid))
{
var webControl = ContentStore.GetItem<WebControl>(itemId);
if (webControl != null && string.IsNullOrEmpty(webControl.View))
razorpath = webControl.View.Replace("/WebControls", "");
}
var renderedContent = TemplateExpander.ExpandTemplate(razorpath, Model);
output.Write(renderedContent);
}
Not entirely sure what you're after, but since you're inheriting from Sitecore.Web.UI.WebControl, it might be something like this you're after:
var p = Parent as Sublayout;
var rId = p.RenderingID;

Dynamic tree control

I am using control named 'tree' from http://www.jeasyui.com. But in my case I want to load at first highest level then when click to one of node load it's child nodes.
<ul id="tt" checkbox="true" animate="true"></ul>
$(function() {
$('#tt').tree({
data: #Html.Raw(Model.Tree)
});
});
on this function I get childs nodes for selected node from DB:
$(function() {
$('#tt').tree({
onBeforeExpand: function(node) {
var hospitalId = node.id;
$.getJSON('#Url.Action("LoadDepartments")', { hospitalId: hospitalId }, function () {
});
}});});
[HttpGet]
public ActionResult LoadDepartments(Guid hospitalId)
{
LoadHospitals();
var departments = _templateAccessor.GetDepartments(hospitalId);
var hospital = tree.Where(obj => obj.id == hospitalId.ToString()).FirstOrDefault();
if (hospital != null)
{
foreach (var department in departments)
{
DataTreeModel dep = new DataTreeModel();
dep.id = department.Id.ToString();
dep.text = department.Name;
dep.state = "closed";
hospital.children.Add(dep);
hospital.state = "open";
}
}
var result = SerializeToJsonString(tree);
return Json(result, JsonRequestBehavior.AllowGet);
}
In method LoadDepartments I have correct structure but the tree doesn't show new elements. the question is how to clean up previous content of tree and fill it with new content, maybe I am doing something wrong?
jqTree
This Tree should have the features you require, it's very lightweight and easy to use. I'm not advertising but I was in the same situation a couple of weeks ago, and this offered me a solution. It will also keep track of opened up nodes, etc...

Retrieve all items from a SharePoint Field Choice Column

I am playing around with a SharePoint server and I am trying to programmatically add a service request to microsoft's call center application template. So far, I have had pretty good success. I can add a call for a specified customer and assign a specific support tech:
private enum FieldNames
{
[EnumExtension.Value("Service Request")]
ServiceRequest,
[EnumExtension.Value("Customer")]
Customer,
[EnumExtension.Value("Service Representative")]
ServiceRepresentative,
[EnumExtension.Value("Assigned To")]
AssignedTo,
[EnumExtension.Value("Software")]
Software,
[EnumExtension.Value("Category")]
Category
}
private void CreateServiceCall(string serviceCallTitle, string customerName, string serviceRep)
{
SPSite allSites = new SPSite(siteURL);
SPWeb site = allSites.AllWebs[siteName];
SPListItemCollection requestsList = site.Lists[serviceRequests].Items;
SPListItem item = requestsList.Add();
SPFieldLookup customerLookup = item.Fields[FieldNames.Customer.Value()] as SPFieldLookup;
item[FieldNames.ServiceRequest.Value()] = serviceCallTitle;
if (customerLookup != null)
{
using (SPWeb lookupWeb = allSites.OpenWeb(customerLookup.LookupWebId))
{
SPList lookupList = lookupWeb.Lists.GetList(new Guid(customerLookup.LookupList), false);
foreach (SPListItem listItem in lookupList.Items)
{
if (listItem[customerLookup.LookupField].ToString() != customerName) continue;
item[FieldNames.Customer.Value()] = new SPFieldLookupValue(listItem.ID, customerName);
break;
}
}
}
SPUserCollection userCollection = site.SiteUsers;
if (userCollection != null)
{
foreach (SPUser user in userCollection)
{
if (user.Name != serviceRep) continue;
item[FieldNames.AssignedTo.Value()] = user;
break;
}
}
item.Update();
site.Close();
allSites.Close();
}
I added two custom columns (category, software) to the default list:
I populated both of these columns inside of SharePoint, now I want to retrieve that data so I can use it in the code snippet I posted to assign the proper category/software etc to the call. I have not been able to get the list in the code, I have tried using a item["Software"], site.Lists["Software"] and a couple of others, but so far all I have come up is null.
Can anyone point me in the right direction for this? Thanks!
SPFieldMultiChoice and related fields have a Choices property:
SPFieldMultiChoice software = item.Fields[FieldNames.Software.Value()] as SPFieldMultiChoice;
StringCollection softwareChoices = software.Choices;
If you need to set a value on the field, use the SPFieldMultiChoiceValue type:
SPFieldMultiChoiceValue values = new SPFieldMultiChoiceValue();
values.Add("Choice 1");
values.Add("Choice 2");
item[FieldNames.Software.Value()] = values;

Categories

Resources