SAP Commerce 1811
I have one custom type e.g. "CustomType" which has one media attribute of type MediaModel. My requirement is to upload CSV media using Drag & Drop Editor in Editor Area.
So i used OOTB com.hybris.cockpitng.editor.dndfileupload of type com.hybris.cockpitng.editor.defaultfileupload.FileUploadResult and apply on my media attribute.
<attribute type="com.hybris.cockpitng.editor.defaultfileupload.FileUploadResult" editor="com.hybris.cockpitng.editor.dndfileupload" qualifier="media">
<editor-parameter>
<name>accept</name>
<value>text/csv</value>
</editor-parameter>
</attribute>
Now i created one custom Backoffice action e.g. "UploadMedia" and configured in editorareaactions of "CustomType".
As in when i upload csv media and click on my action, In my Action Controller, I am trying to fetch uploaded FileUploadResult media but its always giving null value.
#Override
public ActionResult<Object> perform(final ActionContext<TargetGroupModel> ctx)
{
final WidgetModel model = (WidgetModel) ctx.getParameter(ActionContext.PARENT_WIDGET_MODEL);
if (model != null)
{
final FileUploadResult result = model.getValue("currentObject.media", FileUploadResult.class);
System.out.println(result.getData()); // result is always NULL
}
return new ActionResult<>(ActionResult.SUCCESS);
}
And the strange thing is, while on debug, if i inspect the WidgetModel, i can see for this key "currentObject.media", value is there.
Any help ?
I solved the issue by just typecast ctx.getParameter(ActionContext.PARENT_WIDGET_MODEL) with Map and get the value with currentObject.media Key.
Working Code
#Override
public ActionResult<Object> perform(final ActionContext<TargetGroupModel> ctx)
{
final Map map = (Map) ctx.getParameter(ActionContext.PARENT_WIDGET_MODEL);
if (map != null)
{
final FileUploadResult result = map.get("currentObject.media");
System.out.println(result.getData());
}
return new ActionResult<>(ActionResult.SUCCESS);
}
Related
I want to disable Orchard Content Part buttons (Save and Publish Now) in the EDITOR template (when Content Item is created) based on some conditions. Can I do that ? How do I access the buttons in the EDITOR view.
Here are come examples,
To build a content fully from a Controller example, taken from the Blog Module
public ActionResult Create() {
if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Not allowed to create blogs")))
return new HttpUnauthorizedResult();
BlogPart blog = Services.ContentManager.New<BlogPart>("Blog");
if (blog == null)
return HttpNotFound();
dynamic model = Services.ContentManager.BuildEditor(blog);
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)model);
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageBlogs, T("Couldn't create blog")))
return new HttpUnauthorizedResult();
var blog = Services.ContentManager.New<BlogPart>("Blog");
_contentManager.Create(blog, VersionOptions.Draft);
dynamic model = _contentManager.UpdateEditor(blog, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)model);
}
_contentManager.Publish(blog.ContentItem);
return Redirect(Url.BlogForAdmin(blog));
}
BuidEditor does the work for you.
And you should use a alternative version of this template, but remove the edit link and publish link.
Note, you need a route for you custom create action, and a menu link on the dashboard may come in handy.
I want to create alternates for content item based on its tag value.
For example, I want to create an alternate called List-ProjectionPage-tags-special
Searching the nets directs me to implement a new ShapeDisplayEvents
Thus, I have
public class TagAlternatesFactory : ShapeDisplayEvents
{
public TagAlternatesFactory()
{
}
public override void Displaying(ShapeDisplayingContext context)
{
}
}
In the Displaying method, I believe I need to check the contentItem off the context.Shape and create an alternate name based off of that (assuming it has the TagsPart added to the content item).
However, what do I do with it then? How do I add the name of the alternate? And is that all that's needed to create a new alternate type? Will orchard know to look for List-ProjectionPage-tags-special?
I took a cue from Bertrand's comment and looked at some Orchard source for direction.
Here's my implementation:
public class TagAlternatesFactory : ShapeDisplayEvents
{
public override void Displaying(ShapeDisplayingContext context)
{
context.ShapeMetadata.OnDisplaying(displayedContext =>
{
var contentItem = displayedContext.Shape.ContentItem;
var contentType = contentItem.ContentType;
var parts = contentItem.Parts as IEnumerable<ContentPart>;
if (parts == null) return;
var tagsPart = parts.FirstOrDefault(part => part is TagsPart) as TagsPart;
if (tagsPart == null) return;
foreach (var tag in tagsPart.CurrentTags)
{
displayedContext.ShapeMetadata.Alternates.Add(
String.Format("{0}__{1}__{2}__{3}",
displayedContext.ShapeMetadata.Type, (string)contentType, "tag", tag.TagName)); //See update
}
});
}
}
This allows an alternate view based on a tag value. So, if you have a project page that you want to apply a specific style to, you can simply create your alternate view with the name ProjectionPage_tag_special and anytime you want a projection page to use it, just add the special tag to it.
Update
I added the displayedContext.ShapeMetadata.Type to the alternate name so specific shapes could be overridden (like the List-ProjectionPage)
OK - I've created a custom navigation provider that inherits PortalSiteMapProvider and I'm trying to extend my class via the GetChildNodes method (Simple example here).
Essentially what I'm trying to do is add the current SPWeb's SiteLogoUrl string as an attribute (called imgurl) of each SPWeb's respective SiteMapNode, with a view to retrieve this value later in my custom Menu control (which inherits SharePoint:AspMenu).
I'm setting the attributes like so in my provider under GetChildNodes:
public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)
{
PortalSiteMapNode portalNode = (PortalSiteMapNode)node;
if (portalNode != null)
{
if (portalNode.Type == NodeTypes.Area)
{
SiteMapNodeCollection nodeColl = base.GetChildNodes(portalNode);
using (SPSite currentSite = new SPSite(portalNode.PortalProvider.CurrentSite.Url))
{
foreach (SiteMapNode topLevelNode in nodeColl)
{
foreach(SiteMapNode currentNode in topLevelNode.ChildNodes)
{
string currentWebUrl = currentNode.Url.Substring(0, currentNode.Url.ToLower().IndexOf("/pages/"));
using (SPWeb currentWeb = currentSite.OpenWeb(currentWebUrl))
{
if (!string.IsNullOrEmpty(currentWeb.SiteLogoUrl))
{
currentNode["imgurl"] = currentWeb.SiteLogoUrl;
}
}
}
}
}
return nodeColl;
}
Now I can debug this and retrieve the value once it has been inserted like so (x being the index of node, and me doing this in the Command Window):
? topLevelNode.ChildNodes[x]["imgurl"]
and that returns the url of the image fine : "/_layouts/images/myimage.jpg"
Now.. when I try to do this in my custom Menu control I first get a handle on my custom nav provider like so:
CustomNavProvider customProvider = (CustomNavProvider)SiteMap.Providers["CustomNavProvider"];
SiteMapNode currentNode = customProvider.FindSiteMapNode(childitem.NavigateUrl);
and the currentNode variable now contains my SiteMapNode...great, however instead of the attribute I added previously, there is now only a single attribute called 'AlternateUrl' - the imgurl attribute I added in the provider has now disappeared. All other properties like title, desc etc are there so it's definitely returning the correct node.
What's my issue here? Is the attribute not being persisted when I added it to the node in the provider?
Any help or suggestions appreciated.
I've written the following simple command inside my module. The Faq type has one custom part with a single field, and one BodyPart. After _cm.Create(item) is run, the item has an Id assigned but I can't find any trace of it in the database and it doesn't appear in Orchard's content tab. Why does the item get an Id but isn't found in the database? And does it need a driver, view, and placement info before it appears in the content tab?
public class ApiCommands : DefaultOrchardCommandHandler
{
private readonly IContentManager _cm;
public ApiCommands(IContentManager cm)
{
_cm = cm;
}
[CommandName("api seed")]
public void Seed()
{
var item = _cm.New("Faq");
item.As<FaqPart>().Question = "Why is the sky blue?";
item.As<BodyPart>().Text = "Shut up and do your homework.";
_cm.Create(item);
}
}
My custom part has no driver this is the Handler:
public FaqHandler(IRepository<FaqPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
It turns out my type didn't attach a CommonPart. After I attached one and set the Owner property of the part, I was able to save it.
I've got the following problem:
I created a WebPart with a ToolPart,
this toolpart has multiple controls (textbox, dropdownlist, ...)
when I fill in everything and apply, it all goes ok,
even when i press ok. But when i go back to
edit -> modify webpart, all my data i've entered is gone.
How can i solve this?
Thanks
You'll need to save the values from the Toolpart in the webpart's properties. For example, lets say I want to save a string for "Title"... in the webpart define a property:
private const string DEFAULT_WPPColumnTitle = "Title";
private string _WPPColumnTitle = DEFAULT_WPPColumnTitle;
[Browsable(false)]
[WebPartStorage(Storage.Shared)]
public string WPPColumnTitle
{
get { return this._WPPColumnTitle; }
set { this._WPPColumnTitle = value; }
}
I always use the prefix "WPP" to keep all the web part properties together.
Then, in the Toolpart's ApplyChanges override, save the control's value (_ddlColumnsTitle) to the webpart (WPPColumnTitle):
/// <summary>
/// Called by the tool pane to apply property changes to
/// the selected Web Part.
/// </summary>
public override void ApplyChanges()
{
// get our webpart and set it's properties
MyCustomWebPart et = (MyCustomWebPart)ParentToolPane.SelectedWebPart;
et.WPPColumnTitle = _ddlColumnsTitle.SelectedValue;
}
Lastly, if the user edited the properties already, we want the Toolpart to be pre-populated with the user's configuration. In the CreateChildControls() method of your Toolpart, initialize the controls:
protected override void CreateChildControls()
{
try
{
MyCustomWebPart et = (MyCustomWebPart)ParentToolPane.SelectedWebPart;
// ... code to create _ddlColumnsTitle and add it to the Controls
// default our dropdown to the user's selection
ListItem currentItem = _ddlColumnsTitle.Items.FindByValue(et.WPPColumnTitle);
if (null != currentItem)
{
_ddlColumnsTitle.SelectedValue = currentItem.Value;
}
}
catch (Exception ex)
{
_errorMessage = "Error adding edit controls. " + ex.ToString();
}
}
Open up the debugger and double check that the values are getting applied to your propertries on Apply (i.e. WPPColumnTitle is set).
If so then problem is that SharePoint is not serializing/deserializing the value from the property (WPPColumnTitle) to the database and back - verify by writing out this property on the web part - as soon as you leave the page and come back it will be empty.
If so then check things like this on class
[XmlRoot(Namespace = "YourNamespace")]
and this (not strictly necessary) on properties
[XmlElement(ElementName = "ColumnTitle")]
I've also seen problems if you name your web part class "WebPart" so call it MyWebPart
I've solved it with adding a property in my webpart "IsNeverSet" (bool)
and when i go to the "CreateControls()" of my toolpart, I get this property
and if it's false, I load all the properties from my webpart and fill them in the toolpart.
So I found it with the help of Kit Menke