Fermer

juillet 31, 2022

Composant SXA Map Partie 4 Afficher les marqueurs de points d’intérêt pour les mêmes coordonnées

Composant SXA Map Partie 4 Afficher les marqueurs de points d’intérêt pour les mêmes coordonnées


Défi:

Salut les gens! Étant donné le composant SXA Map configuré sur la page et si nous avons plusieurs éléments POI avec les mêmes coordonnées, alors il n’en affiche qu’un seul sur la carte. Apparemment le dernier dans l’arborescence de contenu. Explorons comment nous pouvons résoudre ce problème et afficher toutes les informations sur les éléments POI sur le marqueur.

Il s’agit du quatrième article de la série d’un composant SXA Map.

  1. Composant de carte SXA
  2. Composant SXA Map Partie 2 avec résultats de recherche et localisateur
  3. Composant de carte SXA Partie 3 Afficher la distance dans le marqueur de POI
  4. Composant SXA Map Partie 4 Afficher les marqueurs de points d’intérêt pour les mêmes coordonnées

Scénarios :

  1. Une page n’a que le composant SXA Map avec la source de données ayant l’élément POI ou le dossier POI sélectionné dans le champ POI. Cela charge toutes les données sur le chargement de la page où Sitecore.XA.Feature.Maps.Repositories.MapsRepository est impliqué dans la fourniture de la sortie des marqueurs. (Se référer à Composant de carte SXA pour la configuration de base.)
  2. Une page a le composant SXA Map où sa source de données a un champ POI vide, le composant Location Finder et le composant Search Results. En cliquant sur l’icône du marqueur POI, une API est appelée où Sitecore.XA.Foundation.Variants.Abstractions.Controllers.VariantsApiController est impliqué dans la fourniture de la sortie des marqueurs. (Se référer à Composant SXA Map Partie 2 avec résultats de recherche et localisateur pour une configuration de base sans la signature de recherche.)

Pour reproduire le problème, configurez 2 pages, une pour chaque scénario ci-dessus. Une fois la configuration terminée, sélectionnez 2 éléments POI ou plus et copiez les valeurs des champs Latitude et Longitude d’un élément POI dans les champs respectifs des autres éléments POI.

Par exemple, j’ai un dossier POI comme ci-dessous. Ici, les éléments POI « Spoke Steele » et « St Elmo Steak House » ont les mêmes coordonnées.

Éléments de points d'intérêt aux mêmes coordonnées

Éléments de points d’intérêt aux mêmes coordonnées

Sous le dossier POI Business Locations, nous avons 5 éléments POI, mais la carte n’affiche que 4 informations sur les éléments POI.

Même coordonnées POI Sortie - Un seul marqueur de POI est affiché

Même coordonnées POI Sortie – Un seul marqueur de POI est affiché

La solution:

L’objectif est de montrer la sortie des éléments POI avec les mêmes coordonnées empilés dans un marqueur fournissant toutes les informations.

Sitecore - Comprendre les approches de développement : une perspective de Sitecore

Vérifiez Extension de carte Référentiel pour l’implémentation présentée dans cet article.

Pour le premier cas, la page ne contient que le composant SXA Map. Dans ce cas, nous pouvons remplacer Sitecore.XA.Feature.Maps.Repositories.MapsRepository comme ci-dessous.

using Sitecore.Data.Items;
using Sitecore.XA.Feature.Maps.Models;
using Sitecore.XA.Feature.Maps.Repositories;
using Sitecore.XA.Foundation.Geospatial.Services;
using Sitecore.XA.Foundation.SitecoreExtensions.Extensions;
using System.Collections.Generic;
using System.Linq;

namespace CustomSXA.Foundation.MapExtension.Repositories
{
    public class ExtendedNativeMapRepository : MapsRepository
    {
        public ExtendedNativeMapRepository(IMapsProvider mapsProvider) : base(mapsProvider)
        {
        }

        protected override void GetPois(Item item, ICollection<Sitecore.XA.Feature.Maps.Models.Poi> result)
        {
            if (item == null)
                return;
            if (item.InheritsFrom(Sitecore.XA.Foundation.Geospatial.Templates.PoiGroup.ID) || item.InheritsFrom(Sitecore.XA.Foundation.Geospatial.Templates.PoiGroupingItem.ID))
            {
                foreach (Item child in item.GetChildren())
                    this.GetPois(child, result);
            }
            else
            {
                if (!item.InheritsFrom(Sitecore.XA.Foundation.Geospatial.Templates.MyLocationPoi.ID) && !item.InheritsFrom(Sitecore.XA.Foundation.Geospatial.Templates.IPoi.ID))
                    return;

                AddPois(item, result);
            }
        }

        private void AddPois(Item item, ICollection<Sitecore.XA.Feature.Maps.Models.Poi> result)
        {
            Poi newPoi = new Poi(item, GetPoiIcon(item), GetPoiVariant(item));

            Poi foundPoi = result.ToList().Find(it => it.Latitude == newPoi.Latitude && it.Longitude == newPoi.Longitude);
            if (foundPoi != null)
            {
                foundPoi.Html = foundPoi.Html + "<hr/>" + newPoi.Html;
                return;
            }
            result.Add(newPoi);
        }
    }
}

Corrigez la configuration suivante.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <services>
      <register patch:instead="register[@implementationType="Sitecore.XA.Feature.Maps.Repositories.MapsRepository, Sitecore.XA.Feature.Maps"]" serviceType="Sitecore.XA.Feature.Maps.Repositories.IMapsRepository, Sitecore.XA.Feature.Maps"
                implementationType="CustomSXA.Foundation.MapExtension.Repositories.ExtendedNativeMapRepository, CustomSXA.Foundation.MapExtension" lifetime="Transient"/>
    </services>
  </sitecore>
</configuration>

Créez et déployez la DLL et le fichier de configuration sur votre racine Web.

Sortie des points d'intérêt avec les mêmes coordonnées – Correction du premier cas

Sortie des points d’intérêt avec les mêmes coordonnées – Correction du premier cas

Dans le second cas, la page contient le composant SXA Map avec Location Finder et Search Results.

Puisqu’ici une API – /sxa/geoVariants est appelée en cliquant sur l’icône du marqueur POI, nous pouvons personnaliser sa mise en œuvre comme ci-dessous.

using System;
using System.Collections.Generic;
using Sitecore.ContentSearch.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Mvc.Common;
using Sitecore.Mvc.Presentation;
using Sitecore.XA.Foundation.Abstractions;
using Sitecore.XA.Foundation.Search.Models;
using Sitecore.XA.Foundation.Search.Services;
using Sitecore.XA.Foundation.SitecoreExtensions.Extensions;
using Sitecore.XA.Foundation.SitecoreExtensions.Repositories;
using Sitecore.XA.Foundation.Variants.Abstractions.Models;
using Sitecore.XA.Foundation.Variants.Abstractions.Services;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http;

namespace CustomSXA.Foundation.MapExtension.Controllers
{
    public class ExtendedVariantsApiController : ApiController
    {
        private readonly IVariantRenderingService _variantRenderingService;
        private readonly IContentRepository _contentRepository;
        private readonly IOrderingParametersParserService _parametersParsingService;
        private readonly IContext _context;

        public ExtendedVariantsApiController()
        {}

        public ExtendedVariantsApiController(
          IContentRepository contentRepository,
          IVariantRenderingService variantRenderingService,
          IOrderingParametersParserService parametersParsingService,
          IContext context)
        {
            this._variantRenderingService = variantRenderingService;
            this._contentRepository = contentRepository;
            this._parametersParsingService = parametersParsingService;
            this._context = context;
        }

        [HttpGet]
        [ActionName("renderGeospatial")]
        public RenderVariantResult RenderGeospatialVariant(
          string variantId,
          string itemId,
          string coordinates,
          string ordering,
          string pageId = null)
        {
            Item variantItem = this._contentRepository.GetItem(variantId);
            Item contentItem = this._contentRepository.GetItem(itemId);
            Coordinate coordinate = (Coordinate)coordinates;
            string message = this.ValidateRenderVariantGeospatialParameters(variantId, itemId, coordinates, contentItem, variantItem, coordinate);
            if (!string.IsNullOrEmpty(message))
            {
                Log.Error(message, (object)this);
                throw this.StatusCodeException(HttpStatusCode.BadRequest, message);
            }
            try
            {
                this.SetPageContext(pageId == null ? this._contentRepository.GetItem(itemId) : this._contentRepository.GetItem(pageId));
                if (coordinate == null)
                    return this._variantRenderingService.RenderVariant(variantId, itemId);
                IOrderingParametersParserService parametersParsingService = this._parametersParsingService;
                List<string> sortings = new List<string>();
                sortings.Add(ordering);
                string name = this._context.Site.SiteInfo.Name;
                Unit units = parametersParsingService.GetUnits((IEnumerable<string>)sortings, name);

                //include same coordinates locations
                Item[] sameLocationItems = Sitecore.Context.Database.SelectItems($"{contentItem.Parent.Paths.FullPath}//*[@@templatename="POI" and @Latitude="{contentItem.Fields["Latitude"]}" and @Longitude="{contentItem.Fields["Longitude"]}"]");

                RenderVariantResult finalResult = null;
                foreach (var item in sameLocationItems)
                {
                    Dictionary<string, object> parameters = new Dictionary<string, object>()
                    {
                      {
                        "geospatial",
                        (object) new Geospatial(item, coordinate, units)
                      }
                    };
                    if (finalResult == null)
                        finalResult = this._variantRenderingService.RenderVariantWithParameters(variantItem, contentItem, RendererMode.Html, parameters);
                    else
                    {
                        finalResult.Html += "<hr/>" + this._variantRenderingService.RenderVariantWithParameters(variantItem, item, RendererMode.Html, parameters).Html;
                    }
                }
                return finalResult;
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message, (object)this);
                throw this.StatusCodeException(HttpStatusCode.InternalServerError, ex.Message);
            }
            finally
            {
                this.RevertPageContext();
            }
        }
        protected virtual void SetPageContext(Item contextItem) => ContextService.Get().Push<PageContext>(new PageContext()
        {
            Item = contextItem
        });

        protected virtual void RevertPageContext() => ContextService.Get().Pop<PageContext>();

        protected virtual string ValidateRenderVariantGeospatialParameters(
          string variantId,
          string itemId,
          string coordinates,
          Item item,
          Item variantItem,
          Coordinate parsedCoordinates)
        {
            string originalString = this.ValidateRenderVariantParameters(variantId, itemId, item, variantItem);
            if (parsedCoordinates == null)
                originalString = originalString.AppendNewLine("Coordinates cannot be parsed " + coordinates);
            return originalString;
        }

        protected virtual string ValidateRenderVariantParameters(
          string variantId,
          string itemId,
          Item item,
          Item variantItem)
        {
            string originalString = string.Empty;
            if (item == null)
                originalString = originalString.AppendNewLine("Item not found " + itemId);
            if (variantItem == null)
                originalString = originalString.AppendNewLine("Variant item not found " + variantId);
            return originalString;
        }

        protected virtual HttpResponseException StatusCodeException(
          HttpStatusCode statusCode,
          string message)
        {
            return new HttpResponseException(new HttpResponseMessage()
            {
                StatusCode = statusCode,
                Content = (HttpContent)new ObjectContent(typeof(RenderVariantException), (object)new RenderVariantException(message), (MediaTypeFormatter)System.Web.Http.GlobalConfiguration.Configuration.Formatters.JsonFormatter)
            });
        }
    }
}
using Microsoft.Extensions.DependencyInjection;
using Sitecore.DependencyInjection;
using Sitecore.Pipelines;
using Sitecore.Web;
using Sitecore.XA.Foundation.Multisite;
using System;
using System.Linq;
using System.Web.Http;
using System.Web.Routing;

namespace CustomSXA.Foundation.MapExtension.Pipelines.Initialize
{
    public class InitializeRouting
    {
        public void Process(PipelineArgs args)
        {
            foreach (string virtualFolder in ServiceLocator.ServiceProvider.GetService<ISiteInfoResolver>().Sites.Select<SiteInfo, string>((Func<SiteInfo, string>)(s => s.VirtualFolder.Trim('/'))).Distinct<string>())
            {
                string finalVirtualFolder = virtualFolder.Length > 0 ? virtualFolder + "/" : virtualFolder;

                string key = finalVirtualFolder + "withContextSxaGeospatialVariants";
                RemoveHttpRoute(key);
                RouteTable.Routes.MapHttpRoute(finalVirtualFolder + "withContextSxaGeospatialVariants", finalVirtualFolder + "sxa/geoVariants/{variantId}/{itemId}/{coordinates}/{ordering}/{pageId}", (object)new
                {
                    controller = "ExtendedVariantsApi",
                    action = "renderGeospatial"
                });

                key = finalVirtualFolder + "sxaGeospatialVariants";
                RemoveHttpRoute(key);
                RouteTable.Routes.MapHttpRoute(finalVirtualFolder + "sxaGeospatialVariants", finalVirtualFolder + "sxa/geoVariants/{variantId}/{itemId}/{coordinates}/{ordering}", (object)new
                {
                    controller = "ExtendedVariantsApi",
                    action = "renderGeospatial"
                });
            }
        }

        private static void RemoveHttpRoute(string key)
        {
            if (RouteTable.Routes[key] != null)
            {
                RouteTable.Routes.Remove(RouteTable.Routes[key]);
            }
        }
    }
}

Corrigez la configuration suivante.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <initialize>
        <processor patch:after="processor[@type="Sitecore.XA.Foundation.Variants.Abstractions.Pipelines.Initialize.InitializeRouting, Sitecore.XA.Foundation.Variants.Abstractions"]" type="CustomSXA.Foundation.MapExtension.Pipelines.Initialize.InitializeRouting, CustomSXA.Foundation.MapExtension" resolve="true" />
      </initialize>
    </pipelines>
    <services>
      <register serviceType="CustomSXA.Foundation.MapExtension.Controllers.ExtendedVariantsApiController, CustomSXA.Foundation.MapExtension" implementationType="CustomSXA.Foundation.MapExtension.Controllers.ExtendedVariantsApiController, CustomSXA.Foundation.MapExtension" lifetime="Transient"/>
    </services>
  </sitecore>
</configuration>

Si vous avez suivi les messages précédents, vous trouverez ci-dessous le fichier de configuration du correctif final.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <generateScribanContext>
        <processor type="CustomSXA.Foundation.MapExtension.GetGeospatial, CustomSXA.Foundation.MapExtension" resolve="true" />
      </generateScribanContext>
      <initialize>
        <processor patch:after="processor[@type="Sitecore.XA.Foundation.Variants.Abstractions.Pipelines.Initialize.InitializeRouting, Sitecore.XA.Foundation.Variants.Abstractions"]" type="CustomSXA.Foundation.MapExtension.Pipelines.Initialize.InitializeRouting, CustomSXA.Foundation.MapExtension" resolve="true" />
      </initialize>
    </pipelines>
    <services>
      <register patch:instead="register[@implementationType="Sitecore.XA.Feature.Maps.Repositories.MapsRepository, Sitecore.XA.Feature.Maps"]" serviceType="Sitecore.XA.Feature.Maps.Repositories.IMapsRepository, Sitecore.XA.Feature.Maps"
                implementationType="CustomSXA.Foundation.MapExtension.Repositories.ExtendedNativeMapRepository, CustomSXA.Foundation.MapExtension" lifetime="Transient"/>
      <register serviceType="CustomSXA.Foundation.MapExtension.Controllers.ExtendedVariantsApiController, CustomSXA.Foundation.MapExtension" implementationType="CustomSXA.Foundation.MapExtension.Controllers.ExtendedVariantsApiController, CustomSXA.Foundation.MapExtension" lifetime="Transient"/>
    </services>
  </sitecore>
</configuration>

Créez et déployez la DLL et le fichier de configuration sur votre racine Web.

Sortie des points d'intérêt aux mêmes coordonnées – Correction du deuxième cas

Sortie des points d’intérêt avec les mêmes coordonnées – Correction du deuxième cas

J’espère que cela t’aides! Bon apprentissage Sitecore 🙂






Source link