public async Task WHEN_param_is_ok_SHOULD_fill_criteria_context_from_ComposerContext()
        {
            //Arrange
            var scope       = GetRandom.String(6);
            var cultureInfo = CultureInfo.InvariantCulture;

            ArrangeComposerContext(scope, cultureInfo);

            var param = CreateEmptyParam();
            GetCategoryBrowsingViewModelParam passedParam = null;

            var sut             = _container.CreateInstance <BrowseCategoryRequestContext>();
            var catBrowsingMock = _container.GetMock <ICategoryBrowsingViewService>();

            catBrowsingMock
            .Setup(q => q.GetCategoryBrowsingViewModelAsync(It.IsAny <GetCategoryBrowsingViewModelParam>()))
            .Callback((GetCategoryBrowsingViewModelParam p) => passedParam = p)
            .ReturnsAsync(new CategoryBrowsingViewModel());

            //Act
            await sut.GetCategoryAvailableProductsAsync(param);

            //Assert
            passedParam.CultureInfo.Should().NotBeNull();
            passedParam.CultureInfo.Should().Be(cultureInfo);

            _container.Verify <IComposerContext>();
        }
예제 #2
0
        public virtual async Task <IHttpActionResult> GetCategoryFacets(GetCategoryFacetsRequest request)
        {
            var param = new GetCategoryBrowsingViewModelParam
            {
                CategoryId           = request.CategoryId,
                CategoryName         = string.Empty,
                BaseUrl              = RequestUtils.GetBaseUrl(Request).ToString(),
                IsAllProducts        = false,
                NumberOfItemsPerPage = 0,
                Page                 = 1,
                SortBy               = "score",
                SortDirection        = "desc",
                InventoryLocationIds = await InventoryLocationProvider.GetInventoryLocationIdsForSearchAsync().ConfigureAwait(false),
                CultureInfo          = ComposerContext.CultureInfo
            };

            if (!string.IsNullOrEmpty(request.QueryString))
            {
                var queryString = HttpUtility.ParseQueryString(request.QueryString);
                param.SelectedFacets = SearchUrlProvider.BuildSelectedFacets(queryString).ToList();
            }

            var viewModel = await CategoryBrowsingViewService.GetCategoryBrowsingViewModelAsync(param).ConfigureAwait(false);

            viewModel.ProductSearchResults.Facets = viewModel.ProductSearchResults.Facets.Where(f => !f.FieldName.StartsWith(SearchConfiguration.CategoryFacetFiledNamePrefix)).ToList();

            return(Ok(viewModel));
        }
예제 #3
0
        protected virtual async Task <SearchCriteria> GetSearchCriteriaAsync(GetCategoryBrowsingViewModelParam param)
        {
            var criteria = new CategorySearchCriteria
            {
                NumberOfItemsPerPage = param.NumberOfItemsPerPage,
                IncludeFacets        = true,
                InventoryLocationIds = param.InventoryLocationIds,
                AvailabilityDate     = FulfillmentContext.AvailabilityAndPriceDate,
                StartingIndex        = (param.Page - 1) * SearchConfiguration.MaxItemsPerPage, // The starting index is zero-based.
                SortBy            = param.SortBy,
                SortDirection     = param.SortDirection,
                Page              = param.Page,
                BaseUrl           = param.BaseUrl,
                CultureInfo       = ComposerContext.CultureInfo,
                Scope             = ComposerContext.Scope,
                AutoCorrect       = SearchConfiguration.AutoCorrectSearchTerms,
                CategoryId        = param.CategoryId,
                CategoryHasFacets = param.SelectedFacets.Any()
            };

            List <SearchFilter> selectedCategories = await GetSelectedCategoriesAsync(param).ConfigureAwait(false);

            List <SearchFilter> selectedFacets = param.SelectedFacets;

            criteria.SelectedFacets.AddRange(selectedCategories);
            criteria.SelectedFacets.AddRange(selectedFacets);

            return(criteria);
        }
예제 #4
0
        protected virtual async Task <SelectedFacets> GetSelectedFacetsAsync(GetCategoryBrowsingViewModelParam param)
        {
            List <SearchFilter> selectedCategories = await GetSelectedCategoriesAsync(param).ConfigureAwait(false);

            List <SearchFilter> allFacets = selectedCategories.Concat(param.SelectedFacets).ToList();

            return(FlattenFilterList(allFacets, param.CultureInfo));
        }
예제 #5
0
        private async Task <List <SearchFilter> > GetSelectedCategoriesAsync(GetCategoryBrowsingViewModelParam param)
        {
            List <Category> selectedCategories = await GetAncestorsAndSelfCategoriesAsync(param).ConfigureAwait(false);

            return(selectedCategories.Select((category, i) => new SearchFilter
            {
                Name = String.Format("CategoryLevel{0}_Facet", i + 1),
                Value = category.DisplayName.GetLocalizedValue(_context.CultureInfo.Name),
                IsSystem = true
            }).ToList());
        }
예제 #6
0
        private async Task <TreeNode <Category> > GetCurrentCategoryNodeAsync(GetCategoryBrowsingViewModelParam param)
        {
            Tree <Category, string> tree = await _categoryRepository.GetCategoriesTreeAsync(new GetCategoriesParam { Scope = _context.Scope }).ConfigureAwait(false);

            if (tree.ContainsKey(param.CategoryId))
            {
                return(tree[param.CategoryId]);
            }

            throw new InvalidOperationException(String.Format("{0} does not exist in the retrieved category tree", param.CategoryId));
        }
예제 #7
0
        /// <summary>
        /// Category Browse page allows filter by facets but we can't filter by sibling category facets.
        /// </summary>
        /// <param name="param"></param>
        /// <param name="node"></param>
        ///
        private void CleanSiblingFacets(GetCategoryBrowsingViewModelParam param, CategoryFacetValuesTreeNode node)
        {
            var selected = node.ChildNodes?.FirstOrDefault(c => c.IsSelected && c.CategoryId == param.CategoryId);

            if (selected != null)
            {
                node.ChildNodes = node.ChildNodes.Where(c => c.CategoryId == param.CategoryId).ToList();
            }

            node.ChildNodes?.ForEach(childNode => CleanSiblingFacets(param, childNode));
        }
예제 #8
0
        protected virtual string GetCategoryUrl(string categoryId, GetCategoryBrowsingViewModelParam param, bool isAllProductsPage = false)
        {
            string url = CategoryBrowsingUrlProvider.BuildCategoryBrowsingUrl(new BuildCategoryBrowsingUrlParam
            {
                CategoryId        = categoryId,
                CultureInfo       = param.CultureInfo,
                BaseUrl           = param.BaseUrl,
                IsAllProductsPage = isAllProductsPage
            });

            return(url);
        }
예제 #9
0
        private async Task <List <Category> > GetAncestorsAndSelfCategoriesAsync(GetCategoryBrowsingViewModelParam param)
        {
            TreeNode <Category> current = await GetCurrentCategoryNodeAsync(param).ConfigureAwait(false);

            var categories = new List <Category>();

            while (current != null && !current.Value.Id.Equals("Root", StringComparison.InvariantCultureIgnoreCase))
            {
                categories.Insert(0, current.Value);
                current = current.Parent;
            }

            return(categories);
        }
예제 #10
0
        protected virtual string GetParentPageUrl(TreeNode <Category> currentNode, GetCategoryBrowsingViewModelParam param)
        {
            var nodeLevel            = currentNode.GetLevel();
            var isLandingAllProducts = nodeLevel <= CategoriesConfiguration.LandingPageMaxLevel;

            string parentPageUrl;

            if (currentNode.Value.PrimaryParentCategoryId != null && currentNode.Value.PrimaryParentCategoryId != "Root")
            {
                parentPageUrl = GetCategoryUrl(currentNode.Value.PrimaryParentCategoryId, param, isLandingAllProducts);
            }
            else
            {
                parentPageUrl = GetCategoryUrl(currentNode.Value.Id, param, isLandingAllProducts);
            }

            return(parentPageUrl);
        }
예제 #11
0
        public virtual async Task <IHttpActionResult> GetSearchResults(GetSearchResultsRequest request)
        {
            var queryString    = HttpUtility.ParseQueryString(request.QueryString ?? "");
            var SelectedFacets = SearchUrlProvider.BuildSelectedFacets(queryString).ToList();
            var CurrentPage    = int.TryParse(queryString[SearchRequestParams.Page], out int page) && page > 0 ? page : 1;
            var SortDirection  = queryString[SearchRequestParams.SortDirection] ?? SearchRequestParams.DefaultSortDirection;
            var SortBy         = queryString[SearchRequestParams.SortBy] ?? SearchRequestParams.DefaultSortBy;
            var BaseUrl        = RequestUtils.GetBaseUrl(Request).ToString();
            var Keywords       = queryString[SearchRequestParams.Keywords];
            BaseSearchViewModel viewModel;

            if (!string.IsNullOrEmpty(request.CategoryId))
            {
                var param = new GetCategoryBrowsingViewModelParam
                {
                    CategoryId           = request.CategoryId,
                    CategoryName         = string.Empty,
                    BaseUrl              = BaseUrl,
                    IsAllProducts        = false,
                    NumberOfItemsPerPage = SearchConfiguration.MaxItemsPerPage,
                    Page                 = CurrentPage,
                    SortBy               = SortBy,
                    SortDirection        = SortDirection,
                    InventoryLocationIds = await InventoryLocationProvider.GetInventoryLocationIdsForSearchAsync().ConfigureAwait(false),
                    SelectedFacets       = SelectedFacets,
                    CultureInfo          = ComposerContext.CultureInfo,
                };

                viewModel = await CategoryBrowsingViewService.GetCategoryBrowsingViewModelAsync(param).ConfigureAwait(false);
            }
            else
            {
                var searchCriteria = await BaseSearchCriteriaProvider.GetSearchCriteriaAsync(Keywords, BaseUrl, true, CurrentPage).ConfigureAwait(false);

                searchCriteria.SortBy        = SortBy;
                searchCriteria.SortDirection = SortDirection;
                searchCriteria.SelectedFacets.AddRange(SelectedFacets);

                viewModel = await SearchViewService.GetSearchViewModelAsync(searchCriteria).ConfigureAwait(false);
            }

            viewModel.ProductSearchResults.Facets = viewModel.ProductSearchResults.Facets.Where(f => !f.FieldName.StartsWith(SearchConfiguration.CategoryFacetFiledNamePrefix)).ToList();
            return(Ok(viewModel));
        }
예제 #12
0
        protected virtual List <string> GetLandingPageUrls(TreeNode <Category> startNode,
                                                           GetCategoryBrowsingViewModelParam param)
        {
            var urlStack    = new Stack <string>();
            var currentNode = startNode;

            while (currentNode != null && !IsCategoryFacetSystem(currentNode.Value, currentNode.GetLevel()))
            {
                var url = GetParentPageUrl(currentNode, param);
                urlStack.Push(url ?? String.Empty);

                currentNode = currentNode.Parent;
            }

            var list = new List <string>();

            while (urlStack.Count > 0)
            {
                list.Add(urlStack.Pop());
            }

            return(list);
        }
예제 #13
0
        private async Task <SearchCriteria> GetSearchCriteriaAsync(GetCategoryBrowsingViewModelParam param)
        {
            var criteria = new SearchCriteria
            {
                NumberOfItemsPerPage = SearchConfiguration.MaxItemsPerPage,
                IncludeFacets        = true,
                StartingIndex        = (param.Page - 1) * SearchConfiguration.MaxItemsPerPage, // The starting index is zero-based.
                SortBy        = param.SortBy,
                SortDirection = param.SortDirection,
                Page          = param.Page,
                BaseUrl       = param.BaseUrl,
                CultureInfo   = _context.CultureInfo,
                Scope         = _context.Scope
            };

            List <SearchFilter> selectedCategories = await GetSelectedCategoriesAsync(param).ConfigureAwait(false);

            List <SearchFilter> selectedFacets = param.SelectedFacets;

            criteria.SelectedFacets.AddRange(selectedCategories);
            criteria.SelectedFacets.AddRange(selectedFacets);

            return(criteria);
        }
예제 #14
0
        protected virtual async Task <List <TreeNode <Category> > > GetCategoryChildrenAsync(GetCategoryBrowsingViewModelParam param)
        {
            Tree <Category, string> tree = await CategoryRepository.GetCategoriesTreeAsync(new GetCategoriesParam
            {
                Scope = ComposerContext.Scope
            }).ConfigureAwait(false);

            return(tree[param.CategoryId].Children);
        }
예제 #15
0
        protected virtual async Task <ProductSearchResultsViewModel> GetProductSearchResultsAsync(GetCategoryBrowsingViewModelParam param)
        {
            var searchParam = new BrowsingSearchParam
            {
                Criteria          = await GetSearchCriteriaAsync(param).ConfigureAwait(false),
                CategoryId        = param.CategoryId,
                CategoryFilters   = await GetSelectedCategoriesAsync(param).ConfigureAwait(false),
                IsAllProductsPage = param.IsAllProducts
            };

            ProductSearchResultsViewModel model = await SearchAsync(searchParam).ConfigureAwait(false);

            return(model);
        }
예제 #16
0
        protected virtual async Task <List <ChildCategoryViewModel> > GetChildCategoriesAsync(GetCategoryBrowsingViewModelParam param)
        {
            List <TreeNode <Category> > children = await GetCategoryChildrenAsync(param).ConfigureAwait(false);

            return(children.Select(childCategory => CreateChildCategoryViewModel(childCategory.Value, param)).ToList());
        }
예제 #17
0
 private void BuildCategoryUrlsForTreeNode(GetCategoryBrowsingViewModelParam param, CategoryFacetValuesTreeNode node)
 {
     node.CategoryUrl = GetCategoryUrl(node.CategoryId, param);
     node.ChildNodes?.ForEach(childNode => BuildCategoryUrlsForTreeNode(param, childNode));
 }
예제 #18
0
        private ChildCategoryViewModel CreateChildCategoryViewModel(Category category, GetCategoryBrowsingViewModelParam param)
        {
            string title = category.DisplayName.GetLocalizedValue(_context.CultureInfo.Name);
            string url   = _categoryBrowsingUrlProvider.BuildCategoryBrowsingUrl(new BuildCategoryBrowsingUrlParam
            {
                CategoryId        = category.Id,
                CultureInfo       = _context.CultureInfo,
                BaseUrl           = param.BaseUrl,
                IsAllProductsPage = false
            });

            return(new ChildCategoryViewModel {
                Title = title, Url = url
            });
        }
예제 #19
0
        public virtual async Task <CategoryBrowsingViewModel> GetCategoryBrowsingViewModelAsync(GetCategoryBrowsingViewModelParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException(nameof(param));
            }
            if (param.CategoryId == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.CategoryId)), nameof(param));
            }
            if (param.SelectedFacets == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.SelectedFacets)), nameof(param));
            }

            var node = await GetCurrentCategoryNodeAsync(param).ConfigureAwait(false);

            var landingPageUrls = GetLandingPageUrls(node, param);

            var viewModel = new CategoryBrowsingViewModel
            {
                CategoryId           = param.CategoryId,
                CategoryName         = param.CategoryName,
                SelectedFacets       = await GetSelectedFacetsAsync(param).ConfigureAwait(false),
                ProductSearchResults = await GetProductSearchResultsAsync(param).ConfigureAwait(false),
                ChildCategories      = await GetChildCategoriesAsync(param).ConfigureAwait(false),
                LandingPageUrls      = landingPageUrls
            };

            return(viewModel);
        }
예제 #20
0
        public async Task <CategoryBrowsingViewModel> GetCategoryBrowsingViewModelAsync(GetCategoryBrowsingViewModelParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException("param");
            }
            if (param.CategoryId == null)
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("CategoryId"));
            }
            if (param.SelectedFacets == null)
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("SelectedFacets"));
            }

            var viewModel = new CategoryBrowsingViewModel
            {
                CategoryId           = param.CategoryId,
                CategoryName         = param.CategoryName,
                SelectedFacets       = await GetSelectedFacetsAsync(param).ConfigureAwait(false),
                ProductSearchResults = await GetProductSearchResultsAsync(param).ConfigureAwait(false),
                ChildCategories      = await GetChildCategoriesAsync(param).ConfigureAwait(false)
            };

            viewModel.Context["ProductSearchResults"] = viewModel.ProductSearchResults;
            viewModel.Context["ListName"]             = "Category Browsing";

            return(viewModel);
        }
예제 #21
0
        protected virtual async Task <List <ChildCategoryViewModel> > GetChildCategoriesAsync(GetCategoryBrowsingViewModelParam param)
        {
            List <TreeNode <Category> > children = await GetCategoryChildrenAsync(param).ConfigureAwait(false);

            //If the category has no URL, it probably means there is no item for it in the CMS yet...
            var childCategories = children
                                  .Select(childCategory => CreateChildCategoryViewModel(childCategory.Value, param))
                                  .Where(childCategory => !string.IsNullOrWhiteSpace(childCategory.Url)).ToList();

            return(childCategories);
        }
예제 #22
0
        public virtual async Task <CategoryBrowsingViewModel> GetCategoryBrowsingViewModelAsync(GetCategoryBrowsingViewModelParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException(nameof(param));
            }
            if (param.CategoryId == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.CategoryId)), nameof(param));
            }
            if (param.SelectedFacets == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.SelectedFacets)), nameof(param));
            }

            var node = await GetCurrentCategoryNodeAsync(param).ConfigureAwait(false);

            var landingPageUrls = GetLandingPageUrls(node, param);

            var viewModel = new CategoryBrowsingViewModel
            {
                CategoryId    = param.CategoryId,
                CategoryName  = param.CategoryName,
                FacetSettings = new FacetSettingsViewModel()
                {
                    SelectedFacets = await GetSelectedFacetsAsync(param).ConfigureAwait(false),
                },
                ProductSearchResults = await GetProductSearchResultsAsync(param).ConfigureAwait(false),
                LandingPageUrls      = landingPageUrls,
                ListName             = "Category Browsing"
            };

            viewModel.FacetSettings.CategoryFacetValuesTree = await BuildCategoryFacetValuesTree(viewModel.ProductSearchResults.Facets,
                                                                                                 viewModel.FacetSettings.SelectedFacets,
                                                                                                 viewModel.ProductSearchResults.CategoryFacetCounts).ConfigureAwait(false);

            if (viewModel.FacetSettings.CategoryFacetValuesTree != null)
            {
                var categoryRoot = CategoryRootNode(viewModel.FacetSettings.CategoryFacetValuesTree.ChildNodes, param.CategoryId);
                viewModel.FacetSettings.CategoryFacetValuesTree.TotalCount = categoryRoot != null ? categoryRoot.Quantity : 0;
                viewModel.FacetSettings.CategoryFacetValuesTree.ChildNodes = categoryRoot?.ChildNodes;
                viewModel.FacetSettings.CategoryFacetValuesTree.ChildNodes?.ForEach(childNode => BuildCategoryUrlsForTreeNode(param, childNode));
                viewModel.FacetSettings.CategoryFacetValuesTree.ChildNodes?.ForEach(childNode => CleanSiblingFacets(param, childNode));
                viewModel.FacetSettings.Context["CategoryFacetValuesTree"] = viewModel.FacetSettings.CategoryFacetValuesTree;
            }

            // Json context for Facets
            viewModel.FacetSettings.Context["SelectedFacets"]      = viewModel.FacetSettings.SelectedFacets;
            viewModel.FacetSettings.Context["Facets"]              = viewModel.ProductSearchResults.Facets.Where(f => !f.FieldName.StartsWith(SearchConfiguration.CategoryFacetFiledNamePrefix));
            viewModel.FacetSettings.Context["PromotedFacetValues"] = viewModel.ProductSearchResults.PromotedFacetValues;

            return(viewModel);
        }
예제 #23
0
        protected virtual ChildCategoryViewModel CreateChildCategoryViewModel(Category category, GetCategoryBrowsingViewModelParam param)
        {
            string title = category.DisplayName.GetLocalizedValue(ComposerContext.CultureInfo.Name);
            var    url   = GetCategoryUrl(category.Id, param);

            return(new ChildCategoryViewModel {
                Title = title, Url = url
            });
        }