Custom IContent type with asset pane; wont show "For this X"

Vote:
 

I have created my own, custom IContent, like so:

public class Review : ILocalizable, IContent, IVersionable {...}

Which I would like to be able to assign to my products. (Or articles, for that matter).

I have created a Component for it, like this:

[Component]
    public class ReviewPaneNavigationComponent : ComponentDefinitionBase
    {
        public ReviewPaneNavigationComponent()
            : base("epi-cms.component.SharedBlocks")
        {
            PlugInAreas = new[] { "/episerver/cms/assets/defaultgroup", "/episerver/commerce/assets/defaultgroup" };
            Categories = new[] { "commerce", "cms" };
            LanguagePath = "/components/review/";
            SortOrder = 11090;
            Settings.Add(new Setting("repositoryKey", ReviewPaneDescriptor.RepositoryKey));
        }
    }

...and also its descriptor:

[ServiceConfiguration(typeof(IContentRepositoryDescriptor))]
    public class ReviewPaneDescriptor : ContentRepositoryDescriptorBase
    {
        public static string RepositoryKey { get { return "reviews"; } }
        public override string Key { get { return RepositoryKey; } }
        public override string Name { get { return "Product reviews"; } }

        public override IEnumerable ContainedTypes 
        {
            get { return new List { typeof(Review), typeof(ContentFolder) }; }
        }

        public override IEnumerable CreatableTypes
        {
            get { return new List { typeof(Review) }; }
        }
        public override IEnumerable Roots
        {
            get
            {
                // WHAT TO PUT HERE?
            }
        }
    }

No matter what I try to do in Roots, I can't get the asset folder ("For this product") out. I guess I need to find "Current page" somehow, even if inside Edit mode. And EPiServer should know this internally, since it can do this very thing for Blocks and Media out of the box.

I have created an asset folder, which shows up under Media and Blocks (as "For this {0}", for some reason, but that's another story). If I hit "New block" in that folder, the block is created, but when I refresh the page it does not show up in the asset folder for that product. In the database, it's ContentPath is Root-SysContentAssets-.

My Product class does implement IResourceable, and have been sent through GetOrCreateAssetFolder on ContentAssetHelper.

Is it even possible to do what I want to achieve (a simple edit interface for my custom IContent with a separate asset pane) for products?

#91113
Sep 26, 2014 11:31
Vote:
 

I have done something similar, but with a custom dojo component. I did not use the "for this x" though. However, I think you need to specify the main navigaiton type(s). Try this:

        public override IEnumerable Roots
        {
            get { yield return SiteDefinition.Current.GlobalAssetsRoot; }
        }

        public override IEnumerable MainNavigationTypes
        {
            get { return typeof(ContentFolder).Yield().ToArray(); }
        }



#91114
Edited, Sep 26, 2014 12:17
Vote:
 

Realized that I should also post the code for Yield:

        public static IEnumerable Yield(this T item)
        {
            yield return item;
        }
#91115
Sep 26, 2014 12:18
Vote:
 

Added those, and now I do get the global assets root (obviously), along with "For this {0}" in the Reviews-pane, but there seems to be no way to add stuff to that folder in the GUI.

...and now I realised that every time i call GetOrCreateAssetFolder(product.ContentLink), it creates a new folder every time which might explain things. Researching a bit here...

Edit: GetOrCreateAssetFolder for a normal PageData works as intended. When passing in the content link of a commerce product (inheriting from ProductContent and implementing IResourceable), it gives me a new folder every time. If I ask for GetAssetFolder(contentLink) instead, it returns null. Bug?

Since neither Media nor Blocks can be put into "For this product" for products, it kindof seems to me that IResourceable is not working at all when implementing it on a ProductContent type.

#91122
Edited, Sep 26, 2014 12:57
Vote:
 

Have not tested this, but you may need to flag the content as modified when implementing IResourceable.  If not, it may not have been saved.

        private Guid _contentResourceId;
        private bool _isModified;
        protected override bool IsModified
        {
            get
            {
                return base.IsModified || _isModified;
            }
        }

        public Guid ContentAssetsID
        {
            get
            {
                return this._contentResourceId;
            }
            set
            {
                this.ThrowIfReadOnly();
                this._isModified = true;
                this._contentResourceId = value;
            }
        }

That could explain why you are getting a new folder every time.

#91124
Sep 26, 2014 13:41
Vote:
 

First of all: Cool stuff!

I can mention that we are working on some code samples that shows custom content in separate tabs for quite some time and it's getting real close to publishing these on Git. The samples we have are more focused to showing content providers fetching read only data, but they have a lot of similarities with the stuff that you are doing.

For the issues with IResoursable and Commerce Content: The Commerce content provider does not currently handle the IResourceable interface out of the box. We do not know what this might mean with potential pitfalls, but I would try creating a backing property for your commerce content type, that stores the catalog ID and map this with the ContentFolderID implementation of IResouceable.

#91125
Sep 26, 2014 13:51
Vote:
 

Allright, this worked for creating and storing stuff in a content asset folder on products:

        public virtual string ContentAssetIdInternal { get; set; }

        public Guid ContentAssetsID
        {
            get
            {
                Guid assetId;
                if (Guid.TryParse(ContentAssetIdInternal, out assetId))
                    return assetId;
                return Guid.Empty;
            }
            set
            {
                ContentAssetIdInternal = value.ToString();
                this.ThrowIfReadOnly();
                IsModified = true;
            }
        }

But there's still nothing in my "For this {0}" folder in my nice little review pane. You have any ideas for that? (as seen in the first post, I'm currently using epi-cms.component.SharedBlocks as its component type, I'm guessing that's somehow wrong for my Review that is not a block, but implements IContent directly. I have tried with a few others too, but none of them lists what I want...).

Under Blocks and Media, however, I can now use local blocks as on normal CMS content pages.

#91129
Edited, Sep 26, 2014 14:15
Vote:
 

Not sure if it fixes your issue, but I suggest that you use the generic base widget "epi-cms/widget/HierarchicalList" instead of the shared blocks widget.

#91131
Sep 26, 2014 15:05
Vote:
 

That made the "For this {0}" folder disappear, tried with both epi-cms.widget.HierarchialList and epi-cms/widget/HierarchialList.

Is there a list of existing components that are available somewhere?

#91132
Sep 26, 2014 15:16
Vote:
 

Change this:

     public override IEnumerable ContainedTypes 
        {
            get { return new List { typeof(Review), typeof(ContentFolder) }; }
        }

to this:

        public override IEnumerable ContainedTypes
        {
            get { return new[] { typeof(Review), typeof(ContentFolder) }; }
        }

and I think you'll see the content in the content asset folder

#91133
Sep 26, 2014 15:19
Vote:
 

You are absolutely right! Epic stuff! Thanks!

Weird thing though - is there a specific reason why it requires an Array instead of a List, when the method returns IEnumerable? Seems a bit weird.

Then im 98% there. All that remains now, is the fact that the folder in the nav pane is called "For this {0}" instead of "For this Product" or whatever. Any idea there?

#91135
Sep 26, 2014 15:27
Vote:
 

Sounds like a bug. It should use the client translation API:s with hierarchical support. Need to investigate this some more and potentially report a bug for it.

#91137
Sep 26, 2014 15:30
Vote:
 

Allright. I can live with that for now anyways, it's just cosmetics. 

#91139
Sep 26, 2014 15:38
Vote:
 

Aaand here's the result of my fiddling about.

http://www.epinova.no/blog/arve-systad/dates/2014/9/custom-icontent-with-its-own-navigation-pane/

http://www.epinova.no/blog/arve-systad/dates/2014/9/implementing-iresourceable-on-commerce-entities/

#91163
Sep 28, 2014 14:38
Vote:
 

Nice job! Thanks for sharing

#91193
Sep 29, 2014 13:43
Vote:
 

Hi,

Just implemented this and it works close to perfect! 

my class alsp implements  ILocalizable and IVersionable. IVersionable is needed if you want to use SaveActions (if not implemented your content get published automatically). I only use my reviews on my commerce products.

however i do get some small errors in the episerver GUI:

  • The created date seems to be set to DateTime.Min
  • "For this page" folder only shows on first time page load. if you navigate to a different product in the GUI this folder is missing. i have to do a full refresh of the page to get the folder back.

any ideas why this happens?

#91197
Sep 29, 2014 15:11
Vote:
 

PS: I also have problems saving changes from GUI. Everytime i save a change it is reverted to original values.

#91205
Sep 29, 2014 20:29
Vote:
 

Update:

Basically it all came together when my Review class inherited from ContentBase and nothing else :)

it now looks like working!

-Kjetil

#91208
Sep 29, 2014 22:11
Vote:
 

Hi,

Great stuff!

We've been using this in our project for a couple of months now. Last week thought, we updated our project from EPiServer CMS 8.1.0.0 to 8.11.0.0 and EPiServer Commerce from 8.9.0.566 to 8.15.0.810. Now the reviews don't show up in EPiServer edit mode.

We still get the "Reviews" tab, but "For This {0}" is missing. In the console we get an error in widgets.js:

"The store was queried with a [string] but the entity id is a [undefined]".

The [string] variable has the value "-1_-1".

The console is also being flooded with the warning "Observable store detected, but no sort order specified. You may experience quirks when adding/updating items. These can be resolved by setting a sort order on the list or grid.". This also happens on normal CMS content which don't use the navigation component.

Creating and displaying reviews programmatically on a page still works fine.

Does anyone have this issue with the newest version of EPiServer?

#132843
Aug 19, 2015 12:16
Vote:
 

We recently went from Commerce 8.3 + CMS 7.19 or something to CMS 8.10 and Commerce 8.15 - I currently get nothing in the Reviews-pane now. The console is flooded with things like this:

TypeError: Cannot read property 'appendChild' of null
at Object.place (dojo.js:15)
at _13d.addChild (widgets.js:2)
at _19e (dojo.js:15)
at _6a9.addChild (widgets.js:2)
at _19e (dojo.js:15)
at _126e.addChild (widgets.js:2)
at _19e (dojo.js:15)
at _1a2a.addChild (widgets.js:2)
at Object.addWidgetToRootFunction (widgets.js:2)
at null.<anonymous> (widgets.js:2)(anonymous function) @ widgets.js:2

TypeError: Cannot read property 'tagName' of undefined
at _68.placeAt (widgets.js:2)
at _1a2a.addChild (widgets.js:2)
at Object.addWidgetToRootFunction (widgets.js:2)
at null.<anonymous> (widgets.js:2)
at dojo.js:15
at _2f2 (dojo.js:15)
at Promise.then._2ff.then (dojo.js:15)
at when (dojo.js:15)
at _5e3._createInternal (widgets.js:2)
at null.<anonymous> (widgets.js:2)

Would indeed appreciate any input.

#132848
Aug 19, 2015 13:16
Vote:
 

Hi,

I reproduced a similar issue in 8.16.1 (Commerce). I raised a case with the engineering team, so hopefully will get more input from them regarding what could've caused this custom navigation pane/widget to break in 8.15 and later.

#133371
Sep 03, 2015 0:45
Vote:
 

Did you solve this? I am seeing the same errors in the console in 8.11 (CMS)

#140235
Oct 14, 2015 5:41
Vote:
 

Nope, haven't really come that far yet.

#140237
Oct 14, 2015 8:29
Vote:
 

It has apparently been fixed in EPiServer.CMS.UI 9.2.0.

http://world.episerver.com/support/Bug-list/bug/CMS-1420
http://world.episerver.com/releases/episerver---update-82/

I haven't tried to upgrade yet.

Lars

#140238
Oct 14, 2015 8:59
Vote:
 

Hi,

Lars raised this issue to Developer Support and dev team confirmed that this was a bug. The bug was raised as CMS-1420 and the fix for it was released in the version/udpate Lars mentioned.

#140277
Oct 14, 2015 20:05
Vote:
 

Hi,

Is there a workaround that can fix this problem without upgrading to EPiServer.CMS.UI 9.2.0?

BR

#141680
Nov 18, 2015 14:26
Vote:
 

Still has this issue in EPiServer.CMS.UI 9.3.3

#142077
Nov 30, 2015 15:16
Vote:
 

Workaround for this: add the following to your ContentRepositoryDescriptor (see my original post)

public bool EnableContextualContent { get { return true; } }

Works in CMS 8.9 + Commerce 8.13.X, at least.

(Originally given in http://world.episerver.com/support/Bug-list/bug/CMS-1420 , I got it from Episerver support)

#142177
Edited, Dec 03, 2015 16:16
Vote:
 

Arve, thanks a lot! It works now!

From bug list couldn't understand how to set that property - there is no such in base class.

Maris

#142178
Edited, Dec 03, 2015 17:38
Vote:
 

Hey, I tried couple of approach and plugin area with DefaultAssetGroup but still my component appear at bottom of the asset pane instead of top pane next to media and blocks tab.

How can I show my component in tab next to blocks and media?

#183563
Oct 17, 2017 15:16