Code Monkey home page Code Monkey logo

nikcio.uheadless's Introduction

nikcio.uheadless's People

Contributors

andybutland avatar biapar avatar dependabot[bot] avatar karlmacklin avatar nikcio avatar rizzet avatar thetanz-geoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nikcio.uheadless's Issues

Exception thrown when content picker value is node with unpublished parent

Using UHeadless version 2.2.0

Recreating scenario:

Add a simple document type with a single field in form of a node picker. Make it creatable in root and inherit itself as permissions.
Create the following node structure:

root
\-- page1
|     \--page2
|
\-- testpage

Make sure page2 is published, and have page1 be unpublished.
The slug for page2 should now be /page1/page2.

On the testpage, pick page2 as the content in the content picker.

Try to get the page via graphql query:

query myquery {
  contentByAbsoluteRoute(
    route: "/testpage"
  ) {
    properties {
      alias
      value
    }
  }
}

Expected result:

Null or empty value for the content picker.

Actual result:

An exception is thrown. GraphQL results:

{
  "errors": [
    {
      "message": "Exception has been thrown by the target of an invocation.",
      "locations": [
        {
          "line": 7,
          "column": 7
        }
      ],
      "path": [
        "contentByAbsoluteRoute",
        "properties",
        0,
        "value"
      ]
    }
  ],
  "data": {
    "contentByAbsoluteRoute": {
      "properties": [
        {
          "alias": "pickern",
          "value": null
        }
      ]
    }
  }
}

Dotnet runtime logged error is:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidCastException: Unable to cast object of type 'Umbraco.Cms.Core.GuidUdi' to type 'System.Collections.Generic.IEnumerable`1[Umbraco.Cms.Core.Models.PublishedContent.IPublishedContent]'.
   at Nikcio.UHeadless.UmbracoElements.Properties.EditorsValues.ContentPicker.BasicContentPicker`1..ctor(CreatePropertyValue createPropertyValue, IDependencyReflectorFactory dependencyReflectorFactory)
   at Nikcio.UHeadless.UmbracoElements.Properties.EditorsValues.ContentPicker.BasicContentPicker..ctor(CreatePropertyValue createPropertyValue, IDependencyReflectorFactory dependencyReflectorFactory)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Nikcio.UHeadless.Reflection.Factories.DependencyReflectorFactory.GetReflectedType[T](Type typeToReflect, Object[] constructorRequiredParamerters)
   at Nikcio.UHeadless.UmbracoElements.Properties.Factories.PropertyValueFactory.GetPropertyValue(CreatePropertyValue createPropertyValue)
   at Nikcio.UHeadless.UmbracoElements.Properties.Models.BasicProperty.get_Value()
   at HotChocolate.Execution.Processing.Tasks.ResolverTaskFactory.<ResolveAndCompleteInline>g__TryExecute|4_0(Object& result, <>c__DisplayClass4_0& )

This error does not trigger on multinode tree picker!

Preview

Hi,

Is there a way to use the Umbraco-preview?
Can we query unpublished but saved content in some way?

Extending BlockList blocks?

First of all, just wanted to say this package is very exciting - thanks so much for your work on it!

Also, I had a question about extending the Block List editor.

I can see how we can add custom properties to the parent block list property as per here:
https://github.com/nikcio/Nikcio.UHeadless/blob/v2/contrib/docs/v2/propertyValues/extendBlockList.md

But I can't figure out the syntax if we wanted to add a custom property to the child blocks elements themselves, e.g. having a custom property show in each of the "blocks" items underneath the value property of the BlockList. Is that possible?

Filter By Custom Property Value

Question

Hi,

I want to filter the nodes based on the custom property value. In the following GraphQL query, I have a custom property called "Header". I want to fetch the nodes where the "Header" property has the value "SOME VALUE". How can I achieve this? I have already reviewed the documentation at https://nikcio.github.io/Nikcio.UHeadless/.

{
contentAll{
nodes {

  namedProperties {
    ... on MediaCoverage {
      header {
        value
      }
    }
  }
}

}
}

How to access to the proprierty value?

I tried this query:

{
  contentAtRoot {
    nodes {
      id
      name
      contentType {
        alias
      }

      children {
        id
      }
      path
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
  }
  contentById(id: 1088) {
    id
    templateId
    creatorId
    properties {
      alias
      value {
        alias
        __typename
      }
    }
  }
}

but I don't retrieve the proprerty value. How to?

{
  "data": {
    "contentAtRoot": {
      "nodes": [
        {
          "id": 1088,
          "name": "Home",
          "contentType": {
            "alias": "home"
          },
          "children": [
            {
              "id": 1089
            },
            {
              "id": 1090
            },
            {
              "id": 1095
            },
            {
              "id": 1096
            },
            {
              "id": 1097
            },
            {
              "id": 1098
            }
          ],
          "path": "-1,1088"
        }
      ],
      "pageInfo": {
        "hasNextPage": false,
        "hasPreviousPage": false
      }
    },
    "contentById": {
      "id": 1088,
      "templateId": 1064,
      "creatorId": -1,
      "properties": [
        {
          "alias": "mainContent",
          "value": {
            "alias": "mainContent",
            "__typename": "BasicPropertyValue"
          }
        },
        {
          "alias": "socialLinks",
          "value": {
            "alias": "socialLinks",
            "__typename": "BasicNestedContent"
          }
        },
        {
          "alias": "title",
          "value": {
            "alias": "title",
            "__typename": "BasicPropertyValue"
          }
        },
        {
          "alias": "subtitle",
          "value": {
            "alias": "subtitle",
            "__typename": "BasicPropertyValue"
          }
        },
        {
          "alias": "mainImage",
          "value": {
            "alias": "mainImage",
            "__typename": "BasicMediaPicker"
          }
        },
        {
          "alias": "metaName",
          "value": {
            "alias": "metaName",
            "__typename": "BasicPropertyValue"
          }
        },
        {
          "alias": "metaDescription",
          "value": {
            "alias": "metaDescription",
            "__typename": "BasicPropertyValue"
          }
        },
        {
          "alias": "metaKeywords",
          "value": {
            "alias": "metaKeywords",
            "__typename": "BasicPropertyValue"
          }
        }
      ]
    }
  }
}

Query Error with field Umbraco.Grid

I tried this query where there is Umbraco.Grid field.
It give me this error:

{ contentById(id: 1088) { id name templateId creatorId itemType writerId key url properties { editorAlias, alias, value { ... on BasicPropertyValue { value } ... on BasicLabel { value } } } } }


This error:
{ "errors": [ { "message": "Unexpected Execution Error", "locations": [ { "line": 16, "column": 24 } ], "path": [ "contentById", "properties", 0, "value", "value" ], "extensions": { "message": "Parameter count mismatch.", "stackTrace": " at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitObject(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitObject(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitList(ICollection list, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.VisitValue(Object obj, Action1 setValue, ISet1 processed)\r\n at HotChocolate.Utilities.ObjectToDictionaryConverter.Convert(Object obj)\r\n at HotChocolate.Types.AnyType.TrySerialize(Object runtimeValue, Object& resultValue)\r\n at HotChocolate.Types.ScalarType.Serialize(Object runtimeValue)\r\n at HotChocolate.Execution.Processing.ValueCompletion.TryCompleteLeafValue(IOperationContext operationContext, MiddlewareContext resolverContext, ISelection selection, Path path, IType fieldType, Object result, Object& completedResult)", "code": "EXEC_INVALID_LEAF_VALUE" } } ], "data": { "contentById": { "id": 1088, "name": "Home", "templateId": 1064, "creatorId": -1, "itemType": "CONTENT", "writerId": -1, "key": "dcf18a51-6919-4cf8-89d1-36b94ce4d963", "url": "/", "properties": [ { "editorAlias": "Umbraco.Grid", "alias": "mainContent", "value": { "value": null } }, { "editorAlias": "Umbraco.NestedContent", "alias": "socialLinks", "value": {} }, { "editorAlias": "Umbraco.TextBox", "alias": "title", "value": { "value": "Clean Starter Kit" } }, { "editorAlias": "Umbraco.TextBox", "alias": "subtitle", "value": { "value": "For Umbraco" } }, { "editorAlias": "Umbraco.MediaPicker", "alias": "mainImage", "value": {} }, { "editorAlias": "Umbraco.TextBox", "alias": "metaName", "value": { "value": "" } }, { "editorAlias": "Umbraco.TextArea", "alias": "metaDescription", "value": { "value": "" } }, { "editorAlias": "Umbraco.Tags", "alias": "metaKeywords", "value": { "value": [] } } ] } } }

Allow ParameterType to be IsAssignableFrom()

if (parameters[i].ParameterType != requiredParameter)

Thank you for sharing your code, just what I needed! :)

I did find that I needed to change this line to:

if (parameters[i].ParameterType != requiredParameter && !parameters[i].ParameterType.IsAssignableFrom(requiredParameter))

to give it better flexibility for more use cases e.g. for interfaces and inheritance type scenarios.

Figured I'd share back in case it's helpful.

Custom model UsePaging scope disposed

Umbraco Version

10.0.0-rc1

UHeadless version

2.1.0

Description

When using the UsePaging attribute from HotChoclate on a custom property and then querying for a URL of a sibling or child the scope can be disposed in the process.

Example

using HotChocolate.Data;
using HotChocolate.Types;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Web.Common.PublishedModels;
using Umbraco.Extensions;

namespace Web.GraphQL.Models {
    public class WebNavigation {

        public WebNavigation(IPublishedContent? content) {
            Siblings = content.Siblings()?.Where(sibling => sibling.ContentType.Alias != Frontpage.ModelTypeAlias)?.Select(sibling => new NavigationItem(sibling.Name ?? "Page name not found", sibling.Url(mode: UrlMode.Relative))) ?? Enumerable.Empty<NavigationItem>();

            MenuItems = content.Children()?.Where(sibling => sibling.ContentType.Alias != Frontpage.ModelTypeAlias)?.Select(child => new NavigationItem(child.Name ?? "Page name not found", child.Url(mode: UrlMode.Relative))) ?? Enumerable.Empty<NavigationItem>();
}

        [UsePaging]
        [UseFiltering]
        [UseSorting]
        public IEnumerable<NavigationItem>? MenuItems { get; }

        [UsePaging]
        [UseFiltering]
        [UseSorting]
        public IEnumerable<NavigationItem>? Siblings { get; }
    }
}
using Nikcio.UHeadless.UmbracoContent.Content.Commands;
using Nikcio.UHeadless.UmbracoContent.Content.Factories;
using Nikcio.UHeadless.UmbracoContent.Content.Models;
using Nikcio.UHeadless.UmbracoElements.ContentTypes.Factories;
using Nikcio.UHeadless.UmbracoElements.ContentTypes.Models;
using Nikcio.UHeadless.UmbracoElements.Properties.Factories;
using Nikcio.UHeadless.UmbracoElements.Properties.Models;
using Umbraco.Cms.Core.Web;

namespace Web.GraphQL.Models {
    public class WebContentModel : BasicContent<BasicProperty, BasicContentType> {
        public WebContentModel(CreateContent createContent, IPropertyFactory<BasicProperty> propertyFactory, IContentTypeFactory<BasicContentType> contentTypeFactory, IContentFactory<BasicContent<BasicProperty, BasicContentType>, BasicProperty> contentFactory) : base(createContent, propertyFactory, contentTypeFactory, contentFactory) {
        }

        public WebNavigation Navigation => new(Content);
    }
}

Call Stack

image

   at Umbraco.Cms.Infrastructure.Scoping.Scope.EnsureNotDisposed()
   at Umbraco.Cms.Infrastructure.Scoping.Scope.EnsureNotDisposed()
   at Umbraco.Cms.Infrastructure.Scoping.Scope.Dispose()
   at Umbraco.Cms.Core.Services.LocalizationService.GetDefaultLanguageIsoCode()
   at Umbraco.Cms.Core.Routing.DefaultUrlProvider.GetUrlFromRoute(String route, IUmbracoContext umbracoContext, Int32 id, Uri current, UrlMode mode, String culture)
   at Umbraco.Cms.Core.Routing.DefaultUrlProvider.GetUrl(IPublishedContent content, UrlMode mode, String culture, Uri current)
   at Umbraco.Cms.Core.Routing.UrlProvider.<>c__DisplayClass14_0.<GetUrl>b__0(IUrlProvider provider)
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
   at Umbraco.Cms.Core.Routing.UrlProvider.GetUrl(IPublishedContent content, UrlMode mode, String culture, Uri current)
   at Umbraco.Extensions.PublishedContentExtensions.Url(IPublishedContent content, IPublishedUrlProvider publishedUrlProvider, String culture, UrlMode mode)
   at Web.GraphQL.Models.WebNavigation.<>c.<.ctor>b__0_3(IPublishedContent child) in Y:\GitRepo\sem-4-project\backend\src\cms\Web\GraphQL\Models\WebNavigation.cs:line 27
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.EnumerablePartition`1.MoveNext()
   at HotChocolate.Types.Pagination.QueryableCursorPagination`1.<>c__DisplayClass6_0.<ExecuteAsync>b__0()
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)

How do you write a query to pull back data for all properties? (Breaking Change 2.0 -> 3.0)

Prior to 3.0, I could get all of the property data back.

{
  contentByAbsoluteRoute (route: "/") {
    name,
    url
    key,
    id,
    properties {
      alias,
      value
    }
  }
}

I'm aware this is a breaking change.

Now I'm required to extrapolate this generic object across 10 types: BasicBlockListModel, BasicContentPicker, BasicDateTimePicker, BasicLabel, BasicMediaPicker, BasicMemberPicker, BasicMultiUrlPicker, BasicNestedContent, BasicPropertyValue, BasicRichText.

So I thought, let's use a fragment...

{
  contentByAbsoluteRoute (route: "/") {
    name,
    url
    key,
    id,
    properties {
      value {
        ... propertyValue
      }
    }
  }
}

The fragment approach works well until you come across BasicBlockListModel or BasicNestedContent. These models have content inside them, but I'm not allowed to call a fragment recursively.

fragment propertyValue on PropertyValue {
  alias,
  ... on BasicBlockListModel {
    blocks {
      contentAlias,
      contentProperties {
        ... propertyValue        
      },
      settingsAlias,
      settingsProperties {
        ... propertyValue        
      }
    }
  }
}

I understand this is a breaking change but is it still possible to ask for all property data in my query?

Doubt about PropertyValueFilterInput

Question

Hi! I need help to return all the contents by a search criteria.

I noticed a where clause that is a PropertyValueFilterInput in some queries. Am I able to use it to look for values inside one or more properties with specific alias, even properties inside blocklists, using fuzzy search?

If not how can I proceed to achieve this?

Thank you in advance.

image

How to query only own data?

How to query only own data? That is. I've authenticate the user by Oauth2 and then he can only query his data ( nodes ).

Possible localization bug in BasicBlockListModel?

var propertyValue = createPropertyValue.Property.GetValue();

Should this line pass culture like so?

var propertyValue = createPropertyValue.Property.GetValue(createPropertyValue.Culture);

I was getting cryptic error when querying blocklist, seems it was related to the culture being null:
image

   at Umbraco.Cms.Core.Collections.CompositeStringStringKey..ctor(String key1, String key2)
   at Umbraco.Cms.Infrastructure.PublishedCache.Property.CacheValues.For(String culture, String segment)
   at Umbraco.Cms.Infrastructure.PublishedCache.Property.GetValue(String culture, String segment)

Unable to obtain children of content within BasicContentPicker

Hi there,

I am currently trying to understand the method of accessing selected nodes from within a content picker. I first noticed that there was no relevant property for me to query the content, which led me to discover that the Content property has a tag on it to prevent it being visible within the schema (see here).

I am just curious about the logic behind this decision as I was unable to find any documentation on why that would be the case - as now I am looking to create my own custom BasicContentPickerItem that would get the children prop from the content prop and register a custom BasicContentPicker alongside.

	public sealed class CustomBasicContentPickerItem : BasicContentPickerItem
	{
		/// <summary>
		/// Gets the children of the selected content
		/// </summary>
		[GraphQLDescription("Gets the children of the selected content")]
		public IEnumerable<IPublishedContent> Children => Content.Children;

		public CustomBasicContentPickerItem(CreateContentPickerItem createContentPickerItem) : base(createContentPickerItem)
		{
		}
	}
	public class CustomBasicContentPicker : BasicContentPicker<CustomBasicContentPickerItem>
	{
		public CustomBasicContentPicker(CreatePropertyValue createPropertyValue, IDependencyReflectorFactory dependencyReflectorFactory, IVariationContextAccessor variationContextAccessor) : base(createPropertyValue, dependencyReflectorFactory, variationContextAccessor)
		{
		}
	}

It would be great to know if this is the correct approach to resolving my issue.

Thanks!

P.S Very much enjoying using the package, so far has provided us great route to moving to headless compared to using the Content Delivery API supplied by Umbraco!

Using GraphQL to query MarkdownEditor value

Stellar package Nikolaj.

I'm hitting an issue trying to access values edited using Umbraco's native MarkdownEditor and I can't seem to crack the case.

{
  contentAtRoot {
    nodes {
      properties {
        __typename
        alias
        editorAlias
        value {
          __typename
          ...on BasicPropertyValue {
            __typename
            alias
            value
          }
        }
      }
    }
  }
}

...gives me:

{
  "data": {
    "contentAtRoot": {
      "nodes": [
        {
          "properties": [
            {
              "__typename": "BasicProperty",
              "alias": "thisOneIsMarkdown",
              "editorAlias": "Umbraco.MarkdownEditor",
              "value": {
                "__typename": "BasicPropertyValue",
                "alias": "thisOneIsMarkdown",
                "value": {}
              }
            },
            {
              "__typename": "BasicProperty",
              "alias": "thisOneIsNot",
              "editorAlias": "Umbraco.TextBox",
              "value": {
                "__typename": "BasicPropertyValue",
                "alias": "thisOneIsNot",
                "value": "Air"
              }
            }
          ]
        }
      ]
    }
  }
}

Presume that retrieving the MarkdownEditor's value is just something which is not yet supported?

Adding custom basic types

Hi,

I tried extending the basic content model as stated in the docs:

public class MetaDescriptionContent : BasicContent
	{
		public string MyCustomValue { get; set; }

		public MetaDescriptionContent(CreateContent createContent, IPropertyFactory<BasicProperty> propertyFactory, IContentTypeFactory<BasicContentType> contentTypeFactory, IContentFactory<BasicContent<BasicProperty, BasicContentType, BasicContentRedirect>, BasicProperty> contentFactory) : base(createContent, propertyFactory, contentTypeFactory, contentFactory)
		{
			MyCustomValue = "Custom Value";
		}
	}

	public class MetaDescriptionContentQuery : ContentQuery<MetaDescriptionContent, BasicProperty, BasicContentRedirect>
	{
	}

Registered like so:

var graphqlExtensions = (IRequestExecutorBuilder builder) =>
	            builder
		        .AddTypeExtension<MetaDescriptionContentQuery>()
		        .AddTypeExtension<BasicPropertyQuery>()
		        .AddTypeExtension<BasicMediaQuery>();

			services.AddUmbraco(_env, _config)
                .AddBackOffice()
                .AddWebsite()
                .AddComposers()
	            .AddUHeadless(new()
	            {
		            UHeadlessGraphQLOptions = new()
		            {
			            GraphQLExtensions = graphqlExtensions
					}
	            })
				.Build();

Created query:

{
  contentAtRoot() {
    nodes {
      id,
      name,
      myCustomValue,
      properties {
      value { 
        __typename,
        alias
        ...on BasicPropertyValue {
          alias,
          value
        },
        ... on BasicRichText {
          alias,
          content: value
        } 
        }
      }   
    }
  }
}

But when I try to query, it gives me:

{
  "errors": [
    {
      "message": "The field `contentAtRoot` does not exist on the type `Query`.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "extensions": {
        "type": "Query",
        "field": "contentAtRoot",
        "responseName": "contentAtRoot",
        "specifiedBy": "http://spec.graphql.org/October2021/#sec-Field-Selections-on-Objects-Interfaces-and-Unions-Types"
      }
    }
  ]
}

What could be the issue?
Btw: It does not matter if I remove the myCustomValue from the query or not, the error is the same.
Using Umbraco 10.4.0 and UHeadless 3.3.0

Empty value when property is shared between cultures

Background

I have a very simple demo umbraco site with these packages installed:

  • <PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
  • <PackageReference Include="uSync" Version="11.1.0" />
  • <PackageReference Include="Nikcio.UHeadless" Version="3.3.0" />
  • <PackageReference Include="Umbraco.Cms" Version="11.3.1" />

Steps to reproduce:

  • Create a site with two languages.
  • Create a Document type with "Allow vary by culture" ON.
  • Create a textbox property with "Allow vary by culture" OFF.
  • Go query for that page with one culture:
{
  contentById(id: 1061, culture: "en-us") {
    id
    properties {
      alias
      editorAlias
      value {
        ... on CustomPropertyValue {
          value # Value of that property will be ""
        }
      }
    }
  }
}

Solution

I suspect that the root cause is because you always add Culture when querying for property value. When the correct way to do that (in Umbraco 11) is adding a simple check like this.

public class CustomPropertyValue : BasicPropertyValue
    {
        [GraphQLType(typeof(AnyType))]
        public override object? Value { get; set; }

        public CustomPropertyValue(CreatePropertyValue createPropertyValue) : base(createPropertyValue)
        {
            var property = createPropertyValue.Property;
            Value = property.GetValue(property.PropertyType.Variations == ContentVariation.Culture
                ? createPropertyValue.Culture : string.Empty);
        }
    }

As you can see there will be issues with when "Allow segmentation" involves in, but I'm not experienced enough with Umbraco to think about that right now.

Few words

This project is a game changer for headless cms umbraco. I would love to create a PR but I'm not sure which branch should I fork and create a PR to.
Thank you for your hard work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.