diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ea588b..a6bdbee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,21 @@ name: "CI: Build and Test" on: + push: + branches: [main] + paths: + - "**.cs" + - "**.tsx" + - "**.js" + - "**.csproj" + - "**.props" + - "**.targets" + - "**.sln" + - "**/Client/**/*.json" pull_request: branches: [main] paths: + - ".github/workflows/ci.yml" - "**.cs" - "**.cshtml" - "**.tsx" @@ -29,10 +41,10 @@ jobs: DOTNET_NOLOGO: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: global-json-file: global.json diff --git a/Directory.Packages.props b/Directory.Packages.props index c68d9ca..56ef35c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,10 +7,10 @@ true - - - - + + + + diff --git a/examples/DancingGoat/$CDRepository/repository.config b/examples/DancingGoat/$CDRepository/repository.config deleted file mode 100644 index b764a63..0000000 --- a/examples/DancingGoat/$CDRepository/repository.config +++ /dev/null @@ -1,94 +0,0 @@ - - - - - CreateUpdate - - - - - - - - cms.class - cms.consent - cms.contenttype - cms.contentlanguage - cms.scheduledtask - cms.settingscategory - cms.settingskey - cms.user - cms.role - cms.channel - cms.websitechannel - cms.websitecaptchasettings - cms.contentitem - cms.pagetemplateconfiguration - - cms.headlesschannel - cms.headlessitem - - media.library - media.file - - om.activitytype - om.recipientlist - om.contactgroup - cms.formclass - cms.formfeaturedfield - - emaillibrary.emailchannel - emaillibrary.emailchannelsender - emaillibrary.emailconfiguration - emaillibrary.emailtemplatecontenttype - emaillibrary.recipientlistsettings - emaillibrary.sendconfiguration - emaillibrary.emailtemplate - - ma.automationprocess - ma.automationstep - ma.automationaction - ma.automationtemplate - cms.objectworkflowtrigger - cms.workflowtransition - - cms.webpageitem - cms.webpageurlpath - cms.webpageformerurlpath - om.trackedwebsite - cms.form - - cms.contentworkflow - cms.contentworkflowcontenttype - cms.contentworkflowstep - cms.contentworkflowsteprole - - - - - - - - - - cms.contentitemcommondata - - - - - - - - \ No newline at end of file diff --git a/examples/DancingGoat/.config/dotnet-tools.json b/examples/DancingGoat/.config/dotnet-tools.json index 62b7618..d6bdc96 100644 --- a/examples/DancingGoat/.config/dotnet-tools.json +++ b/examples/DancingGoat/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "kentico.xperience.dbmanager": { - "version": "28.3.1", + "version": "29.5.3", "commands": [ "kentico-xperience-dbmanager" ] diff --git a/examples/DancingGoat/AdminComponents/Apps/SampleDataGenerator/SampleDataGeneratorApplication.cs b/examples/DancingGoat/AdminComponents/Apps/SampleDataGenerator/SampleDataGeneratorApplication.cs index f4435ee..92a0588 100644 --- a/examples/DancingGoat/AdminComponents/Apps/SampleDataGenerator/SampleDataGeneratorApplication.cs +++ b/examples/DancingGoat/AdminComponents/Apps/SampleDataGenerator/SampleDataGeneratorApplication.cs @@ -41,9 +41,9 @@ public class SampleDataGeneratorApplication : OverviewPageBase private readonly IFormBuilderConfigurationSerializer formBuilderConfigurationSerializer; private readonly IEventLogService eventLogService; private readonly IInfoProvider consentInfoProvider; - private readonly IBizFormInfoProvider bizFormInfoProvider; - private readonly IContactGroupInfoProvider contactGroupInfoProvider; - private readonly ISettingsKeyInfoProvider settingsKeyInfoProvider; + private readonly IInfoProvider bizFormInfoProvider; + private readonly IInfoProvider contactGroupInfoProvider; + private readonly IInfoProvider settingsKeyInfoProvider; private readonly IInfoProvider websiteChannelInfoProvider; @@ -61,9 +61,9 @@ public SampleDataGeneratorApplication( IFormBuilderConfigurationSerializer formBuilderConfigurationSerializer, IEventLogService eventLogService, IInfoProvider consentInfoProvider, - IBizFormInfoProvider bizFormInfoProvider, - IContactGroupInfoProvider contactGroupInfoProvider, - ISettingsKeyInfoProvider settingsKeyInfoProvider, + IInfoProvider bizFormInfoProvider, + IInfoProvider contactGroupInfoProvider, + IInfoProvider settingsKeyInfoProvider, IInfoProvider websiteChannelInfoProvider) { this.formBuilderConfigurationSerializer = formBuilderConfigurationSerializer; diff --git a/examples/DancingGoat/Components/ViewComponents/Articles/ArticlesViewComponent.cs b/examples/DancingGoat/Components/ViewComponents/Articles/ArticlesViewComponent.cs index 757ced9..3675cda 100644 --- a/examples/DancingGoat/Components/ViewComponents/Articles/ArticlesViewComponent.cs +++ b/examples/DancingGoat/Components/ViewComponents/Articles/ArticlesViewComponent.cs @@ -43,7 +43,7 @@ public async Task InvokeAsync(WebPageRelatedItem articl { var languageName = currentLanguageRetriever.Get(); - var articlesSection = await articlesSectionRepository.GetArticlesSection(articlesSectionItem.WebPageGuid, languageName); + var articlesSection = await articlesSectionRepository.GetArticlesSection(articlesSectionItem.WebPageGuid, languageName, HttpContext.RequestAborted); if (articlesSection == null) { return View("~/Components/ViewComponents/Articles/Default.cshtml", ArticlesSectionViewModel.GetViewModel(null, Enumerable.Empty(), string.Empty)); @@ -55,11 +55,11 @@ public async Task InvokeAsync(WebPageRelatedItem articl var models = new List(); foreach (var article in articlePages) { - var model = await ArticleViewModel.GetViewModel(article, urlRetriever, languageName); + var model = await ArticleViewModel.GetViewModel(article, urlRetriever, languageName, HttpContext.RequestAborted); models.Add(model); } - var url = (await urlRetriever.Retrieve(articlesSection, languageName)).RelativePath; + var url = (await urlRetriever.Retrieve(articlesSection, languageName, HttpContext.RequestAborted)).RelativePath; var viewModel = ArticlesSectionViewModel.GetViewModel(articlesSection, models, url); diff --git a/examples/DancingGoat/Components/ViewComponents/Cafe/Default.cshtml b/examples/DancingGoat/Components/ViewComponents/Cafe/Default.cshtml index 144930d..adf016c 100644 --- a/examples/DancingGoat/Components/ViewComponents/Cafe/Default.cshtml +++ b/examples/DancingGoat/Components/ViewComponents/Cafe/Default.cshtml @@ -8,13 +8,11 @@ } else { - -

@Model.Name

- - @if (!string.IsNullOrEmpty(Model.PhotoPath)) - { - @Model.PhotoShortDescription - } -
+

@Model.Name

+ + @if (!string.IsNullOrEmpty(Model.PhotoPath)) + { + @Model.PhotoShortDescription + } } \ No newline at end of file diff --git a/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewComponent.cs b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewComponent.cs index 2babe51..21e673c 100644 --- a/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewComponent.cs +++ b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewComponent.cs @@ -1,8 +1,13 @@ using System.Collections.Generic; -using System.Linq; +using System.Threading.Tasks; +using System.Threading; + +using CMS.Websites; using DancingGoat.Models; +using Kentico.Content.Web.Mvc.Routing; + using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewComponents; @@ -13,9 +18,37 @@ namespace DancingGoat.ViewComponents /// public class CafeCardSectionViewComponent : ViewComponent { - public ViewViewComponentResult Invoke(IEnumerable cafes) + private readonly ContactsPageRepository contactsPageRepository; + private readonly IWebPageUrlRetriever webPageUrlRetriever; + private readonly IPreferredLanguageRetriever currentLanguageRetriever; + + + public CafeCardSectionViewComponent(IPreferredLanguageRetriever currentLanguageRetriever, ContactsPageRepository contactsPageRepository, IWebPageUrlRetriever webPageUrlRetriever) + { + this.currentLanguageRetriever = currentLanguageRetriever; + this.contactsPageRepository = contactsPageRepository; + this.webPageUrlRetriever = webPageUrlRetriever; + } + + + public async Task InvokeAsync(IEnumerable cafes) { - return View("~/Components/ViewComponents/CafeCardSection/Default.cshtml", cafes.Take(3)); + string languageName = currentLanguageRetriever.Get(); + string contactsPagePath = await GetContactsPagePath(languageName, HttpContext.RequestAborted); + var model = new CafeCardSectionViewModel(cafes, contactsPagePath); + + return View("~/Components/ViewComponents/CafeCardSection/Default.cshtml", model); + } + + + private async Task GetContactsPagePath(string languageName, CancellationToken cancellationToken) + { + const string CONTACTS_PAGE_TREE_PATH = "/Contacts"; + + var contactsPage = await contactsPageRepository.GetContactsPage(CONTACTS_PAGE_TREE_PATH, languageName, cancellationToken); + var url = await webPageUrlRetriever.Retrieve(contactsPage, cancellationToken); + + return url.RelativePath; } } } diff --git a/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewModel.cs b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewModel.cs new file mode 100644 index 0000000..b913e19 --- /dev/null +++ b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/CafeCardSectionViewModel.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +using DancingGoat.Models; + +namespace DancingGoat.ViewComponents +{ + public record CafeCardSectionViewModel(IEnumerable Cafes, string ContactsPagePath) + { + } +} diff --git a/examples/DancingGoat/Components/ViewComponents/CafeCardSection/Default.cshtml b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/Default.cshtml index 4d3463d..74b7e0d 100644 --- a/examples/DancingGoat/Components/ViewComponents/CafeCardSection/Default.cshtml +++ b/examples/DancingGoat/Components/ViewComponents/CafeCardSection/Default.cshtml @@ -1,15 +1,17 @@ -@using DancingGoat.Models -@model IEnumerable +@using DancingGoat.ViewComponents +@model CafeCardSectionViewModel

@HtmlLocalizer["Taste our coffee"]

- @foreach (var cafe in Model) + @foreach (var cafe in Model.Cafes) {
- + + +
}
diff --git a/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs b/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs index 5aba6e7..dc70e54 100644 --- a/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs +++ b/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs @@ -54,7 +54,7 @@ public async Task InvokeAsync() { ConsentShortText = (await consent.GetConsentTextAsync(currentLanguage)).ShortText, ReturnPageUrl = webPageDataContextRetriever.TryRetrieve(out var currentWebPageContext) - ? (await urlRetriever.Retrieve(currentWebPageContext.WebPage.WebPageItemID, currentLanguage)).RelativePath + ? (await urlRetriever.Retrieve(currentWebPageContext.WebPage.WebPageItemID, currentLanguage, cancellationToken: HttpContext.RequestAborted)).RelativePath : (HttpContext.Request.PathBase + HttpContext.Request.Path).Value }; @@ -62,7 +62,7 @@ public async Task InvokeAsync() if ((contact != null) && consentAgreementService.IsAgreed(contact, consent)) { consentModel.IsConsentAgreed = true; - consentModel.PrivacyPageUrl = Url.Content((await urlRetriever.Retrieve(PrivacyPageConstants.PRIVACY_PAGE_TREE_PATH, websiteChannelContext.WebsiteChannelName, currentLanguage)).RelativePath); + consentModel.PrivacyPageUrl = Url.Content((await urlRetriever.Retrieve(PrivacyPageConstants.PRIVACY_PAGE_TREE_PATH, websiteChannelContext.WebsiteChannelName, currentLanguage, cancellationToken: HttpContext.RequestAborted)).RelativePath); } return View("~/Components/ViewComponents/TrackingConsent/Default.cshtml", consentModel); diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs index 4089355..7c37d68 100644 --- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs +++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs @@ -21,7 +21,7 @@ public class ProductCardListViewModel /// /// Collection of products. /// Hydrated ViewModel. - public static ProductCardListViewModel GetViewModel(IEnumerable products) + public static ProductCardListViewModel GetViewModel(IEnumerable products) { var productModels = new List(); diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs index 009ac5b..cf4a8d3 100644 --- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs +++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs @@ -2,8 +2,6 @@ using CMS.ContentEngine; -using DancingGoat.Models; - using Kentico.PageBuilder.Web.Mvc; using Kentico.Xperience.Admin.Base.FormAnnotations; @@ -17,7 +15,7 @@ public class ProductCardProperties : IWidgetProperties /// /// Selected products. /// - [ContentItemSelectorComponent(Coffee.CONTENT_TYPE_NAME, Label = "Selected products", Order = 1)] + [ContentItemSelectorComponent(typeof(ProductCardSchemaFilter), Label = "Selected products", Order = 1)] public IEnumerable SelectedProducts { get; set; } = new List(); } } diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs new file mode 100644 index 0000000..9f36e5f --- /dev/null +++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +using DancingGoat.Models; + +using Kentico.Xperience.Admin.Base.FormAnnotations; + +namespace DancingGoat.Widgets +{ + /// + /// Product card widget filter for content item selector. + /// + public class ProductCardSchemaFilter : IReusableFieldSchemasFilter + { + /// + IEnumerable IReusableFieldSchemasFilter.AllowedSchemaNames => new List { IProductFields.REUSABLE_FIELD_SCHEMA_NAME }; + } +} diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs index ec7f25f..19936a5 100644 --- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs +++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs @@ -32,7 +32,7 @@ public class ProductCardViewModel /// /// Product. /// Hydrated ViewModel. - public static ProductCardViewModel GetViewModel(Coffee product) + public static ProductCardViewModel GetViewModel(IProductFields product) { if (product == null) { @@ -41,9 +41,9 @@ public static ProductCardViewModel GetViewModel(Coffee product) return new ProductCardViewModel { - Heading = product.CoffeeName, - ImagePath = (product.CoffeeImage.FirstOrDefault())?.ImageFile.Url, - Text = product.CoffeeShortDescription + Heading = product.ProductFieldsName, + ImagePath = product.ProductFieldsImage.FirstOrDefault()?.ImageFile.Url, + Text = product.ProductFieldsShortDescription }; } } diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs index 0a0429a..04a3e77 100644 --- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs +++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Threading.Tasks; +using CMS.ContentEngine; + using DancingGoat.Models; using DancingGoat.Widgets; @@ -26,7 +27,7 @@ public class ProductCardWidgetViewComponent : ViewComponent public const string IDENTIFIER = "DancingGoat.LandingPage.ProductCardWidget"; - private readonly CoffeeRepository repository; + private readonly ProductRepository repository; private readonly IPreferredLanguageRetriever currentLanguageRetriever; @@ -35,7 +36,7 @@ public class ProductCardWidgetViewComponent : ViewComponent /// /// Repository for retrieving products. /// Retrieves preferred language name for the current request. Takes language fallback into account. - public ProductCardWidgetViewComponent(CoffeeRepository repository, IPreferredLanguageRetriever currentLanguageRetriever) + public ProductCardWidgetViewComponent(ProductRepository repository, IPreferredLanguageRetriever currentLanguageRetriever) { this.repository = repository; this.currentLanguageRetriever = currentLanguageRetriever; @@ -46,8 +47,8 @@ public async Task InvokeAsync(ProductCardProperties pro { var languageName = currentLanguageRetriever.Get(); var selectedProductGuids = properties.SelectedProducts.Select(i => i.Identifier).ToList(); - IEnumerable products = (await repository.GetCoffees(selectedProductGuids, languageName)) - .OrderBy(p => selectedProductGuids.IndexOf(p.SystemFields.ContentItemGUID)); + var products = (await repository.GetProducts(selectedProductGuids, languageName)) + .OrderBy(p => selectedProductGuids.IndexOf(((IContentItemFieldsSource)p).SystemFields.ContentItemGUID)); var model = ProductCardListViewModel.GetViewModel(products); return View("~/Components/Widgets/ProductCardWidget/_ProductCardWidget.cshtml", model); diff --git a/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs b/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs new file mode 100644 index 0000000..75421af --- /dev/null +++ b/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Mvc; + +using CMS.ContentEngine; + +using Kentico.Content.Web.Mvc; +using Kentico.Content.Web.Mvc.Routing; + +using DancingGoat; +using DancingGoat.Controllers; +using DancingGoat.Models; + +[assembly: RegisterWebPageRoute(CoffeePage.CONTENT_TYPE_NAME, typeof(DancingGoatCoffeeController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME }, ActionName = nameof(DancingGoatCoffeeController.Detail))] + +namespace DancingGoat.Controllers +{ + public class DancingGoatCoffeeController : Controller + { + private readonly ProductPageRepository productPageRepository; + private readonly IWebPageDataContextRetriever webPageDataContextRetriever; + private readonly IPreferredLanguageRetriever currentLanguageRetriever; + private readonly ITaxonomyRetriever taxonomyRetriever; + + + public DancingGoatCoffeeController(ProductPageRepository productPageRepository, + IWebPageDataContextRetriever webPageDataContextRetriever, + IPreferredLanguageRetriever currentLanguageRetriever, + ITaxonomyRetriever taxonomyRetriever) + { + this.productPageRepository = productPageRepository; + this.webPageDataContextRetriever = webPageDataContextRetriever; + this.currentLanguageRetriever = currentLanguageRetriever; + this.taxonomyRetriever = taxonomyRetriever; + } + + + public async Task Detail() + { + var languageName = currentLanguageRetriever.Get(); + var webPageItemId = webPageDataContextRetriever.Retrieve().WebPage.WebPageItemID; + + var coffee = await productPageRepository.GetProduct(CoffeePage.CONTENT_TYPE_NAME, webPageItemId, languageName, cancellationToken: HttpContext.RequestAborted); + + return View(await CoffeeDetailViewModel.GetViewModel(coffee, languageName, taxonomyRetriever)); + } + } +} diff --git a/examples/DancingGoat/Controllers/DancingGoatContactsController.cs b/examples/DancingGoat/Controllers/DancingGoatContactsController.cs index 24e2191..ceadd78 100644 --- a/examples/DancingGoat/Controllers/DancingGoatContactsController.cs +++ b/examples/DancingGoat/Controllers/DancingGoatContactsController.cs @@ -51,19 +51,22 @@ public async Task Index(CancellationToken cancellationToken) private async Task GetIndexViewModel(ContactsPage contactsPage, CancellationToken cancellationToken) { var languageName = currentLanguageRetriever.Get(); - var cafes = await cafeRepository.GetCompanyCafes(4, languageName, cancellationToken); + var cafes = (await cafeRepository.GetCafes(0, languageName, cancellationToken)).ToList(); + var companyCafes = cafes.Where(c => c.CafeIsCompanyCafe).OrderBy(c => c.CafeName); + var partnerCafes = cafes.Where(c => !c.CafeIsCompanyCafe).OrderBy(c => c.CafeCity); var contact = await contactRepository.GetContact(languageName, HttpContext.RequestAborted); return new ContactsIndexViewModel { CompanyContact = ContactViewModel.GetViewModel(contact), - CompanyCafes = GetCompanyCafesModel(cafes), + CompanyCafes = GetCafesModel(companyCafes), + PartnerCafes = GetCafesModel(partnerCafes), WebPage = contactsPage }; } - private List GetCompanyCafesModel(IEnumerable cafes) + private List GetCafesModel(IEnumerable cafes) { return cafes.Select(cafe => CafeViewModel.GetViewModel(cafe)).ToList(); } diff --git a/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs b/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs new file mode 100644 index 0000000..be3f1a4 --- /dev/null +++ b/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Mvc; + +using CMS.ContentEngine; + +using Kentico.Content.Web.Mvc; +using Kentico.Content.Web.Mvc.Routing; + +using DancingGoat; +using DancingGoat.Controllers; +using DancingGoat.Models; + +[assembly: RegisterWebPageRoute(GrinderPage.CONTENT_TYPE_NAME, typeof(DancingGoatGrinderController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME }, ActionName = nameof(DancingGoatGrinderController.Detail))] + +namespace DancingGoat.Controllers +{ + public class DancingGoatGrinderController : Controller + { + private readonly ProductPageRepository productPageRepository; + private readonly IWebPageDataContextRetriever webPageDataContextRetriever; + private readonly IPreferredLanguageRetriever currentLanguageRetriever; + private readonly ITaxonomyRetriever taxonomyRetriever; + + + public DancingGoatGrinderController(ProductPageRepository productPageRepository, + IWebPageDataContextRetriever webPageDataContextRetriever, + IPreferredLanguageRetriever currentLanguageRetriever, + ITaxonomyRetriever taxonomyRetriever) + { + this.productPageRepository = productPageRepository; + this.webPageDataContextRetriever = webPageDataContextRetriever; + this.currentLanguageRetriever = currentLanguageRetriever; + this.taxonomyRetriever = taxonomyRetriever; + } + + + public async Task Detail() + { + var languageName = currentLanguageRetriever.Get(); + var webPageItemId = webPageDataContextRetriever.Retrieve().WebPage.WebPageItemID; + + var grinder = await productPageRepository.GetProduct(GrinderPage.CONTENT_TYPE_NAME, webPageItemId, languageName, cancellationToken: HttpContext.RequestAborted); + + return View(await GrinderDetailViewModel.GetViewModel(grinder, languageName, taxonomyRetriever)); + } + } +} diff --git a/examples/DancingGoat/Controllers/DancingGoatProductController.cs b/examples/DancingGoat/Controllers/DancingGoatProductController.cs new file mode 100644 index 0000000..511c03d --- /dev/null +++ b/examples/DancingGoat/Controllers/DancingGoatProductController.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using CMS.ContentEngine; +using CMS.Websites; + +using DancingGoat; +using DancingGoat.Controllers; +using DancingGoat.Models; + +using Kentico.Content.Web.Mvc; +using Kentico.Content.Web.Mvc.Routing; + +using Microsoft.AspNetCore.Mvc; + +[assembly: RegisterWebPageRoute(ProductsSection.CONTENT_TYPE_NAME, typeof(DancingGoatProductController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME })] + +namespace DancingGoat.Controllers +{ + public class DancingGoatProductController : Controller + { + private readonly ProductSectionRepository productSectionRepository; + private readonly ProductPageRepository productPageRepository; + private readonly ProductRepository productRepository; + private readonly ITaxonomyRetriever taxonomyRetriever; + private readonly IWebPageUrlRetriever urlRetriever; + private readonly IWebPageDataContextRetriever webPageDataContextRetriever; + private readonly IPreferredLanguageRetriever currentLanguageRetriever; + + + public DancingGoatProductController( + ProductSectionRepository productSectionRepository, + ProductPageRepository productPageRepository, + ProductRepository productRepository, + IWebPageUrlRetriever urlRetriever, + IPreferredLanguageRetriever currentLanguageRetriever, + IWebPageDataContextRetriever webPageDataContextRetriever, + ITaxonomyRetriever taxonomyRetriever) + { + this.productSectionRepository = productSectionRepository; + this.productPageRepository = productPageRepository; + this.productRepository = productRepository; + this.urlRetriever = urlRetriever; + this.webPageDataContextRetriever = webPageDataContextRetriever; + this.currentLanguageRetriever = currentLanguageRetriever; + this.taxonomyRetriever = taxonomyRetriever; + } + + + public async Task Index() + { + var languageName = currentLanguageRetriever.Get(); + var webPage = webPageDataContextRetriever.Retrieve().WebPage; + var productsSection = await productSectionRepository.GetProductsSection(webPage.WebPageItemID, languageName, HttpContext.RequestAborted); + + var products = await GetProducts(languageName, productsSection); + + var taxonomies = new Dictionary(); + var taxonomyNames = new List { "CoffeeProcessing", "CoffeeTastes", "GrinderManufacturer", "GrinderType" }; + foreach (var taxonomyName in taxonomyNames) + { + var taxonomy = await taxonomyRetriever.RetrieveTaxonomy(taxonomyName, languageName); + if (taxonomy.Tags.Any()) + { + taxonomies.Add(taxonomyName, TaxonomyViewModel.GetViewModel(taxonomy)); + } + } + + var listModel = new ProductListViewModel(products, taxonomies); + + return View(listModel); + } + + + [HttpPost($"{{{WebPageRoutingOptions.LANGUAGE_ROUTE_VALUE_KEY}}}/{{controller}}/{{action}}")] + [ValidateAntiForgeryToken] + public async Task Filter(IDictionary filter) + { + var languageName = currentLanguageRetriever.Get(); + var webPage = webPageDataContextRetriever.Retrieve().WebPage; + var productsSection = await productSectionRepository.GetProductsSection(webPage.WebPageItemID, languageName, HttpContext.RequestAborted); + + var products = await GetProducts(languageName, productsSection, filter); + return PartialView("ProductsList", products); + } + + + private async Task> GetProducts(string languageName, ProductsSection productsSection, IDictionary filter = null) + { + var products = await productRepository.GetProducts(languageName, filter ?? new Dictionary(), cancellationToken: HttpContext.RequestAborted); + var productPages = await productPageRepository.GetProducts(productsSection.SystemFields.WebPageItemTreePath, languageName, products, cancellationToken: HttpContext.RequestAborted); + + return productPages.Select(productPage => ProductListItemViewModel.GetViewModel(productPage, urlRetriever, languageName).Result); + } + } +} diff --git a/examples/DancingGoat/Controllers/SiteMapController.cs b/examples/DancingGoat/Controllers/SiteMapController.cs new file mode 100644 index 0000000..28d5fdc --- /dev/null +++ b/examples/DancingGoat/Controllers/SiteMapController.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Xml; + +using CMS.ContentEngine; +using CMS.DataEngine; +using CMS.Websites; + +using DancingGoat.Models; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.AspNetCore.Mvc; + +namespace DancingGoat.Controllers +{ + /// + /// Controller for generating a sitemap. + /// + public class SiteMapController : Controller + { + private const string XML_TYPE = "application/xml"; + + private readonly IContentQueryExecutor contentQueryExecutor; + private readonly IWebPageUrlRetriever urlRetriever; + private readonly IInfoProvider contentLanguageProvider; + + + /// + /// Initializes a new instance of the class. + /// + public SiteMapController(IContentQueryExecutor contentQueryExecutor, IWebPageUrlRetriever urlRetriever, IInfoProvider contentLanguageProvider) + { + this.contentQueryExecutor = contentQueryExecutor; + this.urlRetriever = urlRetriever; + this.contentLanguageProvider = contentLanguageProvider; + } + + + [HttpGet] + [Route("/sitemap.xml")] + public async Task Index() + { + var options = new ContentQueryExecutionOptions + { + ForPreview = false, + IncludeSecuredItems = false + }; + + var relativeUrls = new List(); + + foreach (var language in contentLanguageProvider.Get().OrderByDescending(i => i.ContentLanguageIsDefault)) + { + var builder = new ContentItemQueryBuilder().ForContentTypes(p => p.OfReusableSchema("SEOFields").ForWebsite()) + .InLanguage(language.ContentLanguageName, false) + .Parameters(p => p.Columns(nameof(IWebPageContentQueryDataContainer.WebPageItemID)) + .Where(w => w.WhereTrue(nameof(ISEOFields.SEOFieldsAllowSearchIndexing)))); + + var pageIdentifiers = await contentQueryExecutor.GetWebPageResult(builder, i => i.WebPageItemID, options, HttpContext.RequestAborted); + var languageUrls = await GetWebPageRelativeUrls(pageIdentifiers, language.ContentLanguageName); + + relativeUrls.AddRange(languageUrls); + } + + var absoluteUrls = GetAbsoluteUrls(relativeUrls); + var document = GetSitemap(absoluteUrls); + + return Content(document.OuterXml, XML_TYPE); + } + + + private async Task> GetWebPageRelativeUrls(IEnumerable pageIdentifiers, string languageName) + { + var relativeUrls = new List(); + + foreach (var pageIdentifier in pageIdentifiers) + { + var webPageUrl = await urlRetriever.Retrieve(pageIdentifier, languageName, false, HttpContext.RequestAborted); + relativeUrls.Add(webPageUrl.RelativePath.TrimStart('~')); + } + + return relativeUrls; + } + + + private IEnumerable GetAbsoluteUrls(IEnumerable relativeUrls) + { + var request = HttpContext.Request; + + return relativeUrls.Select(i => UriHelper.BuildAbsolute(request.Scheme, request.Host, path: i)).OrderBy(i => i); + } + + + private static XmlDocument GetSitemap(IEnumerable urls) + { + var document = new XmlDocument(); + + var urlSet = document.CreateElement("urlset"); + urlSet.SetAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"); + + foreach (var url in urls) + { + var element = document.CreateElement("url"); + var location = document.CreateElement("loc"); + location.InnerText = url; + + element.AppendChild(location); + urlSet.AppendChild(element); + } + + document.AppendChild(urlSet); + + return document; + } + } +} diff --git a/examples/DancingGoat/DancingGoatConstants.cs b/examples/DancingGoat/DancingGoatConstants.cs index ad53549..774b6b1 100644 --- a/examples/DancingGoat/DancingGoatConstants.cs +++ b/examples/DancingGoat/DancingGoatConstants.cs @@ -8,7 +8,7 @@ internal static class DancingGoatConstants /// The constraint ensures that broken URLs lead to a "404 page not found" page and are not handled by a controller dedicated to the component or /// to a page handled by the content tree-based router (which would lead to an exception). /// - public const string CONSTRAINT_FOR_NON_ROUTER_PAGE_CONTROLLERS = "Account|Consent"; + public const string CONSTRAINT_FOR_NON_ROUTER_PAGE_CONTROLLERS = "Account|Consent|SiteMap"; public const string DEFAULT_ROUTE_NAME = "default"; diff --git a/examples/DancingGoat/Data/Template.zip b/examples/DancingGoat/Data/Template.zip index 56ee6da..2c7f8f3 100644 Binary files a/examples/DancingGoat/Data/Template.zip and b/examples/DancingGoat/Data/Template.zip differ diff --git a/examples/DancingGoat/Export-DeploymentPackage.ps1 b/examples/DancingGoat/Export-DeploymentPackage.ps1 deleted file mode 100644 index 2120347..0000000 --- a/examples/DancingGoat/Export-DeploymentPackage.ps1 +++ /dev/null @@ -1,104 +0,0 @@ -<# -.Synopsis - Creates a deployment package for uploading to the Xperience Cloud environment. -#> -[CmdletBinding()] -param ( - # Output path for exported deployment package. - [Parameter(Mandatory = $false)] - [string]$OutputPackagePath = "./DeploymentPackage.zip", - - # The name of the main web application assembly used as the starting point by the Xperience Cloud. - [Parameter(Mandatory = $true)] - [string]$AssemblyName, - - # If present, the custom build number won't be used as a "Product version" suffix in the format yyyyMMddHHmm. - [switch]$KeepProductVersion, - - # Mode in which the storage assets are deployed, if present. - [ValidateSet("Create", "CreateUpdate")] - [String]$StorageAssetsDeploymentMode = "Create" -) -$ErrorActionPreference = "Stop" - -$OutputFolderPath = "./bin/CloudDeployment/" -$MetadataFilePath = Join-Path $OutputFolderPath "cloud-metadata.json" -$CDRepositoryFolderPath = "./`$CDRepository" -$StorageAssetsFolderName = "`$StorageAssets" -$BuildNumber = (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmm") - -# Remove previously published website -Remove-Item -Recurse -Force $OutputFolderPath -ErrorAction SilentlyContinue - -# Publish the application in the 'Release' mode -$PublishCommand = "dotnet publish --nologo -c Release -o $OutputFolderPath" - -if (!$KeepProductVersion) { - $PublishCommand += " --version-suffix $BuildNumber" -} - -Invoke-Expression $PublishCommand - -if ($LASTEXITCODE -ne 0) { - throw "Publishing the website failed." -} - -# Get CD repositories paths -$LocalCDRepositoryPath = Join-Path (Resolve-Path .) $CDRepositoryFolderPath -$OutputCDRepositoryPath = Join-Path $OutputFolderPath $CDRepositoryFolderPath - -# Check for non-existing or empty CD repository which could corrupt the database -if (-not (Test-Path $LocalCDRepositoryPath) -or (@(Get-ChildItem -Path $LocalCDRepositoryPath -Directory).Count -le 0)) { - throw "Cannot detect CD repository on path '$LocalCDRepositoryPath'. Make sure to run 'dotnet run --kxp-cd-store --repository-path ""```$CDRepository""' before 'Export-DeploymentPackage.ps1'." -} - -# Copy content of the CD repository to the output folder -Copy-Item -Force -Recurse "$LocalCDRepositoryPath/*" -Destination $OutputCDRepositoryPath - -# Get storage assets paths -$LocalStorageAssetsPath = Join-Path (Resolve-Path .) $StorageAssetsFolderName -$OutputStorageAssetsPath = Join-Path $OutputFolderPath $StorageAssetsFolderName - -if (Test-Path $LocalStorageAssetsPath) { - # Check if storage asset top-level directories have valid names - Get-ChildItem -Path $LocalStorageAssetsPath | % { - if ($_.Name -cnotmatch "^[a-z0-9](?!.*--)[a-z0-9-]{1,61}[a-z0-9]$") { - throw "Storage asset directory '$($_.FullName)' does not have a valid name. Top level storage asset directories must have names that are 3-63 characters long and contain only lowercase letters, numbers or dashes (-). Every dash symbol must be surrounded by letters or numbers." - } - } - - # Copy storage assets to the output folder - New-Item -Force -ItemType Directory $OutputStorageAssetsPath | Out-Null - Copy-Item -Force -Recurse "$LocalStorageAssetsPath/*" -Destination $OutputStorageAssetsPath - - # Deployed assets need to have lowercase names - Get-ChildItem -Path $OutputStorageAssetsPath -Recurse | % { - $lowercasedAssetName = $_.Name.ToLowerInvariant() - - if ($_.Name -cne $lowercasedAssetName) { - Rename-Item -Force $_.FullName "$($_.Name).tmp" - Rename-Item -Force "$($_.FullName).tmp" $lowercasedAssetName - } - } -} - -$AssemblyPath = Join-Path $OutputFolderPath "$AssemblyName.dll" -Resolve -$PackageMetadata = @{ - AssemblyName = $AssemblyName - Version = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($AssemblyPath).ProductVersion -} - -# Add necessary metadata if storage assets folder has been exported as well -if (Test-Path $OutputStorageAssetsPath) { - $PackageMetadata.Add("StorageAssetsDirectory", $StorageAssetsFolderName) - $PackageMetadata.Add("StorageAssetsDeploymentMode", $StorageAssetsDeploymentMode) -} - -# Create all necessary metadata for cloud-based package deployment -$PackageMetadata | ConvertTo-Json -Depth 2 | Set-Content $MetadataFilePath -Encoding utf8 - -# Create a deployment package -if (Test-Path -Path $OutputPackagePath -PathType Container) { - $OutputPackagePath = Join-Path -Path $OutputPackagePath -ChildPath "./DeploymentPackage.zip" -} -Compress-Archive -Force -Path "$OutputFolderPath/*" -DestinationPath $OutputPackagePath \ No newline at end of file diff --git a/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentContactGroupGenerator.cs b/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentContactGroupGenerator.cs index f2ec24a..0150305 100644 --- a/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentContactGroupGenerator.cs +++ b/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentContactGroupGenerator.cs @@ -1,4 +1,5 @@ using CMS.ContactManagement; +using CMS.DataEngine; using CMS.MacroEngine; using CMS.Membership; @@ -9,14 +10,14 @@ public class FormContactGroupGenerator private const string CONTACT_GROUP_DISPLAY_NAME = "Coffee samples applicants"; private const string CONTACT_GROUP_NAME = "CoffeeSamplesApplicants"; - private readonly IContactGroupInfoProvider contactGroupInfoProvider; + private readonly IInfoProvider contactGroupInfoProvider; /// /// Initializes a new instance of the class. /// /// Contact group info provider. - public FormContactGroupGenerator(IContactGroupInfoProvider contactGroupInfoProvider) + public FormContactGroupGenerator(IInfoProvider contactGroupInfoProvider) { this.contactGroupInfoProvider = contactGroupInfoProvider; } diff --git a/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentGenerator.cs b/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentGenerator.cs index 6d29a93..305093a 100644 --- a/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentGenerator.cs +++ b/examples/DancingGoat/Helpers/Generators/DataProtection/FormConsentGenerator.cs @@ -29,7 +29,7 @@ public class FormConsentGenerator private readonly IFormBuilderConfigurationSerializer formBuilderConfigurationSerializer; private readonly IInfoProvider consentInfoProvider; - private readonly IBizFormInfoProvider bizFormInfoProvider; + private readonly IInfoProvider bizFormInfoProvider; /// @@ -41,7 +41,7 @@ public class FormConsentGenerator public FormConsentGenerator( IFormBuilderConfigurationSerializer formBuilderConfigurationSerializer, IInfoProvider consentInfoProvider, - IBizFormInfoProvider bizFormInfoProvider) + IInfoProvider bizFormInfoProvider) { this.formBuilderConfigurationSerializer = formBuilderConfigurationSerializer; this.consentInfoProvider = consentInfoProvider; diff --git a/examples/DancingGoat/Models/ContentRepositoryBase.cs b/examples/DancingGoat/Models/ContentRepositoryBase.cs index f00723e..f18e177 100644 --- a/examples/DancingGoat/Models/ContentRepositoryBase.cs +++ b/examples/DancingGoat/Models/ContentRepositoryBase.cs @@ -6,11 +6,13 @@ using CMS.ContentEngine; using CMS.Helpers; -using CMS.Websites; using CMS.Websites.Routing; namespace DancingGoat.Models { + /// + /// Shared implementation for content type repositories. + /// public abstract class ContentRepositoryBase { /// @@ -20,7 +22,6 @@ public abstract class ContentRepositoryBase private readonly IContentQueryExecutor executor; - private readonly IWebPageQueryResultMapper mapper; private readonly IProgressiveCache cache; @@ -29,13 +30,11 @@ public abstract class ContentRepositoryBase /// /// Website channel context. /// Content query executor. - /// Mapper to provide mapping from data container to model. /// Cache. - public ContentRepositoryBase(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) + public ContentRepositoryBase(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) { WebsiteChannelContext = websiteChannelContext; this.executor = executor; - this.mapper = mapper; this.cache = cache; } @@ -57,7 +56,6 @@ public Task> GetCachedQueryResult( CacheSettings cacheSettings, Func, CancellationToken, Task>> cacheDependenciesFunc, CancellationToken cancellationToken) - where T : new() { if (queryBuilder is null) { @@ -79,76 +77,29 @@ public Task> GetCachedQueryResult( queryOptions = new ContentQueryExecutionOptions(); } - return GetCachedQueryResultInternal(queryBuilder, queryOptions, container => mapper.Map(container), cacheSettings, cacheDependenciesFunc, cancellationToken); - } - - - /// - /// Returns cached query result. - /// - /// Model to which the query results will be mapped. - /// Prepared query builder to be executed by the injected . - /// Optional . Default values are used if not specified. - /// Function converting a web page content query data record container to the resulting instance. - /// Object with values to set up cache. See for more information. - /// Function that will create cache dependencies for the query. - /// Cancellation instruction. - /// Thrown when any of the , or parameters is null. - /// Request is not cached if the request is for preview. - public Task> GetCachedQueryResult( - ContentItemQueryBuilder queryBuilder, - ContentQueryExecutionOptions queryOptions, - Func resultSelector, - CacheSettings cacheSettings, - Func, CancellationToken, Task>> cacheDependenciesFunc, - CancellationToken cancellationToken) - where T : new() - { - if (queryBuilder is null) - { - throw new ArgumentNullException(nameof(queryBuilder)); - } - - if (cacheSettings is null) - { - throw new ArgumentNullException(nameof(cacheSettings)); - } - - if (cacheDependenciesFunc is null) - { - throw new ArgumentNullException(nameof(cacheDependenciesFunc)); - } - - if (queryOptions == null) - { - queryOptions = new ContentQueryExecutionOptions(); - } - - return GetCachedQueryResultInternal(queryBuilder, queryOptions, resultSelector, cacheSettings, cacheDependenciesFunc, cancellationToken); + return GetCachedQueryResultInternal(queryBuilder, queryOptions, cacheSettings, cacheDependenciesFunc, cancellationToken); } private async Task> GetCachedQueryResultInternal(ContentItemQueryBuilder queryBuilder, ContentQueryExecutionOptions queryOptions, - Func resultSelector, CacheSettings cacheSettings, Func, CancellationToken, Task>> cacheDependenciesFunc, CancellationToken cancellationToken) - where T : new() { queryOptions.ForPreview = WebsiteChannelContext.IsPreview; queryOptions.IncludeSecuredItems = queryOptions.IncludeSecuredItems || WebsiteChannelContext.IsPreview; if (WebsiteChannelContext.IsPreview) { - return await executor.GetWebPageResult(queryBuilder, resultSelector, options: queryOptions, cancellationToken: cancellationToken); + return await executor.GetMappedResult(queryBuilder, queryOptions, cancellationToken); } return await cache.LoadAsync(async (cacheSettings) => { - var result = await executor.GetWebPageResult(queryBuilder, resultSelector, options: queryOptions, cancellationToken: cancellationToken); + var result = await executor.GetMappedResult(queryBuilder, queryOptions, cancellationToken); - if (cacheSettings.Cached = (result != null && result.Any())) + if (cacheSettings.Cached = result != null && result.Any()) { cacheSettings.CacheDependency = CacheHelper.GetCacheDependency(await cacheDependenciesFunc(result, cancellationToken)); } diff --git a/examples/DancingGoat/Models/Reusable/Banner/Banner.generated.cs b/examples/DancingGoat/Models/Reusable/Banner/Banner.generated.cs index 2bffb4a..381fb0f 100644 --- a/examples/DancingGoat/Models/Reusable/Banner/Banner.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Banner/Banner.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Banner : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Banner : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/Cafe/Cafe.generated.cs b/examples/DancingGoat/Models/Reusable/Cafe/Cafe.generated.cs index 2940e5c..46ba1ef 100644 --- a/examples/DancingGoat/Models/Reusable/Cafe/Cafe.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Cafe/Cafe.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Cafe : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Cafe : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/Cafe/CafeRepository.cs b/examples/DancingGoat/Models/Reusable/Cafe/CafeRepository.cs index 4662ea9..2bb02a5 100644 --- a/examples/DancingGoat/Models/Reusable/Cafe/CafeRepository.cs +++ b/examples/DancingGoat/Models/Reusable/Cafe/CafeRepository.cs @@ -6,7 +6,6 @@ using CMS.ContentEngine; using CMS.Helpers; -using CMS.Websites; using CMS.Websites.Routing; namespace DancingGoat.Models @@ -22,22 +21,21 @@ public partial class CafeRepository : ContentRepositoryBase public CafeRepository( IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, - IWebPageQueryResultMapper mapper, IProgressiveCache cache, ILinkedItemsDependencyAsyncRetriever linkedItemsDependencyRetriever) - : base(websiteChannelContext, executor, mapper, cache) + : base(websiteChannelContext, executor, cache) { this.linkedItemsDependencyRetriever = linkedItemsDependencyRetriever; } /// - /// Returns an enumerable collection of company cafes ordered by a position in the content tree. + /// Returns an enumerable collection of cafes. /// - public async Task> GetCompanyCafes(int count, string languageName, CancellationToken cancellationToken = default) + public async Task> GetCafes(int count, string languageName, CancellationToken cancellationToken = default) { var queryBuilder = GetQueryBuilder(count, languageName); - var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(CafeRepository), languageName, nameof(GetCompanyCafes), count); + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(CafeRepository), nameof(GetCafes), count, languageName); return await GetCachedQueryResult(queryBuilder, null, cacheSettings, GetDependencyCacheKeys, cancellationToken); } @@ -48,9 +46,8 @@ private static ContentItemQueryBuilder GetQueryBuilder(int count, string languag return new ContentItemQueryBuilder() .ForContentType(Cafe.CONTENT_TYPE_NAME, config => config - .WithLinkedItems(1) - .TopN(count) - .Where(where => where.WhereTrue(nameof(Cafe.CafeIsCompanyCafe)))) + .WithLinkedItems(1) + .TopN(count)) .InLanguage(languageName); } diff --git a/examples/DancingGoat/Models/Reusable/Cafe/CafeViewModel.cs b/examples/DancingGoat/Models/Reusable/Cafe/CafeViewModel.cs index c0ff811..9a26bb0 100644 --- a/examples/DancingGoat/Models/Reusable/Cafe/CafeViewModel.cs +++ b/examples/DancingGoat/Models/Reusable/Cafe/CafeViewModel.cs @@ -1,4 +1,6 @@ -namespace DancingGoat.Models +using System.Linq; + +namespace DancingGoat.Models { public record CafeViewModel(string Name, string PhotoPath, string PhotoShortDescription, string Street, string City, string Country, string ZipCode, string Phone) { diff --git a/examples/DancingGoat/Models/Reusable/Coffee/Coffee.generated.cs b/examples/DancingGoat/Models/Reusable/Coffee/Coffee.generated.cs index 75b1b01..4271000 100644 --- a/examples/DancingGoat/Models/Reusable/Coffee/Coffee.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Coffee/Coffee.generated.cs @@ -18,7 +18,8 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// - public partial class Coffee : IContentItemFieldsSource + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] + public partial class Coffee : IContentItemFieldsSource, IProductFields { /// /// Code name of the content type. @@ -29,30 +30,43 @@ public partial class Coffee : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } /// - /// CoffeeName. + /// CoffeeProcessing. /// - public string CoffeeName { get; set; } + public IEnumerable CoffeeProcessing { get; set; } /// - /// CoffeeShortDescription. + /// CoffeeTastes. /// - public string CoffeeShortDescription { get; set; } + public IEnumerable CoffeeTastes { get; set; } /// - /// CoffeeDescription. + /// ProductFieldsName. /// - public string CoffeeDescription { get; set; } + public string ProductFieldsName { get; set; } /// - /// CoffeeImage. + /// ProductFieldsDescription. /// - public IEnumerable CoffeeImage { get; set; } + public string ProductFieldsDescription { get; set; } + + + /// + /// ProductFieldsShortDescription. + /// + public string ProductFieldsShortDescription { get; set; } + + + /// + /// ProductFieldsImage. + /// + public IEnumerable ProductFieldsImage { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/Reusable/Coffee/CoffeeRepository.cs b/examples/DancingGoat/Models/Reusable/Coffee/CoffeeRepository.cs deleted file mode 100644 index 0afb48c..0000000 --- a/examples/DancingGoat/Models/Reusable/Coffee/CoffeeRepository.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using CMS.ContentEngine; -using CMS.Helpers; -using CMS.Websites; -using CMS.Websites.Routing; - -namespace DancingGoat.Models -{ - /// - /// Represents a collection of coffees. - /// - public partial class CoffeeRepository : ContentRepositoryBase - { - private readonly ILinkedItemsDependencyRetriever linkedItemsDependencyRetriever; - - /// - /// Initializes a new instance of the class that returns coffees. - /// - public CoffeeRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache, ILinkedItemsDependencyRetriever linkedItemsDependencyRetriever) - : base(websiteChannelContext, executor, mapper, cache) - { - this.linkedItemsDependencyRetriever = linkedItemsDependencyRetriever; - } - - - /// - /// Returns an enumerable collection of based on a given collection of content item guids. - /// - public async Task> GetCoffees(ICollection coffeeGuids, string languageName, CancellationToken cancellationToken = default) - { - var queryBuilder = GetQueryBuilder(coffeeGuids, languageName); - - var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(CoffeeRepository), nameof(GetCoffees), languageName, coffeeGuids.Select(guid => guid.ToString()).Join("|")); - - return await GetCachedQueryResult(queryBuilder, null, cacheSettings, (coffees, cancellationToken) => GetDependencyCacheKeys(coffees, coffeeGuids), cancellationToken); - } - - - private static ContentItemQueryBuilder GetQueryBuilder(ICollection coffeeGuids, string languageName) - { - return new ContentItemQueryBuilder() - .ForContentType(Coffee.CONTENT_TYPE_NAME, - config => config - .WithLinkedItems(1) - .Where(where => where.WhereIn(nameof(IContentQueryDataContainer.ContentItemGUID), coffeeGuids))) - .InLanguage(languageName); - } - - - private Task> GetDependencyCacheKeys(IEnumerable coffees, IEnumerable coffeeGuids) - { - var dependencyCacheKeys = linkedItemsDependencyRetriever.Get(coffees.Select(coffee => coffee.SystemFields.ContentItemID), 1).ToHashSet(StringComparer.InvariantCultureIgnoreCase); - - foreach (var guid in coffeeGuids) - { - dependencyCacheKeys.Add(CacheHelper.BuildCacheItemName(new[] { "contentitem", "byguid", guid.ToString() }, false)); - } - - return Task.FromResult>(dependencyCacheKeys); - } - } -} diff --git a/examples/DancingGoat/Models/Reusable/Contact/Contact.generated.cs b/examples/DancingGoat/Models/Reusable/Contact/Contact.generated.cs index 6c7e3e1..541e1d6 100644 --- a/examples/DancingGoat/Models/Reusable/Contact/Contact.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Contact/Contact.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Contact : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Contact : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/Contact/ContactRepository.cs b/examples/DancingGoat/Models/Reusable/Contact/ContactRepository.cs index bfbf0a3..96f9025 100644 --- a/examples/DancingGoat/Models/Reusable/Contact/ContactRepository.cs +++ b/examples/DancingGoat/Models/Reusable/Contact/ContactRepository.cs @@ -5,7 +5,6 @@ using CMS.ContentEngine; using CMS.Helpers; -using CMS.Websites; using CMS.Websites.Routing; namespace DancingGoat.Models @@ -15,8 +14,8 @@ namespace DancingGoat.Models /// public class ContactRepository : ContentRepositoryBase { - public ContactRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public ContactRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/Reusable/Event/Event.generated.cs b/examples/DancingGoat/Models/Reusable/Event/Event.generated.cs index dcc7131..221b331 100644 --- a/examples/DancingGoat/Models/Reusable/Event/Event.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Event/Event.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Event : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Event : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/Event/EventViewModel.cs b/examples/DancingGoat/Models/Reusable/Event/EventViewModel.cs index 3db555c..fb7ce36 100644 --- a/examples/DancingGoat/Models/Reusable/Event/EventViewModel.cs +++ b/examples/DancingGoat/Models/Reusable/Event/EventViewModel.cs @@ -26,7 +26,7 @@ public static EventViewModel GetViewModel(Event eventContentItem) eventContentItem.EventPromoText, eventContentItem.EventDate, cafe?.CafeName, - cafe?.CafeCuppingOffer.Select(coffee => coffee.CoffeeName) + cafe?.CafeCuppingOffer.Select(coffee => coffee.ProductFieldsName) ); } } diff --git a/examples/DancingGoat/Models/Reusable/Grinder/Grinder.generated.cs b/examples/DancingGoat/Models/Reusable/Grinder/Grinder.generated.cs new file mode 100644 index 0000000..32cc100 --- /dev/null +++ b/examples/DancingGoat/Models/Reusable/Grinder/Grinder.generated.cs @@ -0,0 +1,72 @@ +//-------------------------------------------------------------------------------------------------- +// +// +// This code was generated by code generator tool. +// +// To customize the code use your own partial class. For more info about how to use and customize +// the generated code see the documentation at https://docs.xperience.io/. +// +// +//-------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using CMS.ContentEngine; + +namespace DancingGoat.Models +{ + /// + /// Represents a content item of type . + /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] + public partial class Grinder : IContentItemFieldsSource, IProductFields + { + /// + /// Code name of the content type. + /// + public const string CONTENT_TYPE_NAME = "DancingGoat.Grinder"; + + + /// + /// Represents system properties for a content item. + /// + [SystemField] + public ContentItemFields SystemFields { get; set; } + + + /// + /// GrinderManufacturer. + /// + public IEnumerable GrinderManufacturer { get; set; } + + + /// + /// GrinderType. + /// + public IEnumerable GrinderType { get; set; } + + + /// + /// ProductFieldsName. + /// + public string ProductFieldsName { get; set; } + + + /// + /// ProductFieldsDescription. + /// + public string ProductFieldsDescription { get; set; } + + + /// + /// ProductFieldsShortDescription. + /// + public string ProductFieldsShortDescription { get; set; } + + + /// + /// ProductFieldsImage. + /// + public IEnumerable ProductFieldsImage { get; set; } + } +} \ No newline at end of file diff --git a/examples/DancingGoat/Models/Reusable/Image/Image.generated.cs b/examples/DancingGoat/Models/Reusable/Image/Image.generated.cs index d334b91..4c98e04 100644 --- a/examples/DancingGoat/Models/Reusable/Image/Image.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Image/Image.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Image : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Image : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/Image/ImageRepository.cs b/examples/DancingGoat/Models/Reusable/Image/ImageRepository.cs index 31e6e1f..2852d46 100644 --- a/examples/DancingGoat/Models/Reusable/Image/ImageRepository.cs +++ b/examples/DancingGoat/Models/Reusable/Image/ImageRepository.cs @@ -6,15 +6,14 @@ using CMS.ContentEngine; using CMS.Helpers; -using CMS.Websites; using CMS.Websites.Routing; namespace DancingGoat.Models { public class ImageRepository : ContentRepositoryBase { - public ImageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public ImageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/Reusable/Product/ProductRepository.cs b/examples/DancingGoat/Models/Reusable/Product/ProductRepository.cs new file mode 100644 index 0000000..ff114df --- /dev/null +++ b/examples/DancingGoat/Models/Reusable/Product/ProductRepository.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using CMS.ContentEngine; +using CMS.DataEngine; +using CMS.Helpers; +using CMS.Websites; +using CMS.Websites.Routing; + +namespace DancingGoat.Models +{ + /// + /// Represents a collection of product pages. + /// + public class ProductRepository : ContentRepositoryBase + { + private const string COFFEE_PROCESSING = "CoffeeProcessing"; + private const string COFFEE_TASTES = "CoffeeTastes"; + private const string GRINDER_MANUFACTURER = "GrinderManufacturer"; + private const string GRINDER_TYPE = "GrinderType"; + + + private readonly ILinkedItemsDependencyAsyncRetriever linkedItemsDependencyRetriever; + private readonly IInfoProvider taxonomyInfoProvider; + + + /// + /// Initializes new instance of . + /// + public ProductRepository( + IWebsiteChannelContext websiteChannelContext, + IContentQueryExecutor executor, + IProgressiveCache cache, + ILinkedItemsDependencyAsyncRetriever linkedItemsDependencyRetriever, + IInfoProvider taxonomyInfoProvider) + : base(websiteChannelContext, executor, cache) + { + this.linkedItemsDependencyRetriever = linkedItemsDependencyRetriever; + this.taxonomyInfoProvider = taxonomyInfoProvider; + } + + + /// + /// Returns list of content items. + /// + public async Task> GetProducts(string languageName, IDictionary filter, bool includeSecuredItems = true, CancellationToken cancellationToken = default) + { + var queryBuilder = await GetQueryBuilder(languageName, filter: filter); + + var options = new ContentQueryExecutionOptions + { + IncludeSecuredItems = includeSecuredItems + }; + + var filterCacheItemNameParts = filter.Values.Where(value => value != null && value.Tags != null).SelectMany(value => value.Tags.Where(tag => tag.IsChecked)).Select(id => id.Value.ToString()).Join("|"); + + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, languageName, includeSecuredItems, nameof(IProductFields), filterCacheItemNameParts); + + return await GetCachedQueryResult(queryBuilder, options, cacheSettings, (_, _) => GetDependencyCacheKeys(languageName), cancellationToken); + } + + + /// + /// Returns list of content items. + /// + public async Task> GetProducts(ICollection productGuids, string languageName, CancellationToken cancellationToken = default) + { + var queryBuilder = await GetQueryBuilder(languageName, productGuids); + + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, languageName, nameof(IProductFields), productGuids.Select(guid => guid.ToString()).Join("|")); + + return await GetCachedQueryResult(queryBuilder, new ContentQueryExecutionOptions(), cacheSettings, (_, _) => GetDependencyCacheKeys(languageName, productGuids), cancellationToken); + } + + + private static async Task GetQueryBuilder(string languageName, IEnumerable productGuids = null, IDictionary filter = null) + { + var baseBuilder = new ContentItemQueryBuilder().ForContentTypes(ct => + { + ct.OfReusableSchema(IProductFields.REUSABLE_FIELD_SCHEMA_NAME) + .WithContentTypeFields() + .WithLinkedItems(1); + }).InLanguage(languageName); + + if (productGuids != null) + { + baseBuilder.Parameters(query => query.Where(where => where.WhereIn(nameof(IContentQueryDataContainer.ContentItemGUID), productGuids))); + } + + if (filter == null || !filter.Any()) + { + return baseBuilder; + } + + var coffeeProcessingTags = await GetSelectedTags(filter, COFFEE_PROCESSING); + var coffeeTastesTags = await GetSelectedTags(filter, COFFEE_TASTES); + var grinderManufacturerTags = await GetSelectedTags(filter, GRINDER_MANUFACTURER); + var grinderTypeTags = await GetSelectedTags(filter, GRINDER_TYPE); + + return baseBuilder + .Parameters(query => query.Where(where => where + .Where(coffeeWhere => coffeeWhere + .WhereContainsTags(nameof(Coffee.CoffeeProcessing), coffeeProcessingTags) + .WhereContainsTags(nameof(Coffee.CoffeeTastes), coffeeTastesTags)) + .Where(grinderWhere => grinderWhere + .WhereContainsTags(nameof(Grinder.GrinderManufacturer), grinderManufacturerTags) + .WhereContainsTags(nameof(Grinder.GrinderType), grinderTypeTags)) + )); + } + + + private static async Task GetSelectedTags(IDictionary filter, string taxonomyName) + { + if (filter.TryGetValue(taxonomyName, out var taxonomy)) + { + return await taxonomy.GetSelectedTags(); + } + + return null; + } + + + private async Task> GetDependencyCacheKeys(string languageName, ICollection productGuids = null) + { + var dependencyCacheKeys = new HashSet(StringComparer.InvariantCultureIgnoreCase) + { + CacheHelper.GetCacheItemName(null, WebsiteChannelInfo.OBJECT_TYPE, "byid", WebsiteChannelContext.WebsiteChannelID), + CacheHelper.GetCacheItemName(null, "contentitem", "bycontenttype", Coffee.CONTENT_TYPE_NAME, languageName), + CacheHelper.GetCacheItemName(null, "contentitem", "bycontenttype", Grinder.CONTENT_TYPE_NAME, languageName), + await GetTaxonomyTagsCacheDependencyKey(COFFEE_PROCESSING), + await GetTaxonomyTagsCacheDependencyKey(COFFEE_TASTES), + await GetTaxonomyTagsCacheDependencyKey(GRINDER_MANUFACTURER), + await GetTaxonomyTagsCacheDependencyKey(GRINDER_TYPE) + }; + GetProductPageDependencies(productGuids, dependencyCacheKeys); + + return dependencyCacheKeys; + } + + + private static void GetProductPageDependencies(ICollection productGuids, HashSet dependencyCacheKeys) + { + if (productGuids == null || !productGuids.Any()) + { + return; + } + + foreach (var guid in productGuids) + { + dependencyCacheKeys.Add(CacheHelper.BuildCacheItemName(new[] { "contentitem", "byguid", guid.ToString() }, false)); + } + } + + + private async Task GetTaxonomyTagsCacheDependencyKey(string taxonomyName) + { + var taxonomyID = (await taxonomyInfoProvider.GetAsync(taxonomyName)).TaxonomyID; + return CacheHelper.GetCacheItemName(null, TaxonomyInfo.OBJECT_TYPE, "byid", taxonomyID, "children"); + } + } +} diff --git a/examples/DancingGoat/Models/Reusable/Reference/Reference.generated.cs b/examples/DancingGoat/Models/Reusable/Reference/Reference.generated.cs index 0b60d2c..c1aaa25 100644 --- a/examples/DancingGoat/Models/Reusable/Reference/Reference.generated.cs +++ b/examples/DancingGoat/Models/Reusable/Reference/Reference.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class Reference : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class Reference : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/SocialLink/SocialLink.generated.cs b/examples/DancingGoat/Models/Reusable/SocialLink/SocialLink.generated.cs index 64dab81..1bef5b5 100644 --- a/examples/DancingGoat/Models/Reusable/SocialLink/SocialLink.generated.cs +++ b/examples/DancingGoat/Models/Reusable/SocialLink/SocialLink.generated.cs @@ -18,6 +18,7 @@ namespace DancingGoat.Models /// /// Represents a content item of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class SocialLink : IContentItemFieldsSource { /// @@ -29,6 +30,7 @@ public partial class SocialLink : IContentItemFieldsSource /// /// Represents system properties for a content item. /// + [SystemField] public ContentItemFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/Reusable/SocialLink/SocialLinkRepository.cs b/examples/DancingGoat/Models/Reusable/SocialLink/SocialLinkRepository.cs index 2822daf..08d8b07 100644 --- a/examples/DancingGoat/Models/Reusable/SocialLink/SocialLinkRepository.cs +++ b/examples/DancingGoat/Models/Reusable/SocialLink/SocialLinkRepository.cs @@ -6,7 +6,6 @@ using CMS.ContentEngine; using CMS.Helpers; -using CMS.Websites; using CMS.Websites.Routing; namespace DancingGoat.Models @@ -19,8 +18,8 @@ public class SocialLinkRepository : ContentRepositoryBase private readonly ILinkedItemsDependencyRetriever linkedItemsDependencyRetriever; - public SocialLinkRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache, ILinkedItemsDependencyRetriever linkedItemsDependencyRetriever) - : base(websiteChannelContext, executor, mapper, cache) + public SocialLinkRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache, ILinkedItemsDependencyRetriever linkedItemsDependencyRetriever) + : base(websiteChannelContext, executor, cache) { this.linkedItemsDependencyRetriever = linkedItemsDependencyRetriever; } diff --git a/examples/DancingGoat/Models/Reusable/Tag/TagViewModel.cs b/examples/DancingGoat/Models/Reusable/Tag/TagViewModel.cs new file mode 100644 index 0000000..a7dcaaa --- /dev/null +++ b/examples/DancingGoat/Models/Reusable/Tag/TagViewModel.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using CMS.ContentEngine; + +using Tag = CMS.ContentEngine.Tag; + +namespace DancingGoat.Models +{ + public record TagViewModel(string Name, int Level, Guid Value, bool IsChecked = false) + { + private const int ROOT_TAG_ID = 0; + + public static TagViewModel GetViewModel(Tag tag, int level = 0) + { + return new TagViewModel(tag.Title, level, tag.Identifier); + } + + + public static List GetViewModels(IEnumerable tags) + { + var result = new List(); + var tagsByParentId = tags.GroupBy(tag => tag.ParentID).ToDictionary(group => group.Key, group => group.ToList()); + + if (tagsByParentId.TryGetValue(ROOT_TAG_ID, out var firstLevelTags)) + { + GetTagsWithTagViewModels(firstLevelTags, ROOT_TAG_ID); + } + + return result; + + + void GetTagsWithTagViewModels(IEnumerable currentLevelTags, int level) + { + foreach (var tag in currentLevelTags.OrderBy(tag => tag.Order)) + { + var children = tagsByParentId.TryGetValue(tag.ID, out var childrenTags) ? childrenTags : Enumerable.Empty(); + result.Add(GetViewModel(tag, level)); + GetTagsWithTagViewModels(children, level + 1); + } + } + } + } +} diff --git a/examples/DancingGoat/Models/Reusable/Taxonomy/TaxonomyViewModel.cs b/examples/DancingGoat/Models/Reusable/Taxonomy/TaxonomyViewModel.cs new file mode 100644 index 0000000..d4128ef --- /dev/null +++ b/examples/DancingGoat/Models/Reusable/Taxonomy/TaxonomyViewModel.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using CMS.ContentEngine; + +namespace DancingGoat.Models +{ + public record TaxonomyViewModel(string Name, string CodeName, List Tags) + { + /// + /// Maps to a . + /// + public static TaxonomyViewModel GetViewModel(TaxonomyData taxonomy) + { + return new TaxonomyViewModel(taxonomy.Taxonomy.Title, taxonomy.Taxonomy.Name, TagViewModel.GetViewModels(taxonomy.Tags)); + } + + + /// + /// Gets selected tags. + /// + public async Task GetSelectedTags() + { + if (Tags == null) + { + return null; + } + + return await TagCollection.Create(Tags.Where(tag => tag.IsChecked).Select(tag => tag.Value)); + } + } +} \ No newline at end of file diff --git a/examples/DancingGoat/Models/Schema/IProductFields.generated.cs b/examples/DancingGoat/Models/Schema/IProductFields.generated.cs new file mode 100644 index 0000000..d5dda02 --- /dev/null +++ b/examples/DancingGoat/Models/Schema/IProductFields.generated.cs @@ -0,0 +1,51 @@ +//-------------------------------------------------------------------------------------------------- +// +// +// This code was generated by code generator tool. +// +// To customize the code use your own partial class. For more info about how to use and customize +// the generated code see the documentation at https://docs.xperience.io/. +// +// +//-------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; + +namespace DancingGoat.Models +{ + /// + /// Defines a contract for content types with the reusable schema assigned. + /// + public interface IProductFields + { + /// + /// Code name of the reusable field schema. + /// + public const string REUSABLE_FIELD_SCHEMA_NAME = "ProductFields"; + + + /// + /// ProductFieldsName. + /// + public string ProductFieldsName { get; set; } + + + /// + /// ProductFieldsDescription. + /// + public string ProductFieldsDescription { get; set; } + + + /// + /// ProductFieldsShortDescription. + /// + public string ProductFieldsShortDescription { get; set; } + + + /// + /// ProductFieldsImage. + /// + public IEnumerable ProductFieldsImage { get; set; } + } +} \ No newline at end of file diff --git a/examples/DancingGoat/Models/Schema/ISEOFields.generated.cs b/examples/DancingGoat/Models/Schema/ISEOFields.generated.cs index c7bedc8..3146ad8 100644 --- a/examples/DancingGoat/Models/Schema/ISEOFields.generated.cs +++ b/examples/DancingGoat/Models/Schema/ISEOFields.generated.cs @@ -19,6 +19,12 @@ namespace DancingGoat.Models /// public interface ISEOFields { + /// + /// Code name of the reusable field schema. + /// + public const string REUSABLE_FIELD_SCHEMA_NAME = "SEOFields"; + + /// /// SEOFieldsTitle. /// @@ -29,5 +35,11 @@ public interface ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePage.generated.cs b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePage.generated.cs index 773b003..e3b46a9 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class ArticlePage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class ArticlePage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -78,5 +81,11 @@ public partial class ArticlePage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePageRepository.cs b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePageRepository.cs index 1705dca..c9b6325 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticlePageRepository.cs @@ -26,10 +26,9 @@ public class ArticlePageRepository : ContentRepositoryBase public ArticlePageRepository( IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, - IWebPageQueryResultMapper mapper, IProgressiveCache cache, IWebPageLinkedItemsDependencyAsyncRetriever webPageLinkedItemsDependencyRetriever) - : base(websiteChannelContext, executor, mapper, cache) + : base(websiteChannelContext, executor, cache) { this.webPageLinkedItemsDependencyRetriever = webPageLinkedItemsDependencyRetriever; } @@ -60,10 +59,7 @@ public async Task> GetArticles(ICollection guids, { var queryBuilder = GetQueryBuilder(guids, languageName); - var options = new ContentQueryExecutionOptions - { - IncludeSecuredItems = true - }; + var options = new ContentQueryExecutionOptions { IncludeSecuredItems = true }; var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, languageName, guids.GetHashCode()); @@ -106,13 +102,14 @@ private ContentItemQueryBuilder GetQueryBuilder(int topN, string treePath, strin private ContentItemQueryBuilder GetQueryBuilder(ICollection guids, string languageName) { - return GetQueryBuilder( - languageName, - config => config - .WithLinkedItems(1) - .OrderBy(OrderByColumn.Desc(nameof(ArticlePage.ArticlePagePublishDate))) - .ForWebsite(WebsiteChannelContext.WebsiteChannelName) - .Where(where => where.WhereIn(nameof(IWebPageContentQueryDataContainer.WebPageItemGUID), guids))); + return new ContentItemQueryBuilder().ForContentTypes(q => + { + q.ForWebsite(guids) + .WithContentTypeFields() + .WithLinkedItems(1); + }).InLanguage(languageName) + .Parameters(q => + q.OrderBy(OrderByColumn.Desc(nameof(ArticlePage.ArticlePagePublishDate)))); } diff --git a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticleViewModel.cs b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticleViewModel.cs index e3feaff..9410c3d 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlePage/ArticleViewModel.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlePage/ArticleViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using CMS.Websites; @@ -11,11 +12,11 @@ public record ArticleViewModel(string Title, string TeaserUrl, string Summary, s /// /// Validates and maps to a . /// - public static async Task GetViewModel(ArticlePage articlePage, IWebPageUrlRetriever urlRetriever, string languageName) + public static async Task GetViewModel(ArticlePage articlePage, IWebPageUrlRetriever urlRetriever, string languageName, CancellationToken cancellationToken = default) { var teaser = articlePage.ArticlePageTeaser.FirstOrDefault(); - var url = await urlRetriever.Retrieve(articlePage, languageName); + var url = await urlRetriever.Retrieve(articlePage, languageName, cancellationToken); return new ArticleViewModel( articlePage.ArticleTitle, diff --git a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSection.generated.cs b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSection.generated.cs index 8baf231..c51466d 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSection.generated.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSection.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class ArticlesSection : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class ArticlesSection : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -42,5 +45,11 @@ public partial class ArticlesSection : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionRepository.cs b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionRepository.cs index a4abc11..390f96d 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionRepository.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionRepository.cs @@ -16,8 +16,8 @@ public class ArticlesSectionRepository : ContentRepositoryBase /// /// Initializes new instance of . /// - public ArticlesSectionRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public ArticlesSectionRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionViewModel.cs b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionViewModel.cs index ebf1dc7..72ca09d 100644 --- a/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionViewModel.cs +++ b/examples/DancingGoat/Models/WebPage/ArticlesSection/ArticlesSectionViewModel.cs @@ -1,4 +1,5 @@ - +using System.Collections.Generic; + using CMS.Websites; namespace DancingGoat.Models @@ -13,10 +14,12 @@ public record ArticlesSectionViewModel(IEnumerable Articles, s /// /// Maps to a . /// - public static ArticlesSectionViewModel GetViewModel(ArticlesSection articlesSection, IEnumerable articles, string articlesPath) => - new(articles, articlesPath) + public static ArticlesSectionViewModel GetViewModel(ArticlesSection articlesSection, IEnumerable Articles, string ArticlesPath) + { + return new ArticlesSectionViewModel(Articles, ArticlesPath) { WebPage = articlesSection }; + } } } diff --git a/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeeDetailViewModel.cs b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeeDetailViewModel.cs new file mode 100644 index 0000000..ae380f3 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeeDetailViewModel.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using CMS.ContentEngine; + +using Tag = CMS.ContentEngine.Tag; + +namespace DancingGoat.Models +{ + public record CoffeeDetailViewModel(string Name, string Description, string ImageUrl, IEnumerable Tastes, IEnumerable Processing) + { + /// + /// Maps to a . + /// + public async static Task GetViewModel(CoffeePage coffeePage, string languageName, ITaxonomyRetriever taxonomyRetriever) + { + var coffee = coffeePage.RelatedItem.FirstOrDefault(); + var image = coffee.ProductFieldsImage.FirstOrDefault(); + + return new CoffeeDetailViewModel( + coffee.ProductFieldsName, + coffee.ProductFieldsDescription, + image?.ImageFile.Url, + await taxonomyRetriever.RetrieveTags(coffee.CoffeeTastes.Select(taste => taste.Identifier), languageName), + await taxonomyRetriever.RetrieveTags(coffee.CoffeeProcessing.Select(processing => processing.Identifier), languageName) + ); + } + } +} diff --git a/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.cs b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.cs new file mode 100644 index 0000000..57542c5 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace DancingGoat.Models +{ + /// + /// Custom code for page of type . + /// + public partial class CoffeePage : IProductPage + { + /// + IEnumerable IProductPage.RelatedItem { get => RelatedItem; } + } +} diff --git a/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.generated.cs b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.generated.cs new file mode 100644 index 0000000..5045100 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/CoffeePage/CoffeePage.generated.cs @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------------------- +// +// +// This code was generated by code generator tool. +// +// To customize the code use your own partial class. For more info about how to use and customize +// the generated code see the documentation at https://docs.xperience.io/. +// +// +//-------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using CMS.ContentEngine; +using CMS.Websites; + +namespace DancingGoat.Models +{ + /// + /// Represents a page of type . + /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] + public partial class CoffeePage : IWebPageFieldsSource + { + /// + /// Code name of the content type. + /// + public const string CONTENT_TYPE_NAME = "DancingGoat.CoffeePage"; + + + /// + /// Represents system properties for a web page item. + /// + [SystemField] + public WebPageFields SystemFields { get; set; } + + + /// + /// RelatedItem. + /// + public IEnumerable RelatedItem { get; set; } + } +} diff --git a/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPage.generated.cs b/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPage.generated.cs index 80d3333..5c0fcd1 100644 --- a/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class ConfirmationPage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class ConfirmationPage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -66,5 +69,11 @@ public partial class ConfirmationPage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPageRepository.cs b/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPageRepository.cs index d81fb45..6a9179c 100644 --- a/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/ConfirmationPage/ConfirmationPageRepository.cs @@ -15,8 +15,8 @@ namespace DancingGoat.Models /// public class ConfirmationPageRepository : ContentRepositoryBase { - public ConfirmationPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public ConfirmationPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsIndexViewModel.cs b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsIndexViewModel.cs index 30a5f1d..ccb1a70 100644 --- a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsIndexViewModel.cs +++ b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsIndexViewModel.cs @@ -18,6 +18,12 @@ public class ContactsIndexViewModel : IWebPageBasedViewModel public List CompanyCafes { get; set; } + /// + /// The partner cafes data. + /// + public List PartnerCafes { get; set; } + + /// public IWebPageFieldsSource WebPage { get; init; } } diff --git a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPage.generated.cs b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPage.generated.cs index 513a741..965fbb5 100644 --- a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class ContactsPage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class ContactsPage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -42,5 +45,11 @@ public partial class ContactsPage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPageRepository.cs b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPageRepository.cs index 3b1a9c4..4133065 100644 --- a/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/ContactsPage/ContactsPageRepository.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -15,20 +16,35 @@ public class ContactsPageRepository : ContentRepositoryBase /// /// Initializes new instance of . /// - public ContactsPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public ContactsPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } + /// + /// Returns web page by tree path and language name. + /// + public async Task GetContactsPage(string treePath, string languageName, CancellationToken cancellationToken = default) + { + var queryBuilder = GetQueryBuilder(w => w.WhereEquals(nameof(IWebPageContentQueryDataContainer.WebPageItemTreePath), treePath), languageName); + + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(ContactsPage), nameof(IWebPageContentQueryDataContainer.WebPageItemTreePath), treePath, languageName); + + var result = await GetCachedQueryResult(queryBuilder, null, cacheSettings, GetDependencyCacheKeys, cancellationToken); + + return result.FirstOrDefault(); + } + + /// /// Returns web page by ID and language name. /// public async Task GetContactsPage(int webPageItemId, string languageName, CancellationToken cancellationToken = default) { - var queryBuilder = GetQueryBuilder(webPageItemId, languageName); + var queryBuilder = GetQueryBuilder(w => w.WhereEquals(nameof(IWebPageContentQueryDataContainer.WebPageItemID), webPageItemId), languageName); - var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(ContactsPage), webPageItemId, languageName); + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(ContactsPage), nameof(IWebPageContentQueryDataContainer.WebPageItemID), webPageItemId, languageName); var result = await GetCachedQueryResult(queryBuilder, null, cacheSettings, GetDependencyCacheKeys, cancellationToken); @@ -36,13 +52,12 @@ public async Task GetContactsPage(int webPageItemId, string langua } - private ContentItemQueryBuilder GetQueryBuilder(int webPageItemId, string languageName) + private ContentItemQueryBuilder GetQueryBuilder(Action where, string languageName) { return new ContentItemQueryBuilder() .ForContentType(ContactsPage.CONTENT_TYPE_NAME, config => config - .ForWebsite(WebsiteChannelContext.WebsiteChannelName, includeUrlPath: false) - .Where(where => where - .WhereEquals(nameof(IWebPageContentQueryDataContainer.WebPageItemID), webPageItemId)) + .ForWebsite(WebsiteChannelContext.WebsiteChannelName) + .Where(where) .TopN(1)) .InLanguage(languageName); } diff --git a/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderDetailViewModel.cs b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderDetailViewModel.cs new file mode 100644 index 0000000..5079460 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderDetailViewModel.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using CMS.ContentEngine; + +using Tag = CMS.ContentEngine.Tag; + +namespace DancingGoat.Models +{ + public record GrinderDetailViewModel(string Name, string Description, string ImageUrl, IEnumerable Manufacturers, IEnumerable Type) + { + /// + /// Maps to a . + /// + public async static Task GetViewModel(GrinderPage grinderPage, string languageName, ITaxonomyRetriever taxonomyRetriever) + { + var grinder = grinderPage.RelatedItem.FirstOrDefault(); + var image = grinder.ProductFieldsImage.FirstOrDefault(); + + return new GrinderDetailViewModel( + grinder.ProductFieldsName, + grinder.ProductFieldsDescription, + image?.ImageFile.Url, + await taxonomyRetriever.RetrieveTags(grinder.GrinderManufacturer.Select(manufacturer => manufacturer.Identifier), languageName), + await taxonomyRetriever.RetrieveTags(grinder.GrinderType.Select(type => type.Identifier), languageName) + ); + } + } +} diff --git a/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.cs b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.cs new file mode 100644 index 0000000..ded6ed2 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace DancingGoat.Models +{ + /// + /// Custom code for page of type . + /// + public partial class GrinderPage : IProductPage + { + /// + IEnumerable IProductPage.RelatedItem { get => RelatedItem; } + } +} diff --git a/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.generated.cs b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.generated.cs new file mode 100644 index 0000000..d79dda1 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/GrinderPage/GrinderPage.generated.cs @@ -0,0 +1,43 @@ +//-------------------------------------------------------------------------------------------------- +// +// +// This code was generated by code generator tool. +// +// To customize the code use your own partial class. For more info about how to use and customize +// the generated code see the documentation at https://docs.xperience.io/. +// +// +//-------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using CMS.ContentEngine; +using CMS.Websites; + +namespace DancingGoat.Models +{ + /// + /// Represents a page of type . + /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] + public partial class GrinderPage : IWebPageFieldsSource + { + /// + /// Code name of the content type. + /// + public const string CONTENT_TYPE_NAME = "DancingGoat.GrinderPage"; + + + /// + /// Represents system properties for a web page item. + /// + [SystemField] + public WebPageFields SystemFields { get; set; } + + + /// + /// RelatedItem. + /// + public IEnumerable RelatedItem { get; set; } + } +} \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/HomePage/HomePage.generated.cs b/examples/DancingGoat/Models/WebPage/HomePage/HomePage.generated.cs index f4d0791..4585e10 100644 --- a/examples/DancingGoat/Models/WebPage/HomePage/HomePage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/HomePage/HomePage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class HomePage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class HomePage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -78,5 +81,11 @@ public partial class HomePage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/HomePage/HomePageRepository.cs b/examples/DancingGoat/Models/WebPage/HomePage/HomePageRepository.cs index 9f8c8a5..c9614e3 100644 --- a/examples/DancingGoat/Models/WebPage/HomePage/HomePageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/HomePage/HomePageRepository.cs @@ -22,8 +22,8 @@ public class HomePageRepository : ContentRepositoryBase /// /// Initializes new instance of . /// - public HomePageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache, IWebPageLinkedItemsDependencyAsyncRetriever webPageLinkedItemsDependencyRetriever) - : base(websiteChannelContext, executor, mapper, cache) + public HomePageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache, IWebPageLinkedItemsDependencyAsyncRetriever webPageLinkedItemsDependencyRetriever) + : base(websiteChannelContext, executor, cache) { this.webPageLinkedItemsDependencyRetriever = webPageLinkedItemsDependencyRetriever; } diff --git a/examples/DancingGoat/Models/WebPage/LandingPage/LandingPage.generated.cs b/examples/DancingGoat/Models/WebPage/LandingPage/LandingPage.generated.cs index fbec93c..fcfb146 100644 --- a/examples/DancingGoat/Models/WebPage/LandingPage/LandingPage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/LandingPage/LandingPage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class LandingPage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class LandingPage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -42,5 +45,11 @@ public partial class LandingPage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/LandingPage/LandingPageRepository.cs b/examples/DancingGoat/Models/WebPage/LandingPage/LandingPageRepository.cs index 42f8fce..7b4c717 100644 --- a/examples/DancingGoat/Models/WebPage/LandingPage/LandingPageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/LandingPage/LandingPageRepository.cs @@ -15,8 +15,8 @@ namespace DancingGoat.Models /// public class LandingPageRepository : ContentRepositoryBase { - public LandingPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public LandingPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItem.generated.cs b/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItem.generated.cs index 179c2c3..a338f4e 100644 --- a/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItem.generated.cs +++ b/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItem.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class NavigationItem : IWebPageFieldsSource { /// @@ -29,6 +31,7 @@ public partial class NavigationItem : IWebPageFieldsSource /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } diff --git a/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItemRepository.cs b/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItemRepository.cs index c9615c9..2d6a49e 100644 --- a/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItemRepository.cs +++ b/examples/DancingGoat/Models/WebPage/NavigationItem/NavigationItemRepository.cs @@ -19,8 +19,8 @@ public class NavigationItemRepository : ContentRepositoryBase /// /// Initializes new instance of . /// - public NavigationItemRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public NavigationItemRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPage.generated.cs b/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPage.generated.cs index c7f13e4..976108f 100644 --- a/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPage.generated.cs +++ b/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPage.generated.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using CMS.ContentEngine; using CMS.Websites; namespace DancingGoat.Models @@ -18,6 +19,7 @@ namespace DancingGoat.Models /// /// Represents a page of type . /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] public partial class PrivacyPage : IWebPageFieldsSource, ISEOFields { /// @@ -29,6 +31,7 @@ public partial class PrivacyPage : IWebPageFieldsSource, ISEOFields /// /// Represents system properties for a web page item. /// + [SystemField] public WebPageFields SystemFields { get; set; } @@ -42,5 +45,11 @@ public partial class PrivacyPage : IWebPageFieldsSource, ISEOFields /// SEOFieldsDescription. /// public string SEOFieldsDescription { get; set; } + + + /// + /// SEOFieldsAllowSearchIndexing. + /// + public bool SEOFieldsAllowSearchIndexing { get; set; } } } \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPageRepository.cs b/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPageRepository.cs index 1327842..dfcc233 100644 --- a/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPageRepository.cs +++ b/examples/DancingGoat/Models/WebPage/PrivacyPage/PrivacyPageRepository.cs @@ -15,8 +15,8 @@ public class PrivacyPageRepository : ContentRepositoryBase /// /// Initializes new instance of . /// - public PrivacyPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IWebPageQueryResultMapper mapper, IProgressiveCache cache) - : base(websiteChannelContext, executor, mapper, cache) + public PrivacyPageRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache) + : base(websiteChannelContext, executor, cache) { } diff --git a/examples/DancingGoat/Models/WebPage/ProductPage/IProductPage.cs b/examples/DancingGoat/Models/WebPage/ProductPage/IProductPage.cs new file mode 100644 index 0000000..82e308f --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductPage/IProductPage.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +using CMS.Websites; + +namespace DancingGoat.Models +{ + /// + /// Represents a common product page model. + /// + public interface IProductPage : IWebPageFieldsSource + { + /// + /// Get product related item. + /// + public IEnumerable RelatedItem { get; } + } +} diff --git a/examples/DancingGoat/Models/WebPage/ProductPage/ProductListItemViewModel.cs b/examples/DancingGoat/Models/WebPage/ProductPage/ProductListItemViewModel.cs new file mode 100644 index 0000000..35d8c22 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductPage/ProductListItemViewModel.cs @@ -0,0 +1,24 @@ +using System.Linq; +using System.Threading.Tasks; + +using CMS.Websites; + +namespace DancingGoat.Models +{ + public record ProductListItemViewModel(string Name, string ImagePath, string Url) + { + public static async Task GetViewModel(IProductPage productPage, IWebPageUrlRetriever urlRetriever, string languageName) + { + var product = productPage.RelatedItem.FirstOrDefault(); + var image = product.ProductFieldsImage.FirstOrDefault(); + + var path = (await urlRetriever.Retrieve(productPage, languageName)).RelativePath; + + return new ProductListItemViewModel( + product.ProductFieldsName, + image?.ImageFile.Url, + path + ); + } + } +} diff --git a/examples/DancingGoat/Models/WebPage/ProductPage/ProductListViewModel.cs b/examples/DancingGoat/Models/WebPage/ProductPage/ProductListViewModel.cs new file mode 100644 index 0000000..3c71a88 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductPage/ProductListViewModel.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace DancingGoat.Models +{ + public record ProductListViewModel(IEnumerable Items, Dictionary Filter) + { + } +} diff --git a/examples/DancingGoat/Models/WebPage/ProductPage/ProductPageRepository.cs b/examples/DancingGoat/Models/WebPage/ProductPage/ProductPageRepository.cs new file mode 100644 index 0000000..f2f12e5 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductPage/ProductPageRepository.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using CMS.ContentEngine; +using CMS.Helpers; +using CMS.Websites; +using CMS.Websites.Routing; + +namespace DancingGoat.Models +{ + /// + /// Represents a collection of product pages. + /// + public class ProductPageRepository : ContentRepositoryBase + { + private readonly IWebPageLinkedItemsDependencyAsyncRetriever webPageLinkedItemsDependencyRetriever; + + + /// + /// Initializes new instance of . + /// + public ProductPageRepository( + IWebsiteChannelContext websiteChannelContext, + IContentQueryExecutor executor, + IProgressiveCache cache, + IWebPageLinkedItemsDependencyAsyncRetriever webPageLinkedItemsDependencyRetriever) + : base(websiteChannelContext, executor, cache) + { + this.webPageLinkedItemsDependencyRetriever = webPageLinkedItemsDependencyRetriever; + } + + + /// + /// Returns list of web pages. + /// + public async Task> GetProducts(string treePath, string languageName, IEnumerable linkedProducts, bool includeSecuredItems = true, CancellationToken cancellationToken = default) + { + if (!linkedProducts.Any()) + { + return Enumerable.Empty(); + } + + var queryBuilder = GetQueryBuilder(treePath, languageName, linkedProducts); + + var options = new ContentQueryExecutionOptions + { + IncludeSecuredItems = includeSecuredItems + }; + + var linkedProductCacheParts = linkedProducts.Select(product => product.ProductFieldsName).Join("|"); + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, treePath, languageName, includeSecuredItems, nameof(IProductPage), linkedProductCacheParts); + + return await GetCachedQueryResult(queryBuilder, options, cacheSettings, GetDependencyCacheKeys, cancellationToken); + } + + + public async Task GetProduct(string contentTypeName, int id, string languageName, bool includeSecuredItems = true, CancellationToken cancellationToken = default) + where ProductPageType : IWebPageFieldsSource, new() + { + var queryBuilder = GetQueryBuilder(id, languageName, contentTypeName); + + var options = new ContentQueryExecutionOptions + { + IncludeSecuredItems = includeSecuredItems + }; + + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(ProductPageType), id, languageName); + + var result = await GetCachedQueryResult(queryBuilder, options, cacheSettings, GetDependencyCacheKeys, cancellationToken); + + return result.FirstOrDefault(); + } + + + private ContentItemQueryBuilder GetQueryBuilder(string treePath, string languageName, IEnumerable linkedProducts) + { + return GetQueryBuilder( + languageName, + config => config + .Linking(nameof(IProductPage.RelatedItem), linkedProducts.Select(linkedProduct => ((IContentItemFieldsSource)linkedProduct).SystemFields.ContentItemID)) + .WithLinkedItems(2) + .ForWebsite(WebsiteChannelContext.WebsiteChannelName, PathMatch.Children(treePath))); + } + + + private static ContentItemQueryBuilder GetQueryBuilder(string languageName, Action configure = null) + { + return new ContentItemQueryBuilder() + .ForContentType(CoffeePage.CONTENT_TYPE_NAME, configure) + .ForContentType(GrinderPage.CONTENT_TYPE_NAME, configure) + .InLanguage(languageName); + } + + + private ContentItemQueryBuilder GetQueryBuilder(int id, string languageName, string contentTypeName) + { + return GetQueryBuilder( + languageName, + contentTypeName, + config => config + .WithLinkedItems(2) + .ForWebsite(WebsiteChannelContext.WebsiteChannelName) + .Where(where => where.WhereEquals(nameof(IWebPageContentQueryDataContainer.WebPageItemID), id))); + } + + + private static ContentItemQueryBuilder GetQueryBuilder(string languageName, string contentTypeName, Action configureQuery = null) + { + return new ContentItemQueryBuilder() + .ForContentType(contentTypeName, configureQuery) + .InLanguage(languageName); + } + + + private async Task> GetDependencyCacheKeys(IEnumerable products, CancellationToken cancellationToken) + where ProductPageType : IWebPageFieldsSource + { + var dependencyCacheKeys = new HashSet(StringComparer.InvariantCultureIgnoreCase); + + foreach (var product in products) + { + dependencyCacheKeys.UnionWith(GetDependencyCacheKeys(product)); + } + + dependencyCacheKeys.UnionWith(await webPageLinkedItemsDependencyRetriever.Get(products.Select(productPage => productPage.SystemFields.WebPageItemID), 1, cancellationToken)); + dependencyCacheKeys.Add(CacheHelper.GetCacheItemName(null, WebsiteChannelInfo.OBJECT_TYPE, "byid", WebsiteChannelContext.WebsiteChannelID)); + + return dependencyCacheKeys; + } + + + private IEnumerable GetDependencyCacheKeys(IWebPageFieldsSource product) + { + if (product == null) + { + return Enumerable.Empty(); + } + + return new List() + { + CacheHelper.BuildCacheItemName(new[] { "webpageitem", "byid", product.SystemFields.WebPageItemID.ToString() }, false), + CacheHelper.BuildCacheItemName(new[] { "webpageitem", "bychannel", WebsiteChannelContext.WebsiteChannelName, "bypath", product.SystemFields.WebPageItemTreePath }, false), + CacheHelper.BuildCacheItemName(new[] { "webpageitem", "bychannel", WebsiteChannelContext.WebsiteChannelName, "childrenofpath", DataHelper.GetParentPath(product.SystemFields.WebPageItemTreePath) }, false), + CacheHelper.GetCacheItemName(null, ContentLanguageInfo.OBJECT_TYPE, "all") + }; + } + } +} diff --git a/examples/DancingGoat/Models/WebPage/ProductsSection/ProductSectionRepository.cs b/examples/DancingGoat/Models/WebPage/ProductsSection/ProductSectionRepository.cs new file mode 100644 index 0000000..f58f027 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductsSection/ProductSectionRepository.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using CMS.ContentEngine; +using CMS.Helpers; +using CMS.Websites; +using CMS.Websites.Routing; + +namespace DancingGoat.Models +{ + public class ProductSectionRepository : ContentRepositoryBase + { + private readonly ILinkedItemsDependencyAsyncRetriever linkedItemsDependencyRetriever; + + + public ProductSectionRepository(IWebsiteChannelContext websiteChannelContext, IContentQueryExecutor executor, IProgressiveCache cache, ILinkedItemsDependencyAsyncRetriever linkedItemsDependencyRetriever) + : base(websiteChannelContext, executor, cache) + { + this.linkedItemsDependencyRetriever = linkedItemsDependencyRetriever; + } + + + public async Task GetProductsSection(int id, string languageName, CancellationToken cancellationToken = default) + { + var queryBuilder = GetQueryBuilder(id, languageName); + + var cacheSettings = new CacheSettings(5, WebsiteChannelContext.WebsiteChannelName, nameof(ProductsSection), id, languageName); + + var result = await GetCachedQueryResult(queryBuilder, null, cacheSettings, GetDependencyCacheKeys, cancellationToken); + + return result.FirstOrDefault(); + } + + + private Task> GetDependencyCacheKeys(IEnumerable productsSection, CancellationToken cancellationToken) + { + var dependencyCacheKeys = new HashSet(StringComparer.InvariantCultureIgnoreCase); + + foreach (var productSection in productsSection) + { + dependencyCacheKeys.UnionWith(GetDependencyCacheKeys(productSection)); + } + + dependencyCacheKeys.Add(CacheHelper.GetCacheItemName(null, WebsiteChannelInfo.OBJECT_TYPE, "byid", WebsiteChannelContext.WebsiteChannelID)); + + return Task.FromResult>(dependencyCacheKeys); + } + + + private static IEnumerable GetDependencyCacheKeys(ProductsSection productsSection) + { + if (productsSection == null) + { + return Enumerable.Empty(); + } + + var cacheKeys = new HashSet(StringComparer.InvariantCultureIgnoreCase) + { + CacheHelper.BuildCacheItemName(new[] { "webpageitem", "byid", productsSection.SystemFields.WebPageItemID.ToString() }, false), + CacheHelper.BuildCacheItemName(new[] { "webpageitem", "byguid", productsSection.SystemFields.WebPageItemGUID.ToString() }, false), + }; + + return cacheKeys; + } + + + private ContentItemQueryBuilder GetQueryBuilder(int id, string languageName) + { + return new ContentItemQueryBuilder() + .ForContentType(ProductsSection.CONTENT_TYPE_NAME, + config => + config + .ForWebsite(WebsiteChannelContext.WebsiteChannelName) + .Where(where => where.WhereEquals(nameof(WebPageFields.WebPageItemID), id)) + .TopN(1)) + .InLanguage(languageName); + } + } +} diff --git a/examples/DancingGoat/Models/WebPage/ProductsSection/ProductsSection.generated.cs b/examples/DancingGoat/Models/WebPage/ProductsSection/ProductsSection.generated.cs new file mode 100644 index 0000000..2948028 --- /dev/null +++ b/examples/DancingGoat/Models/WebPage/ProductsSection/ProductsSection.generated.cs @@ -0,0 +1,37 @@ +//-------------------------------------------------------------------------------------------------- +// +// +// This code was generated by code generator tool. +// +// To customize the code use your own partial class. For more info about how to use and customize +// the generated code see the documentation at https://docs.xperience.io/. +// +// +//-------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using CMS.ContentEngine; +using CMS.Websites; + +namespace DancingGoat.Models +{ + /// + /// Represents a page of type . + /// + [RegisterContentTypeMapping(CONTENT_TYPE_NAME)] + public partial class ProductsSection : IWebPageFieldsSource + { + /// + /// Code name of the content type. + /// + public const string CONTENT_TYPE_NAME = "DancingGoat.ProductsSection"; + + + /// + /// Represents system properties for a web page item. + /// + [SystemField] + public WebPageFields SystemFields { get; set; } + } +} \ No newline at end of file diff --git a/examples/DancingGoat/Models/WebPage/SEOSchemaDataRetriever.cs b/examples/DancingGoat/Models/WebPage/SEOSchemaDataRetriever.cs index 4e700e9..29ae013 100644 --- a/examples/DancingGoat/Models/WebPage/SEOSchemaDataRetriever.cs +++ b/examples/DancingGoat/Models/WebPage/SEOSchemaDataRetriever.cs @@ -79,5 +79,42 @@ public static string GetDescriptionValue(object model) return description; } + + + /// + /// Returns value of field from the given model."/> + /// + /// + /// View model must satisfy following requirements:
+ /// - is a page builder page based on class
+ /// - implements
+ /// - implements and its base page implements
+ /// In other cases the method returns false. + ///
+ /// Model + public static bool GetSearchIndexing(object model) + { + bool allowSearchIndexing = false; + + var viewModel = model; + if (viewModel is TemplateViewModel templateViewModel) + { + viewModel = templateViewModel.GetTemplateModel(); + } + + if (viewModel is ISEOFields webPageWithSEO) + { + allowSearchIndexing = webPageWithSEO.SEOFieldsAllowSearchIndexing; + } + else if (viewModel is IWebPageBasedViewModel webPageBasedViewModel) + { + if (webPageBasedViewModel.WebPage is ISEOFields basePageWithSEO) + { + allowSearchIndexing = basePageWithSEO.SEOFieldsAllowSearchIndexing; + } + } + + return allowSearchIndexing; + } } } diff --git a/examples/DancingGoat/Program.cs b/examples/DancingGoat/Program.cs index 21a99f7..2666161 100644 --- a/examples/DancingGoat/Program.cs +++ b/examples/DancingGoat/Program.cs @@ -1,18 +1,18 @@ using DancingGoat; using DancingGoat.Models; +using Kentico.Activities.Web.Mvc; +using Kentico.Content.Web.Mvc.Routing; +using Kentico.Membership; +using Kentico.OnlineMarketing.Web.Mvc; +using Kentico.PageBuilder.Web.Mvc; +using Kentico.Web.Mvc; + using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Mvc; -using Kentico.Web.Mvc; -using Kentico.Content.Web.Mvc.Routing; -using Kentico.Membership; -using Kentico.PageBuilder.Web.Mvc; -using Kentico.OnlineMarketing.Web.Mvc; -using Kentico.Activities.Web.Mvc; - var builder = WebApplication.CreateBuilder(args); builder.Services.AddKentico(features => @@ -66,6 +66,7 @@ app.UseAuthentication(); + app.UseKentico(); if (env.IsDevelopment()) @@ -141,5 +142,11 @@ static void ConfigureMembershipServices(IServiceCollection services) }; }); + services.Configure(options => + { + // The expiration time span of 8 hours is set for demo purposes only. In production environment, set expiration according to best practices. + options.AuthenticationOptions.ExpireTimeSpan = TimeSpan.FromHours(8); + }); + services.AddAuthorization(); } diff --git a/examples/DancingGoat/README.md b/examples/DancingGoat/README.md index 245eadf..4428c25 100644 --- a/examples/DancingGoat/README.md +++ b/examples/DancingGoat/README.md @@ -24,10 +24,10 @@ If you change the site's content model (add or remove fields, define new content For _reusable field schemas_: ```powershell -dotnet run --no-build -- --kxp-codegen --location "./Models/Schema/" --type ReusableFieldSchemas --include "SEOFields" --namespace "DancingGoat.Models" +dotnet run --no-build -- --kxp-codegen --location "./Models/Schema/" --type ReusableFieldSchemas --namespace "DancingGoat.Models" ``` -This command regenerates the interface for the `SEOFields` reusable schema. Note that the `namespace` must match that of the assigned content types. +This command regenerates the interfaces for all reusable field schemas in the project. Note that the specified `--namespace` must match the namespace where content type code files that reference the schemas are generated. You will get uncompilable code otherwise. For _reusable_ content types: diff --git a/examples/DancingGoat/Readme.txt b/examples/DancingGoat/Readme.txt deleted file mode 100644 index 2f558d0..0000000 --- a/examples/DancingGoat/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -This project provides a starting point for developing an Xperience by Kentico website, along with tools and configuration for deploying the site to the SaaS environment. - -For more information visit: -https://docs.xperience.io/x/IgKQC \ No newline at end of file diff --git a/examples/DancingGoat/DataProtectionSamples/DancingGoatSamplesModule.cs b/examples/DancingGoat/Samples/DataProtection/DancingGoatSamplesModule.cs similarity index 79% rename from examples/DancingGoat/DataProtectionSamples/DancingGoatSamplesModule.cs rename to examples/DancingGoat/Samples/DataProtection/DancingGoatSamplesModule.cs index 70c8181..afc4c92 100644 --- a/examples/DancingGoat/DataProtectionSamples/DancingGoatSamplesModule.cs +++ b/examples/DancingGoat/Samples/DataProtection/DancingGoatSamplesModule.cs @@ -30,16 +30,16 @@ internal class DancingGoatSamplesModule : Module { private const string DATA_PROTECTION_SAMPLES_ENABLED_SETTINGS_KEY_NAME = "DataProtectionSamplesEnabled"; - private IContactInfoProvider contactInfoProvider; + private IInfoProvider contactInfoProvider; private IMemberInfoProvider memberInfoProvider; private IInfoProvider consentAgreementInfoProvider; - private IBizFormInfoProvider bizFormInfoProvider; - private IAccountContactInfoProvider accountContactInfoProvider; - private ISettingsKeyInfoProvider settingsKeyInfoProvider; - private IActivityInfoProvider activityInfoProvider; - private ICountryInfoProvider countryInfoProvider; - private IStateInfoProvider stateInfoProvider; - private IAccountInfoProvider accountInfoProvider; + private IInfoProvider bizFormInfoProvider; + private IInfoProvider accountContactInfoProvider; + private IInfoProvider settingsKeyInfoProvider; + private IInfoProvider activityInfoProvider; + private IInfoProvider countryInfoProvider; + private IInfoProvider stateInfoProvider; + private IInfoProvider accountInfoProvider; /// @@ -57,16 +57,16 @@ protected override void OnInit() { base.OnInit(); - contactInfoProvider = Service.Resolve(); + contactInfoProvider = Service.Resolve>(); memberInfoProvider = Service.Resolve(); consentAgreementInfoProvider = Service.Resolve>(); - bizFormInfoProvider = Service.Resolve(); - accountContactInfoProvider = Service.Resolve(); - settingsKeyInfoProvider = Service.Resolve(); - activityInfoProvider = Service.Resolve(); - countryInfoProvider = Service.Resolve(); - stateInfoProvider = Service.Resolve(); - accountInfoProvider = Service.Resolve(); + bizFormInfoProvider = Service.Resolve>(); + accountContactInfoProvider = Service.Resolve>(); + settingsKeyInfoProvider = Service.Resolve>(); + activityInfoProvider = Service.Resolve>(); + countryInfoProvider = Service.Resolve>(); + stateInfoProvider = Service.Resolve>(); + accountInfoProvider = Service.Resolve>(); InitializeSamples(); } @@ -107,7 +107,7 @@ internal void RegisterSamples() accountContactInfoProvider, accountInfoProvider, bizFormInfoProvider)); PersonalDataCollectorRegister.Instance.Add(new SampleMemberDataCollector()); - PersonalDataEraserRegister.Instance.Add(new SampleContactPersonalDataEraser(consentAgreementInfoProvider, bizFormInfoProvider, accountContactInfoProvider, contactInfoProvider)); + PersonalDataEraserRegister.Instance.Add(new SampleContactPersonalDataEraser(consentAgreementInfoProvider, bizFormInfoProvider, accountContactInfoProvider, contactInfoProvider, activityInfoProvider)); PersonalDataEraserRegister.Instance.Add(new SampleMemberPersonalDataEraser(memberInfoProvider)); RegisterConsentRevokeHandler(); @@ -121,7 +121,7 @@ internal void DeleteContactActivities(ContactInfo contact) { "deleteActivities", true } }; - new SampleContactPersonalDataEraser(consentAgreementInfoProvider, bizFormInfoProvider, accountContactInfoProvider, contactInfoProvider) + new SampleContactPersonalDataEraser(consentAgreementInfoProvider, bizFormInfoProvider, accountContactInfoProvider, contactInfoProvider, activityInfoProvider) .Erase(new[] { contact }, configuration); } diff --git a/examples/DancingGoat/DataProtectionSamples/IdentityCollectors/SampleContactInfoIdentityCollector.cs b/examples/DancingGoat/Samples/DataProtection/IdentityCollectors/SampleContactInfoIdentityCollector.cs similarity index 91% rename from examples/DancingGoat/DataProtectionSamples/IdentityCollectors/SampleContactInfoIdentityCollector.cs rename to examples/DancingGoat/Samples/DataProtection/IdentityCollectors/SampleContactInfoIdentityCollector.cs index b546b27..40ed5be 100644 --- a/examples/DancingGoat/DataProtectionSamples/IdentityCollectors/SampleContactInfoIdentityCollector.cs +++ b/examples/DancingGoat/Samples/DataProtection/IdentityCollectors/SampleContactInfoIdentityCollector.cs @@ -12,14 +12,14 @@ namespace Samples.DancingGoat /// internal class SampleContactInfoIdentityCollector : IIdentityCollector { - private readonly IContactInfoProvider contactInfoProvider; + private readonly IInfoProvider contactInfoProvider; /// /// Initializes a new instance of the class. /// /// Contact info provider. - public SampleContactInfoIdentityCollector(IContactInfoProvider contactInfoProvider) + public SampleContactInfoIdentityCollector(IInfoProvider contactInfoProvider) { this.contactInfoProvider = contactInfoProvider; } diff --git a/examples/DancingGoat/DataProtectionSamples/IdentityCollectors/SampleMemberInfoIdentityCollector.cs b/examples/DancingGoat/Samples/DataProtection/IdentityCollectors/SampleMemberInfoIdentityCollector.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/IdentityCollectors/SampleMemberInfoIdentityCollector.cs rename to examples/DancingGoat/Samples/DataProtection/IdentityCollectors/SampleMemberInfoIdentityCollector.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/CollectedColumn.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/CollectedColumn.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/CollectedColumn.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/CollectedColumn.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollector.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollector.cs similarity index 80% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollector.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollector.cs index 11612bb..47fcdb7 100644 --- a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollector.cs +++ b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollector.cs @@ -14,13 +14,13 @@ namespace Samples.DancingGoat /// internal class SampleContactDataCollector : IPersonalDataCollector { - private readonly IActivityInfoProvider activityInfoProvider; - private readonly ICountryInfoProvider countryInfoProvider; - private readonly IStateInfoProvider stateInfoProvider; + private readonly IInfoProvider activityInfoProvider; + private readonly IInfoProvider countryInfoProvider; + private readonly IInfoProvider stateInfoProvider; private readonly IInfoProvider consentAgreementInfoProvider; - private readonly IAccountContactInfoProvider accountContactInfoProvider; - private readonly IAccountInfoProvider accountInfoProvider; - private readonly IBizFormInfoProvider bizFormInfoProvider; + private readonly IInfoProvider accountContactInfoProvider; + private readonly IInfoProvider accountInfoProvider; + private readonly IInfoProvider bizFormInfoProvider; /// @@ -34,13 +34,13 @@ internal class SampleContactDataCollector : IPersonalDataCollector /// Account info provider. /// BizForm info provider. public SampleContactDataCollector( - IActivityInfoProvider activityInfoProvider, - ICountryInfoProvider countryInfoProvider, - IStateInfoProvider stateInfoProvider, + IInfoProvider activityInfoProvider, + IInfoProvider countryInfoProvider, + IInfoProvider stateInfoProvider, IInfoProvider consentAgreementInfoProvider, - IAccountContactInfoProvider accountContactInfoProvider, - IAccountInfoProvider accountInfoProvider, - IBizFormInfoProvider bizFormInfoProvider) + IInfoProvider accountContactInfoProvider, + IInfoProvider accountInfoProvider, + IInfoProvider bizFormInfoProvider) { this.activityInfoProvider = activityInfoProvider; this.countryInfoProvider = countryInfoProvider; diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollectorCore.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollectorCore.cs similarity index 97% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollectorCore.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollectorCore.cs index 0cf1b6b..6e78567 100644 --- a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleContactDataCollectorCore.cs +++ b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleContactDataCollectorCore.cs @@ -20,13 +20,13 @@ namespace Samples.DancingGoat internal class SampleContactDataCollectorCore { private readonly IPersonalDataWriter writer; - private readonly IActivityInfoProvider activityInfoProvider; - private readonly ICountryInfoProvider countryInfoProvider; - private readonly IStateInfoProvider stateInfoProvider; + private readonly IInfoProvider activityInfoProvider; + private readonly IInfoProvider countryInfoProvider; + private readonly IInfoProvider stateInfoProvider; private readonly IInfoProvider consentAgreementInfoProvider; - private readonly IAccountContactInfoProvider accountContactInfoProvider; - private readonly IAccountInfoProvider accountInfoProvider; - private readonly IBizFormInfoProvider bizFormInfoProvider; + private readonly IInfoProvider accountContactInfoProvider; + private readonly IInfoProvider accountInfoProvider; + private readonly IInfoProvider bizFormInfoProvider; // Lists store Tuples of database column names and their corresponding display names. private readonly List contactInfoColumns = new List { @@ -325,13 +325,13 @@ private object TransformConsentAction(string columnName, object columnValue) /// BizForm info provider. public SampleContactDataCollectorCore( IPersonalDataWriter writer, - IActivityInfoProvider activityInfoProvider, - ICountryInfoProvider countryInfoProvider, - IStateInfoProvider stateInfoProvider, + IInfoProvider activityInfoProvider, + IInfoProvider countryInfoProvider, + IInfoProvider stateInfoProvider, IInfoProvider consentAgreementInfoProvider, - IAccountContactInfoProvider accountContactInfoProvider, - IAccountInfoProvider accountInfoProvider, - IBizFormInfoProvider bizFormInfoProvider) + IInfoProvider accountContactInfoProvider, + IInfoProvider accountInfoProvider, + IInfoProvider bizFormInfoProvider) { this.writer = writer; this.activityInfoProvider = activityInfoProvider; diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleMemberDataCollector.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleMemberDataCollector.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleMemberDataCollector.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleMemberDataCollector.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleMemberDataCollectorCore.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleMemberDataCollectorCore.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/SampleMemberDataCollectorCore.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/SampleMemberDataCollectorCore.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/HumanReadablePersonalDataWriter.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/HumanReadablePersonalDataWriter.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/HumanReadablePersonalDataWriter.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/HumanReadablePersonalDataWriter.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/IPersonalDataWriter.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/IPersonalDataWriter.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/IPersonalDataWriter.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/IPersonalDataWriter.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/XmlPersonalDataWriter.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/XmlPersonalDataWriter.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataCollectors/Writers/XmlPersonalDataWriter.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataCollectors/Writers/XmlPersonalDataWriter.cs diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataErasers/SampleContactPersonalDataEraser.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataErasers/SampleContactPersonalDataEraser.cs similarity index 90% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataErasers/SampleContactPersonalDataEraser.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataErasers/SampleContactPersonalDataEraser.cs index ffcdb7b..c5a73f0 100644 --- a/examples/DancingGoat/DataProtectionSamples/PersonalDataErasers/SampleContactPersonalDataEraser.cs +++ b/examples/DancingGoat/Samples/DataProtection/PersonalDataErasers/SampleContactPersonalDataEraser.cs @@ -36,9 +36,10 @@ internal class SampleContactPersonalDataEraser : IPersonalDataEraser }; private readonly IInfoProvider consentAgreementInfoProvider; - private readonly IBizFormInfoProvider bizFormInfoProvider; - private readonly IAccountContactInfoProvider accountContactInfoProvider; - private readonly IContactInfoProvider contactInfoProvider; + private readonly IInfoProvider bizFormInfoProvider; + private readonly IInfoProvider accountContactInfoProvider; + private readonly IInfoProvider contactInfoProvider; + private readonly IInfoProvider activityInfoProvider; /// @@ -48,16 +49,19 @@ internal class SampleContactPersonalDataEraser : IPersonalDataEraser /// BizForm info provider. /// Account contact info provider. /// Contact info provider. + /// Activity info provider. public SampleContactPersonalDataEraser( IInfoProvider consentAgreementInfoProvider, - IBizFormInfoProvider bizFormInfoProvider, - IAccountContactInfoProvider accountContactInfoProvider, - IContactInfoProvider contactInfoProvider) + IInfoProvider bizFormInfoProvider, + IInfoProvider accountContactInfoProvider, + IInfoProvider contactInfoProvider, + IInfoProvider activityInfoProvider) { this.consentAgreementInfoProvider = consentAgreementInfoProvider; this.bizFormInfoProvider = bizFormInfoProvider; this.accountContactInfoProvider = accountContactInfoProvider; this.contactInfoProvider = contactInfoProvider; + this.activityInfoProvider = activityInfoProvider; } @@ -119,7 +123,7 @@ private void DeleteSubmittedFormsActivities(ICollection contactIds, IDictio if (configuration.TryGetValue("DeleteSubmittedFormsActivities", out object deleteSubmittedFormsActivities) && ValidationHelper.GetBoolean(deleteSubmittedFormsActivities, false)) { - ActivityInfoProvider.ProviderObject.BulkDelete(new WhereCondition().WhereEquals("ActivityType", PredefinedActivityType.BIZFORM_SUBMIT) + activityInfoProvider.BulkDelete(new WhereCondition().WhereEquals("ActivityType", PredefinedActivityType.BIZFORM_SUBMIT) .WhereIn("ActivityContactID", contactIds)); } } @@ -173,7 +177,7 @@ private void DeleteActivities(List contactIds, IDictionary if (configuration.TryGetValue("deleteActivities", out object deleteActivities) && ValidationHelper.GetBoolean(deleteActivities, false)) { - ActivityInfoProvider.ProviderObject.BulkDelete(new WhereCondition().WhereIn("ActivityContactID", contactIds)); + activityInfoProvider.BulkDelete(new WhereCondition().WhereIn("ActivityContactID", contactIds)); } } diff --git a/examples/DancingGoat/DataProtectionSamples/PersonalDataErasers/SampleMemberPersonalDataEraser.cs b/examples/DancingGoat/Samples/DataProtection/PersonalDataErasers/SampleMemberPersonalDataEraser.cs similarity index 100% rename from examples/DancingGoat/DataProtectionSamples/PersonalDataErasers/SampleMemberPersonalDataEraser.cs rename to examples/DancingGoat/Samples/DataProtection/PersonalDataErasers/SampleMemberPersonalDataEraser.cs diff --git a/examples/DancingGoat/Samples/EmailActivityTracking/EmailActivityTrackingEvaluator.cs b/examples/DancingGoat/Samples/EmailActivityTracking/EmailActivityTrackingEvaluator.cs new file mode 100644 index 0000000..6473870 --- /dev/null +++ b/examples/DancingGoat/Samples/EmailActivityTracking/EmailActivityTrackingEvaluator.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; + +using CMS.ContactManagement; +using CMS.DataEngine; +using CMS.DataProtection; +using CMS.EmailLibrary; + +using DancingGoat.Helpers.Generator; + +using Kentico.OnlineMarketing.Web.Mvc; + +namespace Samples.DancingGoat; + +/// +/// Example implementation of . +/// It uses consent generated by the data protection (GDPR) demo. To make it work, +/// you need to visit Sample data generator application and generate the data. +/// Without the consent, email activity tracking is disabled. +/// +public class EmailActivityTrackingEvaluator : IEmailActivityTrackingEvaluator +{ + private readonly IConsentAgreementService consentAgreementService; + private readonly IInfoProvider consentInfoProvider; + + + /// + /// Initializes an instance of the class. + /// + public EmailActivityTrackingEvaluator(IConsentAgreementService consentAgreementService, IInfoProvider consentInfoProvider) + { + this.consentAgreementService = consentAgreementService; + this.consentInfoProvider = consentInfoProvider; + } + + + /// + /// Determines whether the email activities can be tracked for the contact. + /// + /// Contact info of the recipient. + /// Email configuration info. + /// True if the contact has agreed to tracking by giving consent. + /// The consent is generated by . + public async Task IsTrackingAllowed(ContactInfo contact, EmailConfigurationInfo emailConfiguration) + { + var consent = await consentInfoProvider.GetAsync(TrackingConsentGenerator.CONSENT_NAME); + + return consent is not null && consentAgreementService.IsAgreed(contact, consent); + } +} diff --git a/examples/DancingGoat/Services/IServiceCollectionExtensions.cs b/examples/DancingGoat/Services/IServiceCollectionExtensions.cs index 97d96a3..3abf54e 100644 --- a/examples/DancingGoat/Services/IServiceCollectionExtensions.cs +++ b/examples/DancingGoat/Services/IServiceCollectionExtensions.cs @@ -1,8 +1,12 @@ using DancingGoat.Models; using DancingGoat.ViewComponents; +using Kentico.OnlineMarketing.Web.Mvc; + using Microsoft.Extensions.DependencyInjection; +using Samples.DancingGoat; + namespace DancingGoat { public static class IServiceCollectionExtensions @@ -16,6 +20,7 @@ public static void AddDancingGoatServices(this IServiceCollection services) AddRepositories(services); services.AddSingleton(); + services.AddSingleton(); } @@ -27,13 +32,15 @@ private static void AddRepositories(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); } diff --git a/examples/DancingGoat/StorageInitializationModule.cs b/examples/DancingGoat/StorageInitializationModule.cs deleted file mode 100644 index ef500f9..0000000 --- a/examples/DancingGoat/StorageInitializationModule.cs +++ /dev/null @@ -1,94 +0,0 @@ -using CMS; -using CMS.Core; -using CMS.DataEngine; -using CMS.IO; - -using DancingGoat; - -using Kentico.Xperience.AzureStorage; - -// Registers the storage module into the system -[assembly: RegisterModule(typeof(StorageInitializationModule))] - -namespace DancingGoat -{ - public class StorageInitializationModule : Module - { - /// - /// Local directory used for deployment of blob storage contents. - /// - private const string LOCAL_STORAGE_ASSETS_DIRECTORY_NAME = "$StorageAssets"; - - - /// - /// Default container name within the blob storage. - /// - private const string CONTAINER_NAME = "default"; - - - private IWebHostEnvironment mEnvironment; - - - /// - /// Gets the web hosting environment information. - /// - public IWebHostEnvironment Environment - { - get - { - return mEnvironment ??= Service.Resolve(); - } - } - - - // Module class constructor, the system registers the module - public StorageInitializationModule() - : base(nameof(StorageInitializationModule)) - { - } - - - // Contains initialization code that is executed when the application starts - protected override void OnInit() - { - base.OnInit(); - - if (Environment.IsProduction()) - { - // Maps the assets directory (e.g. media files) to the Azure storage provider - MapAzureStoragePath($"~/assets/"); - MapAzureStoragePath($"~/BizFormFiles"); - } - else - { - // Maps contents of the assets directory which are not handled by the CD tool (media files) - // to the dedicated local folder. - MapLocalStoragePath($"~/assets/media"); - } - } - - - private void MapAzureStoragePath(string path) - { - // Creates a new StorageProvider instance for Azure - var provider = AzureStorageProvider.Create(); - - // Specifies the target container - provider.CustomRootPath = CONTAINER_NAME; - provider.PublicExternalFolderObject = false; - - StorageHelper.MapStoragePath(path, provider); - } - - - private void MapLocalStoragePath(string path) - { - // Creates a new StorageProvider instance for local storage - var provider = StorageProvider.CreateFileSystemStorageProvider(); - - provider.CustomRootPath = $"{LOCAL_STORAGE_ASSETS_DIRECTORY_NAME}/{CONTAINER_NAME}"; - - StorageHelper.MapStoragePath(path, provider); - } - } -} diff --git a/examples/DancingGoat/Views/DancingGoatCoffee/Detail.cshtml b/examples/DancingGoat/Views/DancingGoatCoffee/Detail.cshtml new file mode 100644 index 0000000..bf29fe6 --- /dev/null +++ b/examples/DancingGoat/Views/DancingGoatCoffee/Detail.cshtml @@ -0,0 +1,41 @@ +@using DancingGoat.Models + +@model CoffeeDetailViewModel; + +@{ + ViewData["PageClass"] = "inverted"; + ViewData["Title"] = Model.Name; +} + +
+
+
+
+

@Model.Name

+
+
+
+ +
+ @foreach (var item in Model.Processing.Union(Model.Tastes)) + { +
+ @item.Title +
+ } +
+ +
+
+ @if (!string.IsNullOrEmpty(Model.ImageUrl)) + { +
+ @Model.Name +
+ } +
+ @Html.Raw(Model.Description) +
+
+
+
\ No newline at end of file diff --git a/examples/DancingGoat/Views/DancingGoatContacts/Index.cshtml b/examples/DancingGoat/Views/DancingGoatContacts/Index.cshtml index 56f62cb..a63b088 100644 --- a/examples/DancingGoat/Views/DancingGoatContacts/Index.cshtml +++ b/examples/DancingGoat/Views/DancingGoatContacts/Index.cshtml @@ -30,14 +30,12 @@ @foreach (var cafe in @Model.CompanyCafes) {
-
+

@cafe.Name

- - @cafe.Street, @cafe.City
- @cafe.Country -
+ @cafe.Street, @cafe.City
+ @cafe.Country

@cafe.Phone

@@ -45,4 +43,15 @@
}
+ +

@HtmlLocalizer["Other places where you can drink our coffee"]

+
+ @foreach (var partnerCafe in Model.PartnerCafes) + { +

@partnerCafe.City, @partnerCafe.Country

+

+ @partnerCafe.Name, @partnerCafe.Street, @partnerCafe.Phone +

+ } +
\ No newline at end of file diff --git a/examples/DancingGoat/Views/DancingGoatGrinder/Detail.cshtml b/examples/DancingGoat/Views/DancingGoatGrinder/Detail.cshtml new file mode 100644 index 0000000..67c293f --- /dev/null +++ b/examples/DancingGoat/Views/DancingGoatGrinder/Detail.cshtml @@ -0,0 +1,41 @@ +@using DancingGoat.Models + +@model GrinderDetailViewModel; + +@{ + ViewData["PageClass"] = "inverted"; + ViewData["Title"] = Model.Name; +} + +
+
+
+
+

@Model.Name

+
+
+
+ +
+ @foreach (var item in Model.Manufacturers.Union(Model.Type)) + { +
+ @item.Title +
+ } +
+ +
+
+ @if (!string.IsNullOrEmpty(Model.ImageUrl)) + { +
+ @Model.Name +
+ } +
+ @Html.Raw(Model.Description) +
+
+
+
\ No newline at end of file diff --git a/examples/DancingGoat/Views/DancingGoatProduct/Filter.cshtml b/examples/DancingGoat/Views/DancingGoatProduct/Filter.cshtml new file mode 100644 index 0000000..3c00982 --- /dev/null +++ b/examples/DancingGoat/Views/DancingGoatProduct/Filter.cshtml @@ -0,0 +1,15 @@ +@using DancingGoat.Models + +@model Dictionary + +
+ @Html.Kentico().PageData() + + @foreach (var key in Model.Keys) + { +

@HtmlLocalizer[Model[key].Name]

+ @Html.HiddenFor(m => Model[key].Name) + @Html.HiddenFor(m => Model[key].CodeName) + @Html.EditorFor(model => model[key].Tags) + } +
\ No newline at end of file diff --git a/examples/DancingGoat/Views/DancingGoatProduct/Index.cshtml b/examples/DancingGoat/Views/DancingGoatProduct/Index.cshtml new file mode 100644 index 0000000..ef6134c --- /dev/null +++ b/examples/DancingGoat/Views/DancingGoatProduct/Index.cshtml @@ -0,0 +1,29 @@ +@using DancingGoat.Models + +@model ProductListViewModel + +@{ + ViewData["PageClass"] = "inverted"; +} + +
+
+
+ + +
+ +
+
+
+
+ +@section Scripts { + + + +} \ No newline at end of file diff --git a/examples/DancingGoat/Views/DancingGoatProduct/ProductsList.cshtml b/examples/DancingGoat/Views/DancingGoatProduct/ProductsList.cshtml new file mode 100644 index 0000000..c2b1902 --- /dev/null +++ b/examples/DancingGoat/Views/DancingGoatProduct/ProductsList.cshtml @@ -0,0 +1,18 @@ +@using DancingGoat.Models + +@model IEnumerable + +@if (Model.Any()) +{ + foreach (var product in Model) + { + +
+ @Html.DisplayFor(m => product, "ProductListItem") +
+ } +} +else +{ + +} \ No newline at end of file diff --git a/examples/DancingGoat/Views/Shared/DisplayTemplates/ProductListItem.cshtml b/examples/DancingGoat/Views/Shared/DisplayTemplates/ProductListItem.cshtml new file mode 100644 index 0000000..27684d0 --- /dev/null +++ b/examples/DancingGoat/Views/Shared/DisplayTemplates/ProductListItem.cshtml @@ -0,0 +1,15 @@ +@using DancingGoat.Models + +@model ProductListItemViewModel + + \ No newline at end of file diff --git a/examples/DancingGoat/Views/Shared/EditorTemplates/TagViewModel.cshtml b/examples/DancingGoat/Views/Shared/EditorTemplates/TagViewModel.cshtml new file mode 100644 index 0000000..f7022bd --- /dev/null +++ b/examples/DancingGoat/Views/Shared/EditorTemplates/TagViewModel.cshtml @@ -0,0 +1,10 @@ +@using DancingGoat.Models + +@model TagViewModel + +@Html.HiddenFor(m => Model.Value) +@Html.HiddenFor(m => Model.Name) + + + + \ No newline at end of file diff --git a/examples/DancingGoat/Views/Shared/_DancingGoatLayout.cshtml b/examples/DancingGoat/Views/Shared/_DancingGoatLayout.cshtml index 3154812..31201d1 100644 --- a/examples/DancingGoat/Views/Shared/_DancingGoatLayout.cshtml +++ b/examples/DancingGoat/Views/Shared/_DancingGoatLayout.cshtml @@ -47,6 +47,10 @@ + @if (!SEOSchemaModelDataRetriever.GetSearchIndexing(Model)) + { + + } @if (!string.IsNullOrEmpty(description)) { diff --git a/examples/DancingGoat/Views/Shared/_LandingPageLayout.cshtml b/examples/DancingGoat/Views/Shared/_LandingPageLayout.cshtml index b48dd9c..e19f04d 100644 --- a/examples/DancingGoat/Views/Shared/_LandingPageLayout.cshtml +++ b/examples/DancingGoat/Views/Shared/_LandingPageLayout.cshtml @@ -23,6 +23,10 @@ + @if (!SEOSchemaModelDataRetriever.GetSearchIndexing(Model.GetTemplateModel())) + { + + } @if (!string.IsNullOrEmpty(description)) { @@ -31,6 +35,7 @@ @title + @Html.Kentico().ActivityLoggingScriptV2()
diff --git a/examples/DancingGoat/Views/_ViewImports.cshtml b/examples/DancingGoat/Views/_ViewImports.cshtml index f0ab235..dd9ae51 100644 --- a/examples/DancingGoat/Views/_ViewImports.cshtml +++ b/examples/DancingGoat/Views/_ViewImports.cshtml @@ -13,6 +13,5 @@ @addTagHelper *, Kentico.Content.Web.Mvc @addTagHelper *, Kentico.Web.Mvc @addTagHelper *, DancingGoat -@addTagHelper *, CloudWebSite -@inject IHtmlLocalizer HtmlLocalizer \ No newline at end of file +@inject IHtmlLocalizer HtmlLocalizer diff --git a/examples/DancingGoat/assets/ContentItems/1e/1efd72c9-f3ff-4fbf-ac90-f18b7fe7b40e/cc721195-df8f-4799-b974-5ade63036cab/510968cb-ef94-433c-ac43-2ae7679e92d4.jpg b/examples/DancingGoat/assets/ContentItems/1e/1efd72c9-f3ff-4fbf-ac90-f18b7fe7b40e/cc721195-df8f-4799-b974-5ade63036cab/510968cb-ef94-433c-ac43-2ae7679e92d4.jpg new file mode 100644 index 0000000..e904d39 Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/1e/1efd72c9-f3ff-4fbf-ac90-f18b7fe7b40e/cc721195-df8f-4799-b974-5ade63036cab/510968cb-ef94-433c-ac43-2ae7679e92d4.jpg differ diff --git a/examples/DancingGoat/assets/ContentItems/60/60771371-3371-42cd-a101-8ffb6d90f318/cc721195-df8f-4799-b974-5ade63036cab/a0fee33a-d7bc-4f4e-ad0b-5154e0c131b3.jpg b/examples/DancingGoat/assets/ContentItems/60/60771371-3371-42cd-a101-8ffb6d90f318/cc721195-df8f-4799-b974-5ade63036cab/a0fee33a-d7bc-4f4e-ad0b-5154e0c131b3.jpg new file mode 100644 index 0000000..e904d39 Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/60/60771371-3371-42cd-a101-8ffb6d90f318/cc721195-df8f-4799-b974-5ade63036cab/a0fee33a-d7bc-4f4e-ad0b-5154e0c131b3.jpg differ diff --git a/examples/DancingGoat/assets/ContentItems/8a/8a4b970a-99d0-404a-8e9c-82a188731328/cc721195-df8f-4799-b974-5ade63036cab/12d13cb4-6639-4166-9de1-8a1377cc840d.jpg b/examples/DancingGoat/assets/ContentItems/8a/8a4b970a-99d0-404a-8e9c-82a188731328/cc721195-df8f-4799-b974-5ade63036cab/12d13cb4-6639-4166-9de1-8a1377cc840d.jpg new file mode 100644 index 0000000..f99a72b Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/8a/8a4b970a-99d0-404a-8e9c-82a188731328/cc721195-df8f-4799-b974-5ade63036cab/12d13cb4-6639-4166-9de1-8a1377cc840d.jpg differ diff --git a/examples/DancingGoat/assets/ContentItems/da/da0f6058-65b8-48d1-838d-b4d164839cb9/cc721195-df8f-4799-b974-5ade63036cab/390a5c69-11e2-41f0-9cb0-a716af074393.jpg b/examples/DancingGoat/assets/ContentItems/da/da0f6058-65b8-48d1-838d-b4d164839cb9/cc721195-df8f-4799-b974-5ade63036cab/390a5c69-11e2-41f0-9cb0-a716af074393.jpg new file mode 100644 index 0000000..a5eacfd Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/da/da0f6058-65b8-48d1-838d-b4d164839cb9/cc721195-df8f-4799-b974-5ade63036cab/390a5c69-11e2-41f0-9cb0-a716af074393.jpg differ diff --git a/examples/DancingGoat/assets/ContentItems/dd/dde0b153-206f-4adc-924a-8d6e16a7df9e/cc721195-df8f-4799-b974-5ade63036cab/6af2458f-e1b7-4d0c-b0aa-769f0e677551.jpg b/examples/DancingGoat/assets/ContentItems/dd/dde0b153-206f-4adc-924a-8d6e16a7df9e/cc721195-df8f-4799-b974-5ade63036cab/6af2458f-e1b7-4d0c-b0aa-769f0e677551.jpg new file mode 100644 index 0000000..a5eacfd Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/dd/dde0b153-206f-4adc-924a-8d6e16a7df9e/cc721195-df8f-4799-b974-5ade63036cab/6af2458f-e1b7-4d0c-b0aa-769f0e677551.jpg differ diff --git a/examples/DancingGoat/assets/ContentItems/fe/fe59453e-5e59-422f-97b7-0da25ac54354/cc721195-df8f-4799-b974-5ade63036cab/c7037ecc-202b-423a-bce7-12d010eb7c2f.jpg b/examples/DancingGoat/assets/ContentItems/fe/fe59453e-5e59-422f-97b7-0da25ac54354/cc721195-df8f-4799-b974-5ade63036cab/c7037ecc-202b-423a-bce7-12d010eb7c2f.jpg new file mode 100644 index 0000000..f99a72b Binary files /dev/null and b/examples/DancingGoat/assets/ContentItems/fe/fe59453e-5e59-422f-97b7-0da25ac54354/cc721195-df8f-4799-b974-5ade63036cab/c7037ecc-202b-423a-bce7-12d010eb7c2f.jpg differ diff --git a/examples/DancingGoat/packages.lock.json b/examples/DancingGoat/packages.lock.json index 370a617..b435db9 100644 --- a/examples/DancingGoat/packages.lock.json +++ b/examples/DancingGoat/packages.lock.json @@ -4,53 +4,53 @@ "net8.0": { "Kentico.Xperience.Admin": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "22V9ocfYRxpJeBAigIbRUmCiONalCCfmQnpSVap1qQgd8+NP4bvYH5IA3yoFSAU9p93ovfyZVbe0YgUAqNYRHw==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "oLhibuIC4/CRDih3EYtFv42a1s+I9+p2F/GfqOTLmysZswfRDSKlX9nkFX/bu/eVw25YgbPgaV2Kv+3jYGz58g==", "dependencies": { "Kentico.Aira.Client": "1.0.25", - "Kentico.Xperience.WebApp": "[28.3.1]", - "Microsoft.AspNetCore.SpaServices.Extensions": "6.0.27", - "Microsoft.Extensions.FileProviders.Embedded": "6.0.27" + "Kentico.Xperience.WebApp": "[29.5.3]", + "Microsoft.AspNetCore.SpaServices.Extensions": "6.0.33", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.33" } }, "Kentico.Xperience.AzureStorage": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "uBOgWJHlMzmO6+BZk1o2BDrSvdDioKftpQ/ljVm+4y/qVBBXqFli7vHbW/bEmdla9rj1T8bTw37OgklM/gGNRA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "d27b5FANBrdWR4uJEeEVnqfta97FLi5vreWr0lmdwqfHaUQMpI87vJ7Q+v+u/NQ+qtlBtyor6fN03vYwOLln4Q==", "dependencies": { - "Azure.Storage.Blobs": "12.19.1", - "Azure.Storage.Queues": "12.17.1", - "Kentico.Xperience.Core": "28.3.1", + "Azure.Storage.Blobs": "12.21.2", + "Azure.Storage.Queues": "12.19.1", + "Kentico.Xperience.Core": "29.5.3", "Newtonsoft.Json": "13.0.3" } }, "Kentico.Xperience.ImageProcessing": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "p2q/NR6UHFuiMyTjAykqYe/NBcVag5VJbkjgYte1Enib+QiysPlfoHOesFNqWbK8AAoJfCAYwQ8NRQwWOOedGA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "9Xr0xq5rceovyDrsA9yso6bDNHCdDsWuOg13MSy4szWNEnUIMZsuFkgYnocEqmKEUlUD//KTwKL/VBQijhOK3g==", "dependencies": { - "Kentico.Xperience.Core": "28.3.1", - "SkiaSharp": "2.88.7", - "SkiaSharp.NativeAssets.Linux.NoDependencies": "2.88.7" + "Kentico.Xperience.Core": "29.5.3", + "SkiaSharp": "2.88.8", + "SkiaSharp.NativeAssets.Linux.NoDependencies": "2.88.8" } }, "Kentico.Xperience.WebApp": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "I9gz6Gq1XLbXTQ/RtCDuWpBVMYurT4+KrwfKublmxXQILpLwQzvFv5GRYe9Fa3AaHEThIdttSSv2l1y3ybzbqA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "n4V4V3fVq8ZRrus2I9RF8KcD0fX0QWE2aGsbC6Pb8g+kcai1TFHk/dsiOzDCSLSRFGMVyl/xt0o1OOBedXdWUg==", "dependencies": { "CommandLineParser": "2.9.1", - "HotChocolate.AspNetCore": "13.8.1", - "HotChocolate.Data": "13.8.1", - "HtmlSanitizer": "8.0.843", - "Kentico.Xperience.Core": "[28.3.1]", - "Microsoft.Extensions.FileProviders.Embedded": "6.0.27", - "Microsoft.Extensions.Localization": "6.0.27", - "System.Runtime.Caching": "8.0.0" + "HotChocolate.AspNetCore": "13.9.12", + "HotChocolate.Data": "13.9.12", + "HtmlSanitizer": "8.1.870", + "Kentico.Xperience.Core": "[29.5.3]", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.33", + "Microsoft.Extensions.Localization": "6.0.33" } }, "SonarAnalyzer.CSharp": { @@ -78,10 +78,11 @@ }, "Azure.Core": { "type": "Transitive", - "resolved": "1.36.0", - "contentHash": "vwqFZdHS4dzPlI7FFRkPx9ctA+aGGeRev3gnzG8lntWvKMmBhAmulABi1O9CEvS3/jzYt7yA+0pqVdxkpAd7dQ==", + "resolved": "1.41.0", + "contentHash": "7OO8rPCVSvXj2IQET3NkRf8hU2ZDCCvCIUhlrE089qkLNpNfWufJnBwHRKLAOWF3bhKBGJS/9hPBgjJ8kupUIg==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.ClientModel": "1.0.0", "System.Diagnostics.DiagnosticSource": "6.0.1", "System.Memory.Data": "1.0.2", "System.Numerics.Vectors": "4.5.0", @@ -92,12 +93,12 @@ }, "Azure.Identity": { "type": "Transitive", - "resolved": "1.10.3", - "contentHash": "l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==", + "resolved": "1.11.4", + "contentHash": "Sf4BoE6Q3jTgFkgBkx7qztYOFELBCo+wQgpYDwal/qJ1unBH73ywPztIJKXBXORRzAeNijsuxhk94h0TIMvfYg==", "dependencies": { - "Azure.Core": "1.35.0", - "Microsoft.Identity.Client": "4.56.0", - "Microsoft.Identity.Client.Extensions.Msal": "4.56.0", + "Azure.Core": "1.38.0", + "Microsoft.Identity.Client": "4.61.3", + "Microsoft.Identity.Client.Extensions.Msal": "4.61.3", "System.Memory": "4.5.4", "System.Security.Cryptography.ProtectedData": "4.7.0", "System.Text.Json": "4.7.2", @@ -106,44 +107,44 @@ }, "Azure.Storage.Blobs": { "type": "Transitive", - "resolved": "12.19.1", - "contentHash": "x43hWFJ4sPQ23TD4piCwT+KlQpZT8pNDAzqj6yUCqh+WJ2qcQa17e1gh6ZOeT2QNFQTTDSuR56fm2bIV7i11/w==", + "resolved": "12.21.2", + "contentHash": "2J+sMgNbj2DJ+ydRSqYYADDd2AajFLfPzLGxASOxcoGx4iVxyF6jscHw2IY+8QyMPWA09wN3lCtYJ5S4zIsJkA==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Text.Json": "4.7.2" } }, "Azure.Storage.Common": { "type": "Transitive", - "resolved": "12.18.1", - "contentHash": "ohCslqP9yDKIn+DVjBEOBuieB1QwsUCz+BwHYNaJ3lcIsTSiI4Evnq81HcKe8CqM8qvdModbipVQKpnxpbdWqA==", + "resolved": "12.20.1", + "contentHash": "KKBFnc4WZ6m9HgsKgwfO1cIxd154b8cAnP3uWhuelvFkzxqBXQQgIsHF0n3DYBG2AoTJCZDXwJpKuVC7CsKJWg==", "dependencies": { - "Azure.Core": "1.36.0", + "Azure.Core": "1.41.0", "System.IO.Hashing": "6.0.0" } }, "Azure.Storage.Queues": { "type": "Transitive", - "resolved": "12.17.1", - "contentHash": "ziN15iQ4+h0zf9EbKzFd5Zj3LiDH21qIrCknkXhpqwftPfIvlftvdyXbKQLi9+sh8dwT6PFPi/wq4oLsKNGfcQ==", + "resolved": "12.19.1", + "contentHash": "s7jBfSrEScS2yk5n61Xx+rNQCV+4SkFag17Wux4l8OufdBUkQPmEskQbOQxlPqBJNX1ycJRWj55Wd9Cz8lOLtQ==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Memory.Data": "1.0.2", "System.Text.Json": "4.7.2" } }, "BananaCakePop.Middleware": { "type": "Transitive", - "resolved": "13.0.0", - "contentHash": "6Zj/vfmnCXLjBG7WNdtOgZZ5ZDR3Sy1FQSshZUonIYs3OdzozmsFmqPXMd9XJ0QE9aAildgVGq/lDLpLrMI4Yw==", + "resolved": "16.0.3", + "contentHash": "gwWk5ykS1uum2/++x3UnGhmjs+4itxce1lW5YnKdb8JeG4QxAMzSWVGh3B1ehiKJNAuvNtbfBwp2BAQvOsq02g==", "dependencies": { - "Yarp.ReverseProxy": "2.0.1" + "Yarp.ReverseProxy": "2.1.0" } }, "BouncyCastle.Cryptography": { "type": "Transitive", - "resolved": "2.2.1", - "contentHash": "A6Zr52zVqJKt18ZBsTnX0qhG0kwIQftVAjLmszmkiR/trSp8H+xj1gUOzk7XHwaKgyREMSV1v9XaKrBUeIOdvQ==" + "resolved": "2.4.0", + "contentHash": "SwXsAV3sMvAU/Nn31pbjhWurYSjJ+/giI/0n6tCrYoupEK34iIHCuk3STAd9fx8yudM85KkLSVdn951vTng/vQ==" }, "CommandLineParser": { "type": "Transitive", @@ -152,8 +153,8 @@ }, "GreenDonut": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "KgsJ88vcX0UfSKAO7uzbEPOGu8wwJU3Vkgz7AgeTrnfdgIVjZFkesvMxDqjzY6F3fmMbJmfAOLjufYLFs1Fq1g==", + "resolved": "13.9.12", + "contentHash": "w/nOY3tM8nVmjI1Gyhv5/JVk3VyD7itRhz1Ul0A8C4MHavsEyNFaMA7J+lwBFKwSRsW4R52F0BhUVbomIDA5uQ==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0", "System.Diagnostics.DiagnosticSource": "8.0.0", @@ -162,169 +163,169 @@ }, "HotChocolate": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Dfue5pJ99mNWaIBYv6VupDLtZo8KhIGC9blQy76BAvkipd7m9K3xhBLNyxnUA5AmTXDrKdS+RVZ21ghG/pqeAw==", + "resolved": "13.9.12", + "contentHash": "eRHrmy5rNq9rcPrIsWvoEw5BNMDntCkzGa044fpfwKayAvSvzhsMRNRtrY351jGlg5779n3fSsabwofPu3haYw==", "dependencies": { - "HotChocolate.Authorization": "13.8.1", - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1", - "HotChocolate.Types.Mutations": "13.8.1", - "HotChocolate.Types.OffsetPagination": "13.8.1", - "HotChocolate.Validation": "13.8.1" + "HotChocolate.Authorization": "13.9.12", + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12", + "HotChocolate.Types.Mutations": "13.9.12", + "HotChocolate.Types.OffsetPagination": "13.9.12", + "HotChocolate.Validation": "13.9.12" } }, "HotChocolate.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "+llX8ziARzp+aKsOaXQfZAtqE+lF8gSmTiMiRCdpf03M+IWl/uCD9965nhqkM4mauWufwBXlwA7TE4uIUu+UjQ==", + "resolved": "13.9.12", + "contentHash": "zCDFmDV0lzDJQd7KvLthQ/d9x0TsVIKLXG3t/v0SgcQBYXnMvBeV094d+3cx44xE3T4lU4DpDeRTgD3rLLA+Dw==", "dependencies": { - "HotChocolate.Language": "13.8.1", + "HotChocolate.Language": "13.9.12", "System.Collections.Immutable": "8.0.0" } }, "HotChocolate.AspNetCore": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Pg4/+sGPCn5qNwo9z8GP/LcGHKaCRsozOwNw2XVnLRY9EDIOoN2jzblgaFuDqWkXe+rd2yAnxE7NHcdBohTEFQ==", + "resolved": "13.9.12", + "contentHash": "lv4vBVGFfTOofb/T7Fm+i0rJgyS5ZCBkCmryCcNAOw3YYpt8dL67Mms8+oIEPes04N9Wbimev+1pyxmBh5SpZg==", "dependencies": { - "BananaCakePop.Middleware": "13.0.0", - "HotChocolate": "13.8.1", - "HotChocolate.Subscriptions.InMemory": "13.8.1", - "HotChocolate.Transport.Sockets": "13.8.1", - "HotChocolate.Types.Scalars.Upload": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1" + "BananaCakePop.Middleware": "16.0.3", + "HotChocolate": "13.9.12", + "HotChocolate.Subscriptions.InMemory": "13.9.12", + "HotChocolate.Transport.Sockets": "13.9.12", + "HotChocolate.Types.Scalars.Upload": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12" } }, "HotChocolate.Authorization": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y+eLkswOMnSsPaO0fmY1gfNQD6I55SzXtAXhJIqsai1NpPeG2pu5b29y5UoGXNRQgb5/243gazbQbdM5j1S6PQ==", + "resolved": "13.9.12", + "contentHash": "LuTW5qZhD0bpZqQ1sTZJav+u6jc4JO7DltKhGM1nFWsOEPxMAx9OgyehQfuAoiGp0CPKHUI+M/LxDbXu1HFJog==", "dependencies": { - "HotChocolate.Execution": "13.8.1" + "HotChocolate.Execution": "13.9.12" } }, "HotChocolate.Data": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "tgXDs0TuyyPUMAUbPJltjll+HDSU19lX14IVe8J9WdDHGQXTScjyn1px8tX537wYh6Fy1XfBgrCKwmTV21+IdQ==", + "resolved": "13.9.12", + "contentHash": "NFsErsZVyMZntDrA6TPHvCgLCaOQ9QhZvmQmnVqcozLQvfCLuS6cSGwdN5zy+DKYa+yTaMG5DK7uKcxVWT//Sg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12" } }, "HotChocolate.Execution": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "co/VtIsOf3wqabsQLwO6HbTPi4UfL8UnzFlRkP2K4NNsNRdDkurYDdECS89swAuvfttzNua4MFOA4PclbW6Y/Q==", + "resolved": "13.9.12", + "contentHash": "UsuKiq7ynoqa9LvOjUHJAb4XTtnreFmjT3unhU6wz5cVeJU02eqbIQQyiOPDlv/SEk75XxJ1EjiuXZ/sKzcsag==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1", - "HotChocolate.Validation": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12", + "HotChocolate.Validation": "13.9.12", "Microsoft.Extensions.DependencyInjection": "8.0.0", "System.Threading.Channels": "8.0.0" } }, "HotChocolate.Execution.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "sAL6A/Qa23inTgu8sWiNoaKpaJ3MosXLsiP908+XUogMOjudpWnaSWPYu5THgl1deaQ6q55gbyiFvwJx5lRR8A==", + "resolved": "13.9.12", + "contentHash": "o65we+xKpSpn/z5uqeTT3SW8+JEu4tufMxRCXXe38K504+WNy1yuuf3DpmwKBP0I3zeXMaWOsLLFcqzYKMAMXA==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Fetching": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "b1o8+gKmaE7rVX+fq/vFNFj+lcY414LoadaCcriEGEsz5fwIX5+SadmUIiaSuFOhuL+T8VLngh0zJXvPBI3sSA==", + "resolved": "13.9.12", + "contentHash": "dl098a0FSo2z0k3WwHdrlCeAn4fwFGOC2oQnkWjNGmTZAIuUaOrT1zoxLgFGJ/FLSUdB58jgYAiW+tD4zVE1+Q==", "dependencies": { - "GreenDonut": "13.8.1", - "HotChocolate.Types": "13.8.1" + "GreenDonut": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Language": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "qlljQwU51ecUyYa0qdOGHnWgP481QwwZsZRGwFuH/RbUwDVQOF8Fz/9aZxFmECkpiaCBfb8fHJOlzQGE52V6JQ==", + "resolved": "13.9.12", + "contentHash": "rohvOiAmZ9Wo8cLjnm5UwtrYrHfLm0YNKAqD7ZqK8QBqv3DTqlZTs3WMaJdkG6BLdZR/l8dK/g1Bl3BGhqSBJA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1", - "HotChocolate.Language.Utf8": "13.8.1", - "HotChocolate.Language.Visitors": "13.8.1", - "HotChocolate.Language.Web": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12", + "HotChocolate.Language.Utf8": "13.9.12", + "HotChocolate.Language.Visitors": "13.9.12", + "HotChocolate.Language.Web": "13.9.12" } }, "HotChocolate.Language.SyntaxTree": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "0RYVxhsxR1vf0ue/V8GZnN8UVxh1bI74KPe0vFLLlNXRSq55LXTuGt3gYc6+LxSCc4KaItzRl6DwdgRuDRINjw==", + "resolved": "13.9.12", + "contentHash": "rEmQ0OFW+LjTtYZNenFW9IKWTPJny8ACl1XnPULcGF22mgtuxItLwGJRfceRaAKqpAV2g7oLdFfLYmjqeJc3Tw==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0" } }, "HotChocolate.Language.Utf8": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y7YY6usRd72eAHjPS/NffT9cX92FJLg1Q6litLSCdjps1PnYVYTPnkNu5Ys1ngCJjOLsB71Or5CyjO5+Q8XSxA==", + "resolved": "13.9.12", + "contentHash": "JfsKnk734a0PxEFo9XGHiAiXNKI5qV1X0mAMcqRetljaiLGKKwYM/1ndvz3JS/gvVP/oltBaRKNKk1pWO9desg==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Visitors": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "aMibQ+gWIB+L+jZhiq2Vq+Jr6DsKcLwXAwr0GY8Dx54GPq9f/UHgtMi0KWrZ3sJck5/FwvENjLAuOtb2DFBREA==", + "resolved": "13.9.12", + "contentHash": "I2T8u0gRY0TxmjLm+EYjIreihp7oJQLhRXOs8p3y7BZAmJNxfeuc6EkMn8VDca1EQeiroNmC9UTawtJNV7QNyQ==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Web": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "rQ0jTiWoHuPyF58bZ17AdfYezmrpwcHthNhjYBcVfAxkATsvrHzoPqNDIgpv8xv3xaMlpxsv+nPg+i9mW/zS2Q==", + "resolved": "13.9.12", + "contentHash": "/1HpNKOImaJcy6XLDPQaWqIE1H4Dmu4ST2Sl9lPE9EwDfYe6gBv3dS9mQ7jteyQQ7az05QhotXl2zDHD/Zx7lg==", "dependencies": { - "HotChocolate.Language.Utf8": "13.8.1" + "HotChocolate.Language.Utf8": "13.9.12" } }, "HotChocolate.Subscriptions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "RD0eebXDBvfILKsy8dF7kMyR1puoPDzp0/BPUBzfEQalGi66F76P/cuGHN1fJrzTr1x2MIINsPmQN2udlfTTKQ==", + "resolved": "13.9.12", + "contentHash": "2VnYGlN9E7e5kGV76JU4Z/5sOag0wgUh694qwx4aPG1Lc5hPQDOL2BIk9jX7PmftHDmbxpNT3ZBvTSJXvGIoPQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1" + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12" } }, "HotChocolate.Subscriptions.InMemory": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "8A0K4bTBd1CfWbPovj/b1WYb52S8ElaOxghlS8Dea3GN8q4CCF3vSwXrzfkdVynCmrv3AFQYIXV1ddMJG1YqFQ==", + "resolved": "13.9.12", + "contentHash": "yQxVqqLUdMcl7yvU4qVhIrsRA1WIb1pkiKsXuD3FQxxucW9M4qqqklx91tY33AwIGnBGva7UCnofNxHg2FRbYg==", "dependencies": { - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Subscriptions": "13.8.1", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Subscriptions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Transport.Sockets": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "YVfn1O+B0UlGKtieqRoGEeZjnFpSNjK1ZQVLvfKZ/DfCh+7FR9CwZ6II7YXWCE+M9sCQTvEo9Cz5XCpsnJDhIw==", + "resolved": "13.9.12", + "contentHash": "7VWxYdWBKhNA1LxBIba7okMvQDcaGzHlYhkmBtPGKtfg7sKqOrF6TrwlJg0peLnN8luG7TfW8Fmz8cbD7teEdA==", "dependencies": { "System.IO.Pipelines": "8.0.0" } }, "HotChocolate.Types": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "EK5PodS+N+Oi77jmBFucS6Leq0mL4xYjC2fDTq6Le+cNxMLYx+cY8PE5Kjg3rMtrd/MFOOvUSQ/heAes5nuBHQ==", + "resolved": "13.9.12", + "contentHash": "bTPnQZ0zolwj3E37ma2NPS5SxX6jj2OTQj9bszonB+92t0BQLOuX2wlgz0ux7XSmdC+ch7reCxJcrJEnPDs2QQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Types.Shared": "13.8.1", - "HotChocolate.Utilities": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Types.Shared": "13.9.12", + "HotChocolate.Utilities": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.ObjectPool": "8.0.0", "System.ComponentModel.Annotations": "5.0.0", @@ -333,74 +334,74 @@ }, "HotChocolate.Types.CursorPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Nu7ERbmzIkZKeCx/dwMQDIEVXDk7fgMrGGsnBTBVNyk5YA/hyto54CNhlM7TeUqqhYUze3wKynA8rB1sr0f+cw==", + "resolved": "13.9.12", + "contentHash": "gjYxrEgQlcYTIcLMRUbF4/++C5c87OP7JU+f+YP6+BPID+r9tfEjC0U5KuRgbSg83t5jtgK1RpMLrbdTOUUGJg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Mutations": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "euXYibxZS11BTQ+nhY991u4mfd72xK/25KYaA6/mkLR/to9z9Xb27QSukVF5cdCTEWnqBix6CdX3S5fq2YIYGw==", + "resolved": "13.9.12", + "contentHash": "Uvm+FfZISLM5+/vYuq4Rphns1UrfhiCfoLmdUtjMIPq4jVVl4unLxfcy1GrXdHVoBO7bOL1+gHl96e9S422+6w==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.OffsetPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cwspQsQEOUBxjOAOvcmYObf4ol5pcI6epKQahrwfOX7v8GJd+FU0Sh8YmqOA1bks4VyjueDR06t88lw6XNeJIw==", + "resolved": "13.9.12", + "contentHash": "ipcyM/APH4J5oUFSE+TMYlCZ0n3lVvvap4eOHSXiriHlNM9/deLy5CooAlMmBkFbMsiFR8XcD9Ebc7od/xwm+g==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Scalars.Upload": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cUMEyPMt57kEhB8kXvF5/lCyBZQkzkTFuSpTIZwTX3RmJ08bYWaXxpYLpor/jxjoe4qTIyGR+z7z2p8sIearMg==", + "resolved": "13.9.12", + "contentHash": "3cAHgOwyl0O6qznO7SyjYsUa/RdnSK1JnKxPkQ4lk5Y3pDpl4iLLKuGtReoS+n74h5WLE88U3RPR4x6JcWMDlw==", "dependencies": { - "HotChocolate.Types": "13.8.1" + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Shared": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "vPpDZdVLahXD+a9xweLclWyIy3GH8IcKHmzZpOz4zeoZlxUuQCrx0ViXrSdiX1WdtOoV0nc5c26WKPIgCAVJIw==", + "resolved": "13.9.12", + "contentHash": "zWDYduCtLFxGqMV3vJ5lMfUv4h9ebU8dLwtG1Irtv5W5zOze0S+U6C0853hzDwL8/o6Torb5knQj56n78WBnAA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Utilities": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Z33UtFR96+iDR6uyjIW3qU3skvYEnhE/DGYnCoZUCh119t9OebvDW7ANCeL6oGXv0sZDJERvGQRhOZiBWZnqKA==" + "resolved": "13.9.12", + "contentHash": "Bo7aY9qaZ+8rcpDZFz9V03oVu4IWHmVgxlCDbMLYx1VJWOOyJA7pQb25ILxYVzScadn+lMkLy+4iq55GetLMhw==" }, "HotChocolate.Utilities.DependencyInjection": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "4tEg4xfDfiahuLrC59gH+BYfAFqDPEvoyBK7PU3ep7O2cmQgnqeE3tKMqJ1UovGMsVQ5nYwcQ98LhqrPOxECUw==", + "resolved": "13.9.12", + "contentHash": "iSTJZCLfpg7l+ExXFQbWsPPvkAPL+JLU3UA1E6avgTEzPvMpzo9I1c5mA2ItyoOrmTewKSWmnQBlv25oEFQF6g==", "dependencies": { "Microsoft.Extensions.DependencyInjection": "8.0.0" } }, "HotChocolate.Validation": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "kmPmYrtCt1NtmyZiSvfjDU+Abc/4hI2wDLe1uDEZW8JC8O2uwH0becZm1K6j9ZUfVMLp/5ZNsQONOXzL1VwxLA==", + "resolved": "13.9.12", + "contentHash": "7DyCifF5kBD2hbrsFoQX+nVYMURaHDzAt8gFm3+Ubedqx91cV39iP/Mam1qgx3gh/shaKYSRQFw4Ao8TTpFj2Q==", "dependencies": { - "HotChocolate.Types": "13.8.1", + "HotChocolate.Types": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.Options": "8.0.0" } }, "HtmlSanitizer": { "type": "Transitive", - "resolved": "8.0.843", - "contentHash": "XfmHK4rFz9PPN0gcv7J7pc+MRpcni1mrnO04mwA+9/1zIHLgdOvLJeDwWnX5a+up4tioPvGreB+p+KljLJ32wg==", + "resolved": "8.1.870", + "contentHash": "bQWYaKg8PrlgnhM9sPALl0UorpjWQkPTQiSTVyvm8imqF9lCLqBmtC0adUDi8xUYcdg6SJC+aHCw1MOjcg+Wnw==", "dependencies": { "AngleSharp": "[0.17.1]", "AngleSharp.Css": "[0.17.0]", @@ -421,56 +422,38 @@ }, "Kentico.Xperience.Core": { "type": "Transitive", - "resolved": "28.3.1", - "contentHash": "pNl19ECq6pIFdcMxVmGF8o7q7azE0Bkdj7YTAcLlhIqGzzIlFRFc5J/2RARds5v1zPmbEfaJaU4UMwxWU8TGWA==", + "resolved": "29.5.3", + "contentHash": "8o6O60DtlCa2YZqFrKfMeb9F26/HXWXTEZNcUAhi7/zX8S9lWsFt1/ik1U21d6VRy2HA13EJIpuGbzbAQA+2nA==", "dependencies": { "AngleSharp": "0.17.1", - "MailKit": "4.3.0", - "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", - "Microsoft.Data.SqlClient": "5.1.5", + "MailKit": "4.7.1.1", + "Microsoft.Data.SqlClient": "5.2.2", "Microsoft.Extensions.Caching.Memory": "6.0.1", "Microsoft.Extensions.Configuration": "6.0.1", "Microsoft.Extensions.Configuration.Binder": "6.0.0", "Microsoft.Extensions.DependencyInjection": "6.0.1", "Microsoft.Extensions.FileProviders.Physical": "6.0.0", "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization": "6.0.27", + "Microsoft.Extensions.Localization": "6.0.33", "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", "Mono.Cecil": "0.11.5", "Newtonsoft.Json": "13.0.3", - "System.CodeDom": "8.0.0", - "System.Configuration.ConfigurationManager": "6.0.1" + "System.CodeDom": "8.0.0" } }, "MailKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "jVmB3Nr0JpqhyMiXOGWMin+QvRKpucGpSFBCav9dG6jEJPdBV+yp1RHVpKzxZPfT+0adaBuZlMFdbIciZo1EWA==", - "dependencies": { - "MimeKit": "4.3.0" - } - }, - "Microsoft.AspNetCore.Http.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "kQUEVOU4loc8CPSb2WoHFTESqwIa8Ik7ysCBfTwzHAd0moWovc9JQLmhDIHlYLjHbyexqZAlkq/FPRUZqokebw==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "2.1.1", - "System.Text.Encodings.Web": "4.5.0" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VklZ7hWgSvHBcDtwYYkdMdI/adlf7ebxTZ9kdzAhX+gUs5jSHE9mZlTamdgf9miSsxc1QjNazHXTDJdVPZKKTw==", + "resolved": "4.7.1.1", + "contentHash": "Y3okmIxu8g/ZcoJiE2i+dCeKgnNyddsXmcJslZnCPGVPP0aRyeVINHV1h97V+OVMdqjQI6O12J2p8Duwq5UEqQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" + "MimeKit": "4.7.1", + "System.Formats.Asn1": "8.0.1" } }, "Microsoft.AspNetCore.SpaServices.Extensions": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "sJ3wibVaTldyWtQXz2zollxKJO1tnfIcuta5iqqiOHayEJwlbRFDz1qWpinC8hKnGCJ76PMm5bJ+g98KlXegRw==", + "resolved": "6.0.33", + "contentHash": "YFWk3bkKKVLQ1Q8jnTbjuzIIpIVoua4iw152wBNIH50gBZEi0xubmf0vxfgjXKoRs0xIgOBnjunvaMa8Of1e3w==", "dependencies": { "Microsoft.Extensions.FileProviders.Physical": "6.0.0" } @@ -482,28 +465,23 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "5.1.5", - "contentHash": "6kvhQjY5uBCdBccezFD2smfnpQjQ33cZtUZVrNvxlwoBu6uopM5INH6uSgLI7JRLtlQ3bMPwnhMq4kchsXeZ5w==", + "resolved": "5.2.2", + "contentHash": "mtoeRMh7F/OA536c/Cnh8L4H0uLSKB5kSmoi54oN7Fp0hNJDy22IqyMhaMH4PkDCqI7xL//Fvg9ldtuPHG0h5g==", "dependencies": { - "Azure.Identity": "1.10.3", - "Microsoft.Data.SqlClient.SNI.runtime": "5.1.1", - "Microsoft.Identity.Client": "4.56.0", + "Azure.Identity": "1.11.4", + "Microsoft.Data.SqlClient.SNI.runtime": "5.2.0", + "Microsoft.Identity.Client": "4.61.3", "Microsoft.IdentityModel.JsonWebTokens": "6.35.0", "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0", "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "6.0.1", - "System.Diagnostics.DiagnosticSource": "6.0.1", - "System.Runtime.Caching": "6.0.0", - "System.Security.Cryptography.Cng": "5.0.0", - "System.Security.Principal.Windows": "5.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Text.Encodings.Web": "6.0.0" + "System.Configuration.ConfigurationManager": "8.0.0", + "System.Runtime.Caching": "8.0.0" } }, "Microsoft.Data.SqlClient.SNI.runtime": { "type": "Transitive", - "resolved": "5.1.1", - "contentHash": "wNGM5ZTQCa2blc9ikXQouybGiyMd6IHPVJvAlBEPtr6JepZEOYeDxGyprYvFVeOxlCXs7avridZQ0nYkHzQWCQ==" + "resolved": "5.2.0", + "contentHash": "po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==" }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", @@ -573,8 +551,8 @@ }, "Microsoft.Extensions.FileProviders.Embedded": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "trrI4tXQsOIB56H3u/wD4aVu5QtF8nJPtBuQ6wm8phlYSFTR3Rj3/9fXA5Mrz4X2B0lwOk1QndCPL/fWhH9Izw==", + "resolved": "6.0.33", + "contentHash": "A5HxR46JT3B81XtfYY1/vr4RvICcue7/7lkOjrTMhGX0RdDXqQHXL1NpeYB27S1CLlsjuJn2fF1LSeGRnYJbgg==", "dependencies": { "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } @@ -617,19 +595,19 @@ }, "Microsoft.Extensions.Localization": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "sqwoeaqGTeSMBTrUV8ysD8JPfUcH8sdkmv4oCfz9i5WHAGfsS/eHCpoff87sukoxwgaEBBd9YPhTwdaFE9njlw==", + "resolved": "6.0.33", + "contentHash": "o4I6H5vdDoILQvHJXvVdo33ts4zTb4FXcdc+Et1FYG0dao9GLrDQ3HXwgV8yU2M/JeEJJnsQvUwtaANJFDnjQQ==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization.Abstractions": "6.0.27", + "Microsoft.Extensions.Localization.Abstractions": "6.0.33", "Microsoft.Extensions.Logging.Abstractions": "6.0.4", "Microsoft.Extensions.Options": "6.0.0" } }, "Microsoft.Extensions.Localization.Abstractions": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "virsfnfbV6uJASaNKUXLQpdY0qGr48R6dUFwY00Qja5ea+kgntRgm7qzAH6GLeJjfW3zjoltrTiTrCbrAP3KCA==" + "resolved": "6.0.33", + "contentHash": "Hbq0a3DswFjen1K6hDljNENpy6bDbA/s2qsQ5M9kqa6fB3JVKWggAdqwx2GJG4+SGkZKOWkOZxQ1QVqavWaF5g==" }, "Microsoft.Extensions.Logging": { "type": "Transitive", @@ -681,19 +659,19 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==", + "resolved": "4.61.3", + "contentHash": "naJo/Qm35Caaoxp5utcw+R8eU8ZtLz2ALh8S+gkekOYQ1oazfCQMWVT4NJ/FnHzdIJlm8dMz0oMpMGCabx5odA==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "6.22.0" + "Microsoft.IdentityModel.Abstractions": "6.35.0", + "System.Diagnostics.DiagnosticSource": "6.0.1" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==", + "resolved": "4.61.3", + "contentHash": "PWnJcznrSGr25MN8ajlc2XIDW4zCFu0U6FkpaNLEWLgd1NgFCp5uDY3mqLDgM8zCN8hqj8yo5wHYfLB2HjcdGw==", "dependencies": { - "Microsoft.Identity.Client": "4.56.0", - "System.IO.FileSystem.AccessControl": "5.0.0", + "Microsoft.Identity.Client": "4.61.3", "System.Security.Cryptography.ProtectedData": "4.5.0" } }, @@ -746,8 +724,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -761,13 +739,12 @@ }, "MimeKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "39KDXuERDy5VmHIn7NnCWvIVp/Ar4qnxZWg9m06DfRqDbW1B6zFv9o3Tdoa4CCu71tE/0SRqRCN5Z+bbffw6uw==", + "resolved": "4.7.1", + "contentHash": "Qoj4aVvhX14A1FNvaJ33hzOP4VZI2j+Mr38I9wSGcjMq4BYDtWLJG89aJ9nRW2cNfH6Czjwyp7+Mh++xv3AZvg==", "dependencies": { - "BouncyCastle.Cryptography": "2.2.1", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Security.Cryptography.Pkcs": "7.0.3", - "System.Text.Encoding.CodePages": "7.0.0" + "BouncyCastle.Cryptography": "2.4.0", + "System.Formats.Asn1": "8.0.1", + "System.Security.Cryptography.Pkcs": "8.0.0" } }, "MiniProfiler.AspNetCore": { @@ -826,36 +803,45 @@ }, "SkiaSharp": { "type": "Transitive", - "resolved": "2.88.7", - "contentHash": "LJHAMrbWO00J7jXWLWehyjqFo29T4VzABimfJb4nICqpEe3c/KvQGWL4ItON8ymzhxYOeFgyxeRzuNzO4GHSug==", + "resolved": "2.88.8", + "contentHash": "bRkp3uKp5ZI8gXYQT57uKwil1uobb2p8c69n7v5evlB/2JNcMAXVcw9DZAP5Ig3WSvgzGm2YSn27UVeOi05NlA==", "dependencies": { - "SkiaSharp.NativeAssets.Win32": "2.88.7", - "SkiaSharp.NativeAssets.macOS": "2.88.7" + "SkiaSharp.NativeAssets.Win32": "2.88.8", + "SkiaSharp.NativeAssets.macOS": "2.88.8" } }, "SkiaSharp.NativeAssets.Linux.NoDependencies": { "type": "Transitive", - "resolved": "2.88.7", - "contentHash": "KkMftfAz1lGPnuhyecuLJzeyvMjXtHp9cYVQc/oeLhF8KYrxtUxRy5LOX5oROhyLHy/CyqEl9MoAhqmSH7cV7g==", + "resolved": "2.88.8", + "contentHash": "/DoKtdyvRgCC5GR/SH+ps3ZiOjmf0BYpAyrhWQELFOO1hdcqddrDVJjDNCOJ41vV+NlS5b3kcDoZZ7jLhFjyXg==", "dependencies": { - "SkiaSharp": "2.88.7" + "SkiaSharp": "2.88.8" } }, "SkiaSharp.NativeAssets.macOS": { "type": "Transitive", - "resolved": "2.88.7", - "contentHash": "3jNzco4VjcYPFNxR9aNWcgweFXbTSdM1VpNRzCS4X0i1A1OuNqcaulrAvmntNpujeWxHo9e6WGh6FN8Jf5+XhA==" + "resolved": "2.88.8", + "contentHash": "6Kn5TSkKlfyS6azWHF3Jk2sW5C4jCE5uSshM/5AbfFrR+5n6qM5XEnz9h4VaVl7LTxBvHvMkuPb/3bpbq0vxTw==" }, "SkiaSharp.NativeAssets.Win32": { "type": "Transitive", - "resolved": "2.88.7", - "contentHash": "BCXmWdQ0oVck9vRwC8U3ocSaTHEx28VB+6qw9OxGIMQ86iO5bp4Flqk3IXH0l9Pbr7vWAUOpI212iaL9mTaUZQ==" + "resolved": "2.88.8", + "contentHash": "O9QXoWEXA+6cweR4h3BOnwMz+pO9vL9mXdjLrpDd0w1QzCgWmLQBxa1VgySDITiH7nQndrDG1h6937zm9pLj1Q==" }, "System.Buffers": { "type": "Transitive", "resolved": "4.5.1", "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" }, + "System.ClientModel": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "I3CVkvxeqFYjIVEP59DnjbeoGNfo/+SZrCLpRz2v/g0gpCHaEMPtWSY0s9k/7jR1rAsLNg2z2u1JRB76tPjnIw==", + "dependencies": { + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, "System.CodeDom": { "type": "Transitive", "resolved": "8.0.0", @@ -1004,8 +990,8 @@ }, "System.Formats.Asn1": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "+nfpV0afLmvJW8+pLlHxRjz3oZJw4fkyU9MMEaMhCsHi/SN9bGF9q79ROubDiwTiCHezmK0uCWkPP7tGFP/4yg==" + "resolved": "8.0.1", + "contentHash": "XqKba7Mm/koKSjKMfW82olQdmfbI5yqeoLV/tidRp7fbh5rmHAQ5raDI/7SU0swTzv+jgqtUGkzmFxuUg0it1A==" }, "System.Globalization": { "type": "Transitive", @@ -1075,15 +1061,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.IO.FileSystem.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", - "dependencies": { - "System.Security.AccessControl": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, "System.IO.FileSystem.Primitives": { "type": "Transitive", "resolved": "4.3.0", @@ -1343,29 +1320,12 @@ "System.Runtime": "4.3.0" } }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", - "dependencies": { - "System.Formats.Asn1": "5.0.0" - } - }, "System.Security.Cryptography.Pkcs": { "type": "Transitive", - "resolved": "7.0.3", - "contentHash": "yhwEHH5Gzl/VoADrXtt5XC95OFoSjNSWLHNutE7GwdOgefZVRvEXRSooSpL8HHm3qmdd9epqzsWg28UJemt22w==", + "resolved": "8.0.0", + "contentHash": "ULmp3xoOwNYjOYp4JZ2NK/6NdTgiN1GQXzVVN1njQ7LOZ0d0B9vyMnhyqbIi9Qw4JXj1JgCsitkTShboHRx7Eg==", "dependencies": { - "System.Formats.Asn1": "7.0.0" + "System.Formats.Asn1": "8.0.0" } }, "System.Security.Cryptography.ProtectedData": { @@ -1373,11 +1333,6 @@ "resolved": "8.0.0", "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1390,8 +1345,11 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.Text.Encoding.Extensions": { "type": "Transitive", @@ -1471,8 +1429,8 @@ }, "Yarp.ReverseProxy": { "type": "Transitive", - "resolved": "2.0.1", - "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "resolved": "2.1.0", + "contentHash": "VgRuCBxmh5ND4VuFhvIN3AAeoxFhYkS2hNINk6AVCrOVTlpk7OwdrTXi8NHACfqfhDL+/oYCZrF9RxN+yiYnEg==", "dependencies": { "System.IO.Hashing": "7.0.0" } @@ -1481,8 +1439,8 @@ "type": "Project", "dependencies": { "MiniProfiler.AspNetCore.Mvc": "[4.3.8, )", - "kentico.xperience.azurestorage": "[28.3.1, )", - "kentico.xperience.webapp": "[28.3.1, )" + "kentico.xperience.azurestorage": "[29.5.3, )", + "kentico.xperience.webapp": "[29.5.3, )" } }, "MiniProfiler.AspNetCore.Mvc": { diff --git a/examples/DancingGoat/wwwroot/Content/Styles/Controls.less b/examples/DancingGoat/wwwroot/Content/Styles/Controls.less new file mode 100644 index 0000000..c54975b --- /dev/null +++ b/examples/DancingGoat/wwwroot/Content/Styles/Controls.less @@ -0,0 +1,186 @@ +// Checkboxes and radios +// Uses font-icon for the checkboxes and radio buttons +// +// Common radio and checkbox styles +.radio, +.ktc-radio, +.checkbox, +.ktc-checkbox { + display: block; + + label { + display: inline-block; + cursor: pointer; + position: relative; + padding-left: @base-unit * 1.5; + line-height: @line-height-100; + font-weight: normal; + // Common styles for border and inner icon + &:before, + &:after { + content: ""; + width: @base-unit - 1px; // remove white bg around + height: @base-unit - 1px; // remove white bg around + line-height: @base-unit; + display: inline-block; + box-sizing: border-box; + position: absolute; + left: 0; + top: @base-unit * 0.125; // special alignment + background-color: @color-white; + } + // Inner icon specific + &:after { + background-color: transparent; + } + } + + input { + // Disabled styling + &[disabled], &:active[disabled] { + & + label { + cursor: not-allowed; + + &:before, &:focus:before, &:active:before { + color: @input-bg-disabled; + } + + &:after { + color: @input-color-disabled; + } + } + } + // Hide default inputs + .sr-only; + // Icons + + label:before, + + label:after { + font-family: @icon-font-name; + font-size: @icon-size-80; + text-align: center; + } + + + label:before { + color: @color-gray-130; + } + + + label:after { + color: @color-green-100; + } + // Focus + &:focus + label:before, + &:active + label:before { + color: @color-blue-100; + } + } +} +// Checkbox correction for Safari +&.Safari { + .checkbox, .ktc-checkbox { + label { + &:after { + height: @base-unit; + } + } + } +} +// Checkbox correction for Chrome +&.Chrome { + .checkbox, .ktc-checkbox { + label { + &:before, + &:after { + height: @base-unit; + } + } + } +} + +// Radio specific styles +.radio, +.ktc-radio { + input { + // Border - shown for both selected and unselected + ~ label:before { + content: @icon-rb-uncheck; + } + + &:disabled ~ label:before { + content: @icon-circle; + } + // Inner icon + &:checked ~ label:after { + content: @icon-rb-check-sign; + } + } + // Radio button border radius fix - because of background issue on table hover + label:before { + border-radius: 50%; + } +} + +// Checkbox specific styles +.checkbox, .ktc-checkbox { + input { + // Border - shown for both checked and unchecked + ~ label:before { + content: @icon-cb-uncheck; + } + + &:disabled ~ label:before { + content: @icon-cb-check-disabled; + } + // Inner icon + &:checked ~ label:after { + content: @icon-cb-check-sign; + } + } + + &:not(.checkbox-no-label), &:not(.ktc-checkbox-no-label) { + label { + margin-right: @base-unit * 0.5; + } + } +} + + + +// Vertical radio and checkbox lists +.radio-list-vertical, +.ktc-radio-list-vertical, +.checkbox-list-vertical, +.ktc-checkbox-list-vertical { + margin-top: (@base-unit * 0.25 + @input-border-width); + margin-right: @base-unit * 0.5; + + label:not(:first-of-type), + // When disabled, radio list item gets wrapped with a span + span:not(:first-of-type) label, + .radio + .radio, + .ktc-radio + .ktc-radio, + .checkbox + .checkbox, + .ktc-checkbox + .ktc-checkbox { + margin-top: @base-unit * 0.25; + } + // Use this class when the list is the first thing on the page + &.first-on-page { + margin-top: 0px; + } +} + +// Horizontal radio and checkbox lists +.radio-list-horizontal, +.ktc-radio-list-horizontal, +.checkbox-list-horizontal, +.ktc-checkbox-list-horizontal { + .radio, + .ktc-radio, + .checkbox, + .ktc-checkbox { + display: inline-block; + } + + label { + margin-right: @base-unit; + } +} \ No newline at end of file diff --git a/examples/DancingGoat/wwwroot/Content/Styles/Landing-page.css b/examples/DancingGoat/wwwroot/Content/Styles/Landing-page.css index 49da8f8..0e02ed6 100644 --- a/examples/DancingGoat/wwwroot/Content/Styles/Landing-page.css +++ b/examples/DancingGoat/wwwroot/Content/Styles/Landing-page.css @@ -4487,6 +4487,17 @@ p { .row.section-cappuccino .image-uploader-editor .uploader .dz-message { color: #ffffff; } +/*# Consent #*/ +.consent-item:not(:first-of-type) { + border-top: 1px solid #e7e7e7; +} +.consent-item .row { + margin: 0 32px 0 32px; + padding: 8px 0 0 0; +} +.consent-item .consent-heading { + margin: 0; +} .cookie-consent { font-size: 16px; padding: 8px; diff --git a/examples/DancingGoat/wwwroot/Content/Styles/Products.less b/examples/DancingGoat/wwwroot/Content/Styles/Products.less new file mode 100644 index 0000000..701960f --- /dev/null +++ b/examples/DancingGoat/wwwroot/Content/Styles/Products.less @@ -0,0 +1,132 @@ +/*# Image #*/ +.product-tile-image { + overflow: hidden; + text-align: center; + position: relative; + display: block; + margin: .5rem; + padding-top: 15%; + padding-bottom: 25%; +} + +.product-tile-image img { + height: auto; + width: 100%; +} + +.product-tile-info { + padding: 1.25rem; + position: absolute; + bottom: 0; +} + +/*# Product list page #*/ +.product-page { + margin-top: 1.25rem; +} + +.product-tile { + overflow: hidden; + border: 1px solid #E5E5E5; + margin: 0 0 -2px -2px; + background: @color-white; +} + +.product-tile .product-heading { + text-align: center; + font-size: 1rem; + font-weight: normal; + font-family: 'Source Sans Pro', sans-serif; + z-index: 1; + position: absolute; + display: block; + margin: auto; + width: 100%; + padding: 1.25rem; +} + +.product-tile a { + color: #000; + text-decoration: none; +} + +/*# Product #*/ +.product-detail header { + text-align: left; +} + +.product-detail header h2 { + margin-top: 1.5rem; + font-size: 2rem; +} + +.product-detail .description { + margin-top: 1.25rem; +} + +/*# Image #*/ +.product-detail .image { + border: 1px solid #e5e5e5; + margin: 0 0 1.25rem -2px; + text-align: center; +} + +.product-detail .image img { + max-width: 100%; + height: auto; + margin: auto; +} + +.product-detail { + .tag-row { + display: flex; + flex-direction: row; + padding-bottom: 24px; + gap: 12px; + + .tag { + padding: 8px 16px; + border-radius: 8px; + background: #846331; + color: #FFF; + letter-spacing: 0.4px; + } + } +} + +.product-filter { + background-color: @color-brownbg; + padding: 1rem; + + h4 { + &:first-of-type { + margin-top: 0px; + } + } + + label { + padding-left: 0.25rem; + } + + input[type="checkbox"] { + margin: 0; + padding: 0; + } +} + +@media(min-width:768px) { + .product-page > div.flex { + display: -webkit-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } +} + +.product-list { + .ContentLabel { + display: block; + margin-left: 1rem; + margin-top: 0.5rem; + } +} diff --git a/examples/DancingGoat/wwwroot/Content/Styles/Site.css b/examples/DancingGoat/wwwroot/Content/Styles/Site.css index bd2ee66..12270fc 100644 --- a/examples/DancingGoat/wwwroot/Content/Styles/Site.css +++ b/examples/DancingGoat/wwwroot/Content/Styles/Site.css @@ -1,4 +1,4 @@ -/* http://meyerweb.com/eric/tools/css/reset/ +/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ @@ -5089,6 +5089,355 @@ li.dropdown a { padding: 1rem 2.5rem; } } +/*# Image #*/ +.product-tile-image { + overflow: hidden; + text-align: center; + position: relative; + display: block; + margin: 0.5rem; + padding-top: 15%; + padding-bottom: 25%; +} +.product-tile-image img { + height: auto; + width: 100%; +} +.product-tile-info { + padding: 1.25rem; + position: absolute; + bottom: 0; +} +/*# Product list page #*/ +.product-page { + margin-top: 1.25rem; +} +.product-tile { + overflow: hidden; + border: 1px solid #E5E5E5; + margin: 0 0 -2px -2px; + background: #ffffff; +} +.product-tile .product-heading { + text-align: center; + font-size: 1rem; + font-weight: normal; + font-family: 'Source Sans Pro', sans-serif; + z-index: 1; + position: absolute; + display: block; + margin: auto; + width: 100%; + padding: 1.25rem; +} +.product-tile a { + color: #000; + text-decoration: none; +} +/*# Product #*/ +.product-detail header { + text-align: left; +} +.product-detail header h2 { + margin-top: 1.5rem; + font-size: 2rem; +} +.product-detail .description { + margin-top: 1.25rem; +} +/*# Image #*/ +.product-detail .image { + border: 1px solid #e5e5e5; + margin: 0 0 1.25rem -2px; + text-align: center; +} +.product-detail .image img { + max-width: 100%; + height: auto; + margin: auto; +} +.product-detail .tag-row { + display: flex; + flex-direction: row; + padding-bottom: 24px; + gap: 12px; +} +.product-detail .tag-row .tag { + padding: 8px 16px; + border-radius: 8px; + background: #846331; + color: #FFF; + letter-spacing: 0.4px; +} +.product-filter { + background-color: #F0E8DD; + padding: 1rem; +} +.product-filter h4:first-of-type { + margin-top: 0px; +} +.product-filter label { + padding-left: 0.25rem; +} +.product-filter input[type="checkbox"] { + margin: 0; + padding: 0; +} +@media (min-width: 768px) { + .product-page > div.flex { + display: -webkit-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } +} +.product-list .ContentLabel { + display: block; + margin-left: 1rem; + margin-top: 0.5rem; +} +.radio, +.ktc-radio, +.checkbox, +.ktc-checkbox { + display: block; +} +.radio label, +.ktc-radio label, +.checkbox label, +.ktc-checkbox label { + display: inline-block; + cursor: pointer; + position: relative; + padding-left: 24px; + line-height: 20px; + font-weight: normal; +} +.radio label:before, +.ktc-radio label:before, +.checkbox label:before, +.ktc-checkbox label:before, +.radio label:after, +.ktc-radio label:after, +.checkbox label:after, +.ktc-checkbox label:after { + content: ""; + width: 15px; + height: 15px; + line-height: 16px; + display: inline-block; + box-sizing: border-box; + position: absolute; + left: 0; + top: 2px; + background-color: #ffffff; +} +.radio label:after, +.ktc-radio label:after, +.checkbox label:after, +.ktc-checkbox label:after { + background-color: transparent; +} +.radio input, +.ktc-radio input, +.checkbox input, +.ktc-checkbox input { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.radio input[disabled] + label, +.ktc-radio input[disabled] + label, +.checkbox input[disabled] + label, +.ktc-checkbox input[disabled] + label, +.radio input:active[disabled] + label, +.ktc-radio input:active[disabled] + label, +.checkbox input:active[disabled] + label, +.ktc-checkbox input:active[disabled] + label { + cursor: not-allowed; +} +.radio input[disabled] + label:before, +.ktc-radio input[disabled] + label:before, +.checkbox input[disabled] + label:before, +.ktc-checkbox input[disabled] + label:before, +.radio input:active[disabled] + label:before, +.ktc-radio input:active[disabled] + label:before, +.checkbox input:active[disabled] + label:before, +.ktc-checkbox input:active[disabled] + label:before, +.radio input[disabled] + label:focus:before, +.ktc-radio input[disabled] + label:focus:before, +.checkbox input[disabled] + label:focus:before, +.ktc-checkbox input[disabled] + label:focus:before, +.radio input:active[disabled] + label:focus:before, +.ktc-radio input:active[disabled] + label:focus:before, +.checkbox input:active[disabled] + label:focus:before, +.ktc-checkbox input:active[disabled] + label:focus:before, +.radio input[disabled] + label:active:before, +.ktc-radio input[disabled] + label:active:before, +.checkbox input[disabled] + label:active:before, +.ktc-checkbox input[disabled] + label:active:before, +.radio input:active[disabled] + label:active:before, +.ktc-radio input:active[disabled] + label:active:before, +.checkbox input:active[disabled] + label:active:before, +.ktc-checkbox input:active[disabled] + label:active:before { + color: #e5e5e5; +} +.radio input[disabled] + label:after, +.ktc-radio input[disabled] + label:after, +.checkbox input[disabled] + label:after, +.ktc-checkbox input[disabled] + label:after, +.radio input:active[disabled] + label:after, +.ktc-radio input:active[disabled] + label:after, +.checkbox input:active[disabled] + label:after, +.ktc-checkbox input:active[disabled] + label:after { + color: #696663; +} +.radio input + label:before, +.ktc-radio input + label:before, +.checkbox input + label:before, +.ktc-checkbox input + label:before, +.radio input + label:after, +.ktc-radio input + label:after, +.checkbox input + label:after, +.ktc-checkbox input + label:after { + font-family: "Core-icons"; + font-size: 16px; + text-align: center; +} +.radio input + label:before, +.ktc-radio input + label:before, +.checkbox input + label:before, +.ktc-checkbox input + label:before { + color: #bdbbbb; +} +.radio input + label:after, +.ktc-radio input + label:after, +.checkbox input + label:after, +.ktc-checkbox input + label:after { + color: #497d04; +} +.radio input:focus + label:before, +.ktc-radio input:focus + label:before, +.checkbox input:focus + label:before, +.ktc-checkbox input:focus + label:before, +.radio input:active + label:before, +.ktc-radio input:active + label:before, +.checkbox input:active + label:before, +.ktc-checkbox input:active + label:before { + color: #1175ae; +} +.Safari .checkbox label:after, +.Safari .ktc-checkbox label:after { + height: 16px; +} +.Chrome .checkbox label:before, +.Chrome .ktc-checkbox label:before, +.Chrome .checkbox label:after, +.Chrome .ktc-checkbox label:after { + height: 16px; +} +.radio input ~ label:before, +.ktc-radio input ~ label:before { + content: "\e626"; +} +.radio input:disabled ~ label:before, +.ktc-radio input:disabled ~ label:before { + content: "\e6ac"; +} +.radio input:checked ~ label:after, +.ktc-radio input:checked ~ label:after { + content: "\e627"; +} +.radio label:before, +.ktc-radio label:before { + border-radius: 50%; +} +.checkbox input ~ label:before, +.ktc-checkbox input ~ label:before { + content: "\e6ad"; +} +.checkbox input:disabled ~ label:before, +.ktc-checkbox input:disabled ~ label:before { + content: "\e6f0"; +} +.checkbox input:checked ~ label:after, +.ktc-checkbox input:checked ~ label:after { + content: "\e6b0"; +} +.checkbox:not(.checkbox-no-label) label, +.ktc-checkbox:not(.checkbox-no-label) label, +.checkbox:not(.ktc-checkbox-no-label) label, +.ktc-checkbox:not(.ktc-checkbox-no-label) label { + margin-right: 8px; +} +.radio-list-vertical, +.ktc-radio-list-vertical, +.checkbox-list-vertical, +.ktc-checkbox-list-vertical { + margin-top: 6px; + margin-right: 8px; +} +.radio-list-vertical label:not(:first-of-type), +.ktc-radio-list-vertical label:not(:first-of-type), +.checkbox-list-vertical label:not(:first-of-type), +.ktc-checkbox-list-vertical label:not(:first-of-type), +.radio-list-vertical span:not(:first-of-type) label, +.ktc-radio-list-vertical span:not(:first-of-type) label, +.checkbox-list-vertical span:not(:first-of-type) label, +.ktc-checkbox-list-vertical span:not(:first-of-type) label, +.radio-list-vertical .radio + .radio, +.ktc-radio-list-vertical .radio + .radio, +.checkbox-list-vertical .radio + .radio, +.ktc-checkbox-list-vertical .radio + .radio, +.radio-list-vertical .ktc-radio + .ktc-radio, +.ktc-radio-list-vertical .ktc-radio + .ktc-radio, +.checkbox-list-vertical .ktc-radio + .ktc-radio, +.ktc-checkbox-list-vertical .ktc-radio + .ktc-radio, +.radio-list-vertical .checkbox + .checkbox, +.ktc-radio-list-vertical .checkbox + .checkbox, +.checkbox-list-vertical .checkbox + .checkbox, +.ktc-checkbox-list-vertical .checkbox + .checkbox, +.radio-list-vertical .ktc-checkbox + .ktc-checkbox, +.ktc-radio-list-vertical .ktc-checkbox + .ktc-checkbox, +.checkbox-list-vertical .ktc-checkbox + .ktc-checkbox, +.ktc-checkbox-list-vertical .ktc-checkbox + .ktc-checkbox { + margin-top: 4px; +} +.radio-list-vertical.first-on-page, +.ktc-radio-list-vertical.first-on-page, +.checkbox-list-vertical.first-on-page, +.ktc-checkbox-list-vertical.first-on-page { + margin-top: 0px; +} +.radio-list-horizontal .radio, +.ktc-radio-list-horizontal .radio, +.checkbox-list-horizontal .radio, +.ktc-checkbox-list-horizontal .radio, +.radio-list-horizontal .ktc-radio, +.ktc-radio-list-horizontal .ktc-radio, +.checkbox-list-horizontal .ktc-radio, +.ktc-checkbox-list-horizontal .ktc-radio, +.radio-list-horizontal .checkbox, +.ktc-radio-list-horizontal .checkbox, +.checkbox-list-horizontal .checkbox, +.ktc-checkbox-list-horizontal .checkbox, +.radio-list-horizontal .ktc-checkbox, +.ktc-radio-list-horizontal .ktc-checkbox, +.checkbox-list-horizontal .ktc-checkbox, +.ktc-checkbox-list-horizontal .ktc-checkbox { + display: inline-block; +} +.radio-list-horizontal label, +.ktc-radio-list-horizontal label, +.checkbox-list-horizontal label, +.ktc-checkbox-list-horizontal label { + margin-right: 16px; +} /*# Page wrap #*/ html, body { @@ -6079,6 +6428,7 @@ a + .article-tile-info .article-tile-date { /*# Taste our coffee #*/ .ourcoffee-tile-image { overflow: hidden; + height: 100%; width: 100%; } .ourcoffee-tile-text { diff --git a/examples/DancingGoat/wwwroot/Content/Styles/Site.less b/examples/DancingGoat/wwwroot/Content/Styles/Site.less index e7be99e..5e2b495 100644 --- a/examples/DancingGoat/wwwroot/Content/Styles/Site.less +++ b/examples/DancingGoat/wwwroot/Content/Styles/Site.less @@ -5,8 +5,11 @@ @import "./Grid.less"; @import "./Menu.less"; @import "./icons-core.less"; +@import "./TrackingConsent.less"; @import "./Buttons.less"; @import "./Mixins.less"; +@import "./Products.less"; +@import "./Controls.less"; /*# Page wrap #*/ html, body { @@ -1233,6 +1236,7 @@ a + .article-tile-info .article-tile-date { /*# Taste our coffee #*/ .ourcoffee-tile-image { overflow: hidden; + height: 100%; width: 100%; } diff --git a/examples/DancingGoat/wwwroot/Content/Styles/TrackingConsent.less b/examples/DancingGoat/wwwroot/Content/Styles/TrackingConsent.less index e74f226..355024c 100644 --- a/examples/DancingGoat/wwwroot/Content/Styles/TrackingConsent.less +++ b/examples/DancingGoat/wwwroot/Content/Styles/TrackingConsent.less @@ -1,5 +1,21 @@ @import "./variables.less"; +/*# Consent #*/ +.consent-item { + &:not(:first-of-type) { + border-top: 1px solid #e7e7e7; + } + + .row { + margin: 0 32px 0 32px; + padding: 8px 0 0 0; + } + + .consent-heading { + margin: 0; + } +} + .cookie-consent { font-size: @base-unit; padding: 8px; diff --git a/examples/DancingGoat/wwwroot/Scripts/formAutoPost.js b/examples/DancingGoat/wwwroot/Scripts/formAutoPost.js new file mode 100644 index 0000000..8fe957b --- /dev/null +++ b/examples/DancingGoat/wwwroot/Scripts/formAutoPost.js @@ -0,0 +1,44 @@ +(function () { + 'use strict'; + + function formAutoPost(options) { + // Default settings + var settings = Object.assign({ + targetContainerSelector: "#target-list", + url: "" + }, options); + + function onSuccess(data) { + document.querySelector(settings.targetContainerSelector).innerHTML = data; + } + + function getAjaxParameters(htmlControl) { + var form = htmlControl.closest("form"); + return { + url: form.getAttribute("action"), + method: form.getAttribute("method"), + data: new URLSearchParams(new FormData(form)).toString() + }; + } + + function ajaxCall() { + var ajaxParams = getAjaxParameters(this); + var xhr = new XMLHttpRequest(); + xhr.open(ajaxParams.method, ajaxParams.url, true); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + onSuccess(xhr.responseText); + } + }; + xhr.send(ajaxParams.data); + } + + var elements = document.querySelectorAll(".js-postback input[type=checkbox]"); + elements.forEach(function (element) { + element.addEventListener("click", ajaxCall); + }); + } + + window.formAutoPost = formAutoPost; +})(); \ No newline at end of file diff --git a/src/Kentico.Xperience.MiniProfiler/packages.lock.json b/src/Kentico.Xperience.MiniProfiler/packages.lock.json index 97951e9..454792d 100644 --- a/src/Kentico.Xperience.MiniProfiler/packages.lock.json +++ b/src/Kentico.Xperience.MiniProfiler/packages.lock.json @@ -4,30 +4,30 @@ "net8.0": { "Kentico.Xperience.AzureStorage": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "uBOgWJHlMzmO6+BZk1o2BDrSvdDioKftpQ/ljVm+4y/qVBBXqFli7vHbW/bEmdla9rj1T8bTw37OgklM/gGNRA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "d27b5FANBrdWR4uJEeEVnqfta97FLi5vreWr0lmdwqfHaUQMpI87vJ7Q+v+u/NQ+qtlBtyor6fN03vYwOLln4Q==", "dependencies": { - "Azure.Storage.Blobs": "12.19.1", - "Azure.Storage.Queues": "12.17.1", - "Kentico.Xperience.Core": "28.3.1", + "Azure.Storage.Blobs": "12.21.2", + "Azure.Storage.Queues": "12.19.1", + "Kentico.Xperience.Core": "29.5.3", "Newtonsoft.Json": "13.0.3" } }, "Kentico.Xperience.WebApp": { "type": "Direct", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "I9gz6Gq1XLbXTQ/RtCDuWpBVMYurT4+KrwfKublmxXQILpLwQzvFv5GRYe9Fa3AaHEThIdttSSv2l1y3ybzbqA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "n4V4V3fVq8ZRrus2I9RF8KcD0fX0QWE2aGsbC6Pb8g+kcai1TFHk/dsiOzDCSLSRFGMVyl/xt0o1OOBedXdWUg==", "dependencies": { "CommandLineParser": "2.9.1", - "HotChocolate.AspNetCore": "13.8.1", - "HotChocolate.Data": "13.8.1", - "HtmlSanitizer": "8.0.843", - "Kentico.Xperience.Core": "[28.3.1]", - "Microsoft.Extensions.FileProviders.Embedded": "6.0.27", - "Microsoft.Extensions.Localization": "6.0.27", - "System.Runtime.Caching": "8.0.0" + "HotChocolate.AspNetCore": "13.9.12", + "HotChocolate.Data": "13.9.12", + "HtmlSanitizer": "8.1.870", + "Kentico.Xperience.Core": "[29.5.3]", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.33", + "Microsoft.Extensions.Localization": "6.0.33" } }, "MiniProfiler.AspNetCore.Mvc": { @@ -64,10 +64,11 @@ }, "Azure.Core": { "type": "Transitive", - "resolved": "1.36.0", - "contentHash": "vwqFZdHS4dzPlI7FFRkPx9ctA+aGGeRev3gnzG8lntWvKMmBhAmulABi1O9CEvS3/jzYt7yA+0pqVdxkpAd7dQ==", + "resolved": "1.41.0", + "contentHash": "7OO8rPCVSvXj2IQET3NkRf8hU2ZDCCvCIUhlrE089qkLNpNfWufJnBwHRKLAOWF3bhKBGJS/9hPBgjJ8kupUIg==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.ClientModel": "1.0.0", "System.Diagnostics.DiagnosticSource": "6.0.1", "System.Memory.Data": "1.0.2", "System.Numerics.Vectors": "4.5.0", @@ -78,12 +79,12 @@ }, "Azure.Identity": { "type": "Transitive", - "resolved": "1.10.3", - "contentHash": "l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==", + "resolved": "1.11.4", + "contentHash": "Sf4BoE6Q3jTgFkgBkx7qztYOFELBCo+wQgpYDwal/qJ1unBH73ywPztIJKXBXORRzAeNijsuxhk94h0TIMvfYg==", "dependencies": { - "Azure.Core": "1.35.0", - "Microsoft.Identity.Client": "4.56.0", - "Microsoft.Identity.Client.Extensions.Msal": "4.56.0", + "Azure.Core": "1.38.0", + "Microsoft.Identity.Client": "4.61.3", + "Microsoft.Identity.Client.Extensions.Msal": "4.61.3", "System.Memory": "4.5.4", "System.Security.Cryptography.ProtectedData": "4.7.0", "System.Text.Json": "4.7.2", @@ -92,44 +93,44 @@ }, "Azure.Storage.Blobs": { "type": "Transitive", - "resolved": "12.19.1", - "contentHash": "x43hWFJ4sPQ23TD4piCwT+KlQpZT8pNDAzqj6yUCqh+WJ2qcQa17e1gh6ZOeT2QNFQTTDSuR56fm2bIV7i11/w==", + "resolved": "12.21.2", + "contentHash": "2J+sMgNbj2DJ+ydRSqYYADDd2AajFLfPzLGxASOxcoGx4iVxyF6jscHw2IY+8QyMPWA09wN3lCtYJ5S4zIsJkA==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Text.Json": "4.7.2" } }, "Azure.Storage.Common": { "type": "Transitive", - "resolved": "12.18.1", - "contentHash": "ohCslqP9yDKIn+DVjBEOBuieB1QwsUCz+BwHYNaJ3lcIsTSiI4Evnq81HcKe8CqM8qvdModbipVQKpnxpbdWqA==", + "resolved": "12.20.1", + "contentHash": "KKBFnc4WZ6m9HgsKgwfO1cIxd154b8cAnP3uWhuelvFkzxqBXQQgIsHF0n3DYBG2AoTJCZDXwJpKuVC7CsKJWg==", "dependencies": { - "Azure.Core": "1.36.0", + "Azure.Core": "1.41.0", "System.IO.Hashing": "6.0.0" } }, "Azure.Storage.Queues": { "type": "Transitive", - "resolved": "12.17.1", - "contentHash": "ziN15iQ4+h0zf9EbKzFd5Zj3LiDH21qIrCknkXhpqwftPfIvlftvdyXbKQLi9+sh8dwT6PFPi/wq4oLsKNGfcQ==", + "resolved": "12.19.1", + "contentHash": "s7jBfSrEScS2yk5n61Xx+rNQCV+4SkFag17Wux4l8OufdBUkQPmEskQbOQxlPqBJNX1ycJRWj55Wd9Cz8lOLtQ==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Memory.Data": "1.0.2", "System.Text.Json": "4.7.2" } }, "BananaCakePop.Middleware": { "type": "Transitive", - "resolved": "13.0.0", - "contentHash": "6Zj/vfmnCXLjBG7WNdtOgZZ5ZDR3Sy1FQSshZUonIYs3OdzozmsFmqPXMd9XJ0QE9aAildgVGq/lDLpLrMI4Yw==", + "resolved": "16.0.3", + "contentHash": "gwWk5ykS1uum2/++x3UnGhmjs+4itxce1lW5YnKdb8JeG4QxAMzSWVGh3B1ehiKJNAuvNtbfBwp2BAQvOsq02g==", "dependencies": { - "Yarp.ReverseProxy": "2.0.1" + "Yarp.ReverseProxy": "2.1.0" } }, "BouncyCastle.Cryptography": { "type": "Transitive", - "resolved": "2.2.1", - "contentHash": "A6Zr52zVqJKt18ZBsTnX0qhG0kwIQftVAjLmszmkiR/trSp8H+xj1gUOzk7XHwaKgyREMSV1v9XaKrBUeIOdvQ==" + "resolved": "2.4.0", + "contentHash": "SwXsAV3sMvAU/Nn31pbjhWurYSjJ+/giI/0n6tCrYoupEK34iIHCuk3STAd9fx8yudM85KkLSVdn951vTng/vQ==" }, "CommandLineParser": { "type": "Transitive", @@ -138,8 +139,8 @@ }, "GreenDonut": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "KgsJ88vcX0UfSKAO7uzbEPOGu8wwJU3Vkgz7AgeTrnfdgIVjZFkesvMxDqjzY6F3fmMbJmfAOLjufYLFs1Fq1g==", + "resolved": "13.9.12", + "contentHash": "w/nOY3tM8nVmjI1Gyhv5/JVk3VyD7itRhz1Ul0A8C4MHavsEyNFaMA7J+lwBFKwSRsW4R52F0BhUVbomIDA5uQ==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0", "System.Diagnostics.DiagnosticSource": "8.0.0", @@ -148,169 +149,169 @@ }, "HotChocolate": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Dfue5pJ99mNWaIBYv6VupDLtZo8KhIGC9blQy76BAvkipd7m9K3xhBLNyxnUA5AmTXDrKdS+RVZ21ghG/pqeAw==", + "resolved": "13.9.12", + "contentHash": "eRHrmy5rNq9rcPrIsWvoEw5BNMDntCkzGa044fpfwKayAvSvzhsMRNRtrY351jGlg5779n3fSsabwofPu3haYw==", "dependencies": { - "HotChocolate.Authorization": "13.8.1", - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1", - "HotChocolate.Types.Mutations": "13.8.1", - "HotChocolate.Types.OffsetPagination": "13.8.1", - "HotChocolate.Validation": "13.8.1" + "HotChocolate.Authorization": "13.9.12", + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12", + "HotChocolate.Types.Mutations": "13.9.12", + "HotChocolate.Types.OffsetPagination": "13.9.12", + "HotChocolate.Validation": "13.9.12" } }, "HotChocolate.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "+llX8ziARzp+aKsOaXQfZAtqE+lF8gSmTiMiRCdpf03M+IWl/uCD9965nhqkM4mauWufwBXlwA7TE4uIUu+UjQ==", + "resolved": "13.9.12", + "contentHash": "zCDFmDV0lzDJQd7KvLthQ/d9x0TsVIKLXG3t/v0SgcQBYXnMvBeV094d+3cx44xE3T4lU4DpDeRTgD3rLLA+Dw==", "dependencies": { - "HotChocolate.Language": "13.8.1", + "HotChocolate.Language": "13.9.12", "System.Collections.Immutable": "8.0.0" } }, "HotChocolate.AspNetCore": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Pg4/+sGPCn5qNwo9z8GP/LcGHKaCRsozOwNw2XVnLRY9EDIOoN2jzblgaFuDqWkXe+rd2yAnxE7NHcdBohTEFQ==", + "resolved": "13.9.12", + "contentHash": "lv4vBVGFfTOofb/T7Fm+i0rJgyS5ZCBkCmryCcNAOw3YYpt8dL67Mms8+oIEPes04N9Wbimev+1pyxmBh5SpZg==", "dependencies": { - "BananaCakePop.Middleware": "13.0.0", - "HotChocolate": "13.8.1", - "HotChocolate.Subscriptions.InMemory": "13.8.1", - "HotChocolate.Transport.Sockets": "13.8.1", - "HotChocolate.Types.Scalars.Upload": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1" + "BananaCakePop.Middleware": "16.0.3", + "HotChocolate": "13.9.12", + "HotChocolate.Subscriptions.InMemory": "13.9.12", + "HotChocolate.Transport.Sockets": "13.9.12", + "HotChocolate.Types.Scalars.Upload": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12" } }, "HotChocolate.Authorization": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y+eLkswOMnSsPaO0fmY1gfNQD6I55SzXtAXhJIqsai1NpPeG2pu5b29y5UoGXNRQgb5/243gazbQbdM5j1S6PQ==", + "resolved": "13.9.12", + "contentHash": "LuTW5qZhD0bpZqQ1sTZJav+u6jc4JO7DltKhGM1nFWsOEPxMAx9OgyehQfuAoiGp0CPKHUI+M/LxDbXu1HFJog==", "dependencies": { - "HotChocolate.Execution": "13.8.1" + "HotChocolate.Execution": "13.9.12" } }, "HotChocolate.Data": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "tgXDs0TuyyPUMAUbPJltjll+HDSU19lX14IVe8J9WdDHGQXTScjyn1px8tX537wYh6Fy1XfBgrCKwmTV21+IdQ==", + "resolved": "13.9.12", + "contentHash": "NFsErsZVyMZntDrA6TPHvCgLCaOQ9QhZvmQmnVqcozLQvfCLuS6cSGwdN5zy+DKYa+yTaMG5DK7uKcxVWT//Sg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12" } }, "HotChocolate.Execution": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "co/VtIsOf3wqabsQLwO6HbTPi4UfL8UnzFlRkP2K4NNsNRdDkurYDdECS89swAuvfttzNua4MFOA4PclbW6Y/Q==", + "resolved": "13.9.12", + "contentHash": "UsuKiq7ynoqa9LvOjUHJAb4XTtnreFmjT3unhU6wz5cVeJU02eqbIQQyiOPDlv/SEk75XxJ1EjiuXZ/sKzcsag==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1", - "HotChocolate.Validation": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12", + "HotChocolate.Validation": "13.9.12", "Microsoft.Extensions.DependencyInjection": "8.0.0", "System.Threading.Channels": "8.0.0" } }, "HotChocolate.Execution.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "sAL6A/Qa23inTgu8sWiNoaKpaJ3MosXLsiP908+XUogMOjudpWnaSWPYu5THgl1deaQ6q55gbyiFvwJx5lRR8A==", + "resolved": "13.9.12", + "contentHash": "o65we+xKpSpn/z5uqeTT3SW8+JEu4tufMxRCXXe38K504+WNy1yuuf3DpmwKBP0I3zeXMaWOsLLFcqzYKMAMXA==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Fetching": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "b1o8+gKmaE7rVX+fq/vFNFj+lcY414LoadaCcriEGEsz5fwIX5+SadmUIiaSuFOhuL+T8VLngh0zJXvPBI3sSA==", + "resolved": "13.9.12", + "contentHash": "dl098a0FSo2z0k3WwHdrlCeAn4fwFGOC2oQnkWjNGmTZAIuUaOrT1zoxLgFGJ/FLSUdB58jgYAiW+tD4zVE1+Q==", "dependencies": { - "GreenDonut": "13.8.1", - "HotChocolate.Types": "13.8.1" + "GreenDonut": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Language": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "qlljQwU51ecUyYa0qdOGHnWgP481QwwZsZRGwFuH/RbUwDVQOF8Fz/9aZxFmECkpiaCBfb8fHJOlzQGE52V6JQ==", + "resolved": "13.9.12", + "contentHash": "rohvOiAmZ9Wo8cLjnm5UwtrYrHfLm0YNKAqD7ZqK8QBqv3DTqlZTs3WMaJdkG6BLdZR/l8dK/g1Bl3BGhqSBJA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1", - "HotChocolate.Language.Utf8": "13.8.1", - "HotChocolate.Language.Visitors": "13.8.1", - "HotChocolate.Language.Web": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12", + "HotChocolate.Language.Utf8": "13.9.12", + "HotChocolate.Language.Visitors": "13.9.12", + "HotChocolate.Language.Web": "13.9.12" } }, "HotChocolate.Language.SyntaxTree": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "0RYVxhsxR1vf0ue/V8GZnN8UVxh1bI74KPe0vFLLlNXRSq55LXTuGt3gYc6+LxSCc4KaItzRl6DwdgRuDRINjw==", + "resolved": "13.9.12", + "contentHash": "rEmQ0OFW+LjTtYZNenFW9IKWTPJny8ACl1XnPULcGF22mgtuxItLwGJRfceRaAKqpAV2g7oLdFfLYmjqeJc3Tw==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0" } }, "HotChocolate.Language.Utf8": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y7YY6usRd72eAHjPS/NffT9cX92FJLg1Q6litLSCdjps1PnYVYTPnkNu5Ys1ngCJjOLsB71Or5CyjO5+Q8XSxA==", + "resolved": "13.9.12", + "contentHash": "JfsKnk734a0PxEFo9XGHiAiXNKI5qV1X0mAMcqRetljaiLGKKwYM/1ndvz3JS/gvVP/oltBaRKNKk1pWO9desg==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Visitors": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "aMibQ+gWIB+L+jZhiq2Vq+Jr6DsKcLwXAwr0GY8Dx54GPq9f/UHgtMi0KWrZ3sJck5/FwvENjLAuOtb2DFBREA==", + "resolved": "13.9.12", + "contentHash": "I2T8u0gRY0TxmjLm+EYjIreihp7oJQLhRXOs8p3y7BZAmJNxfeuc6EkMn8VDca1EQeiroNmC9UTawtJNV7QNyQ==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Web": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "rQ0jTiWoHuPyF58bZ17AdfYezmrpwcHthNhjYBcVfAxkATsvrHzoPqNDIgpv8xv3xaMlpxsv+nPg+i9mW/zS2Q==", + "resolved": "13.9.12", + "contentHash": "/1HpNKOImaJcy6XLDPQaWqIE1H4Dmu4ST2Sl9lPE9EwDfYe6gBv3dS9mQ7jteyQQ7az05QhotXl2zDHD/Zx7lg==", "dependencies": { - "HotChocolate.Language.Utf8": "13.8.1" + "HotChocolate.Language.Utf8": "13.9.12" } }, "HotChocolate.Subscriptions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "RD0eebXDBvfILKsy8dF7kMyR1puoPDzp0/BPUBzfEQalGi66F76P/cuGHN1fJrzTr1x2MIINsPmQN2udlfTTKQ==", + "resolved": "13.9.12", + "contentHash": "2VnYGlN9E7e5kGV76JU4Z/5sOag0wgUh694qwx4aPG1Lc5hPQDOL2BIk9jX7PmftHDmbxpNT3ZBvTSJXvGIoPQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1" + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12" } }, "HotChocolate.Subscriptions.InMemory": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "8A0K4bTBd1CfWbPovj/b1WYb52S8ElaOxghlS8Dea3GN8q4CCF3vSwXrzfkdVynCmrv3AFQYIXV1ddMJG1YqFQ==", + "resolved": "13.9.12", + "contentHash": "yQxVqqLUdMcl7yvU4qVhIrsRA1WIb1pkiKsXuD3FQxxucW9M4qqqklx91tY33AwIGnBGva7UCnofNxHg2FRbYg==", "dependencies": { - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Subscriptions": "13.8.1", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Subscriptions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Transport.Sockets": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "YVfn1O+B0UlGKtieqRoGEeZjnFpSNjK1ZQVLvfKZ/DfCh+7FR9CwZ6II7YXWCE+M9sCQTvEo9Cz5XCpsnJDhIw==", + "resolved": "13.9.12", + "contentHash": "7VWxYdWBKhNA1LxBIba7okMvQDcaGzHlYhkmBtPGKtfg7sKqOrF6TrwlJg0peLnN8luG7TfW8Fmz8cbD7teEdA==", "dependencies": { "System.IO.Pipelines": "8.0.0" } }, "HotChocolate.Types": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "EK5PodS+N+Oi77jmBFucS6Leq0mL4xYjC2fDTq6Le+cNxMLYx+cY8PE5Kjg3rMtrd/MFOOvUSQ/heAes5nuBHQ==", + "resolved": "13.9.12", + "contentHash": "bTPnQZ0zolwj3E37ma2NPS5SxX6jj2OTQj9bszonB+92t0BQLOuX2wlgz0ux7XSmdC+ch7reCxJcrJEnPDs2QQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Types.Shared": "13.8.1", - "HotChocolate.Utilities": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Types.Shared": "13.9.12", + "HotChocolate.Utilities": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.ObjectPool": "8.0.0", "System.ComponentModel.Annotations": "5.0.0", @@ -319,74 +320,74 @@ }, "HotChocolate.Types.CursorPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Nu7ERbmzIkZKeCx/dwMQDIEVXDk7fgMrGGsnBTBVNyk5YA/hyto54CNhlM7TeUqqhYUze3wKynA8rB1sr0f+cw==", + "resolved": "13.9.12", + "contentHash": "gjYxrEgQlcYTIcLMRUbF4/++C5c87OP7JU+f+YP6+BPID+r9tfEjC0U5KuRgbSg83t5jtgK1RpMLrbdTOUUGJg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Mutations": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "euXYibxZS11BTQ+nhY991u4mfd72xK/25KYaA6/mkLR/to9z9Xb27QSukVF5cdCTEWnqBix6CdX3S5fq2YIYGw==", + "resolved": "13.9.12", + "contentHash": "Uvm+FfZISLM5+/vYuq4Rphns1UrfhiCfoLmdUtjMIPq4jVVl4unLxfcy1GrXdHVoBO7bOL1+gHl96e9S422+6w==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.OffsetPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cwspQsQEOUBxjOAOvcmYObf4ol5pcI6epKQahrwfOX7v8GJd+FU0Sh8YmqOA1bks4VyjueDR06t88lw6XNeJIw==", + "resolved": "13.9.12", + "contentHash": "ipcyM/APH4J5oUFSE+TMYlCZ0n3lVvvap4eOHSXiriHlNM9/deLy5CooAlMmBkFbMsiFR8XcD9Ebc7od/xwm+g==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Scalars.Upload": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cUMEyPMt57kEhB8kXvF5/lCyBZQkzkTFuSpTIZwTX3RmJ08bYWaXxpYLpor/jxjoe4qTIyGR+z7z2p8sIearMg==", + "resolved": "13.9.12", + "contentHash": "3cAHgOwyl0O6qznO7SyjYsUa/RdnSK1JnKxPkQ4lk5Y3pDpl4iLLKuGtReoS+n74h5WLE88U3RPR4x6JcWMDlw==", "dependencies": { - "HotChocolate.Types": "13.8.1" + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Shared": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "vPpDZdVLahXD+a9xweLclWyIy3GH8IcKHmzZpOz4zeoZlxUuQCrx0ViXrSdiX1WdtOoV0nc5c26WKPIgCAVJIw==", + "resolved": "13.9.12", + "contentHash": "zWDYduCtLFxGqMV3vJ5lMfUv4h9ebU8dLwtG1Irtv5W5zOze0S+U6C0853hzDwL8/o6Torb5knQj56n78WBnAA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Utilities": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Z33UtFR96+iDR6uyjIW3qU3skvYEnhE/DGYnCoZUCh119t9OebvDW7ANCeL6oGXv0sZDJERvGQRhOZiBWZnqKA==" + "resolved": "13.9.12", + "contentHash": "Bo7aY9qaZ+8rcpDZFz9V03oVu4IWHmVgxlCDbMLYx1VJWOOyJA7pQb25ILxYVzScadn+lMkLy+4iq55GetLMhw==" }, "HotChocolate.Utilities.DependencyInjection": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "4tEg4xfDfiahuLrC59gH+BYfAFqDPEvoyBK7PU3ep7O2cmQgnqeE3tKMqJ1UovGMsVQ5nYwcQ98LhqrPOxECUw==", + "resolved": "13.9.12", + "contentHash": "iSTJZCLfpg7l+ExXFQbWsPPvkAPL+JLU3UA1E6avgTEzPvMpzo9I1c5mA2ItyoOrmTewKSWmnQBlv25oEFQF6g==", "dependencies": { "Microsoft.Extensions.DependencyInjection": "8.0.0" } }, "HotChocolate.Validation": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "kmPmYrtCt1NtmyZiSvfjDU+Abc/4hI2wDLe1uDEZW8JC8O2uwH0becZm1K6j9ZUfVMLp/5ZNsQONOXzL1VwxLA==", + "resolved": "13.9.12", + "contentHash": "7DyCifF5kBD2hbrsFoQX+nVYMURaHDzAt8gFm3+Ubedqx91cV39iP/Mam1qgx3gh/shaKYSRQFw4Ao8TTpFj2Q==", "dependencies": { - "HotChocolate.Types": "13.8.1", + "HotChocolate.Types": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.Options": "8.0.0" } }, "HtmlSanitizer": { "type": "Transitive", - "resolved": "8.0.843", - "contentHash": "XfmHK4rFz9PPN0gcv7J7pc+MRpcni1mrnO04mwA+9/1zIHLgdOvLJeDwWnX5a+up4tioPvGreB+p+KljLJ32wg==", + "resolved": "8.1.870", + "contentHash": "bQWYaKg8PrlgnhM9sPALl0UorpjWQkPTQiSTVyvm8imqF9lCLqBmtC0adUDi8xUYcdg6SJC+aHCw1MOjcg+Wnw==", "dependencies": { "AngleSharp": "[0.17.1]", "AngleSharp.Css": "[0.17.0]", @@ -395,50 +396,32 @@ }, "Kentico.Xperience.Core": { "type": "Transitive", - "resolved": "28.3.1", - "contentHash": "pNl19ECq6pIFdcMxVmGF8o7q7azE0Bkdj7YTAcLlhIqGzzIlFRFc5J/2RARds5v1zPmbEfaJaU4UMwxWU8TGWA==", + "resolved": "29.5.3", + "contentHash": "8o6O60DtlCa2YZqFrKfMeb9F26/HXWXTEZNcUAhi7/zX8S9lWsFt1/ik1U21d6VRy2HA13EJIpuGbzbAQA+2nA==", "dependencies": { "AngleSharp": "0.17.1", - "MailKit": "4.3.0", - "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", - "Microsoft.Data.SqlClient": "5.1.5", + "MailKit": "4.7.1.1", + "Microsoft.Data.SqlClient": "5.2.2", "Microsoft.Extensions.Caching.Memory": "6.0.1", "Microsoft.Extensions.Configuration": "6.0.1", "Microsoft.Extensions.Configuration.Binder": "6.0.0", "Microsoft.Extensions.DependencyInjection": "6.0.1", "Microsoft.Extensions.FileProviders.Physical": "6.0.0", "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization": "6.0.27", + "Microsoft.Extensions.Localization": "6.0.33", "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", "Mono.Cecil": "0.11.5", "Newtonsoft.Json": "13.0.3", - "System.CodeDom": "8.0.0", - "System.Configuration.ConfigurationManager": "6.0.1" + "System.CodeDom": "8.0.0" } }, "MailKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "jVmB3Nr0JpqhyMiXOGWMin+QvRKpucGpSFBCav9dG6jEJPdBV+yp1RHVpKzxZPfT+0adaBuZlMFdbIciZo1EWA==", - "dependencies": { - "MimeKit": "4.3.0" - } - }, - "Microsoft.AspNetCore.Http.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "kQUEVOU4loc8CPSb2WoHFTESqwIa8Ik7ysCBfTwzHAd0moWovc9JQLmhDIHlYLjHbyexqZAlkq/FPRUZqokebw==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "2.1.1", - "System.Text.Encodings.Web": "4.5.0" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VklZ7hWgSvHBcDtwYYkdMdI/adlf7ebxTZ9kdzAhX+gUs5jSHE9mZlTamdgf9miSsxc1QjNazHXTDJdVPZKKTw==", + "resolved": "4.7.1.1", + "contentHash": "Y3okmIxu8g/ZcoJiE2i+dCeKgnNyddsXmcJslZnCPGVPP0aRyeVINHV1h97V+OVMdqjQI6O12J2p8Duwq5UEqQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" + "MimeKit": "4.7.1", + "System.Formats.Asn1": "8.0.1" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -453,28 +436,23 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "5.1.5", - "contentHash": "6kvhQjY5uBCdBccezFD2smfnpQjQ33cZtUZVrNvxlwoBu6uopM5INH6uSgLI7JRLtlQ3bMPwnhMq4kchsXeZ5w==", + "resolved": "5.2.2", + "contentHash": "mtoeRMh7F/OA536c/Cnh8L4H0uLSKB5kSmoi54oN7Fp0hNJDy22IqyMhaMH4PkDCqI7xL//Fvg9ldtuPHG0h5g==", "dependencies": { - "Azure.Identity": "1.10.3", - "Microsoft.Data.SqlClient.SNI.runtime": "5.1.1", - "Microsoft.Identity.Client": "4.56.0", + "Azure.Identity": "1.11.4", + "Microsoft.Data.SqlClient.SNI.runtime": "5.2.0", + "Microsoft.Identity.Client": "4.61.3", "Microsoft.IdentityModel.JsonWebTokens": "6.35.0", "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0", "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "6.0.1", - "System.Diagnostics.DiagnosticSource": "6.0.1", - "System.Runtime.Caching": "6.0.0", - "System.Security.Cryptography.Cng": "5.0.0", - "System.Security.Principal.Windows": "5.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Text.Encodings.Web": "6.0.0" + "System.Configuration.ConfigurationManager": "8.0.0", + "System.Runtime.Caching": "8.0.0" } }, "Microsoft.Data.SqlClient.SNI.runtime": { "type": "Transitive", - "resolved": "5.1.1", - "contentHash": "wNGM5ZTQCa2blc9ikXQouybGiyMd6IHPVJvAlBEPtr6JepZEOYeDxGyprYvFVeOxlCXs7avridZQ0nYkHzQWCQ==" + "resolved": "5.2.0", + "contentHash": "po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==" }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", @@ -544,8 +522,8 @@ }, "Microsoft.Extensions.FileProviders.Embedded": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "trrI4tXQsOIB56H3u/wD4aVu5QtF8nJPtBuQ6wm8phlYSFTR3Rj3/9fXA5Mrz4X2B0lwOk1QndCPL/fWhH9Izw==", + "resolved": "6.0.33", + "contentHash": "A5HxR46JT3B81XtfYY1/vr4RvICcue7/7lkOjrTMhGX0RdDXqQHXL1NpeYB27S1CLlsjuJn2fF1LSeGRnYJbgg==", "dependencies": { "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } @@ -577,19 +555,19 @@ }, "Microsoft.Extensions.Localization": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "sqwoeaqGTeSMBTrUV8ysD8JPfUcH8sdkmv4oCfz9i5WHAGfsS/eHCpoff87sukoxwgaEBBd9YPhTwdaFE9njlw==", + "resolved": "6.0.33", + "contentHash": "o4I6H5vdDoILQvHJXvVdo33ts4zTb4FXcdc+Et1FYG0dao9GLrDQ3HXwgV8yU2M/JeEJJnsQvUwtaANJFDnjQQ==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization.Abstractions": "6.0.27", + "Microsoft.Extensions.Localization.Abstractions": "6.0.33", "Microsoft.Extensions.Logging.Abstractions": "6.0.4", "Microsoft.Extensions.Options": "6.0.0" } }, "Microsoft.Extensions.Localization.Abstractions": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "virsfnfbV6uJASaNKUXLQpdY0qGr48R6dUFwY00Qja5ea+kgntRgm7qzAH6GLeJjfW3zjoltrTiTrCbrAP3KCA==" + "resolved": "6.0.33", + "contentHash": "Hbq0a3DswFjen1K6hDljNENpy6bDbA/s2qsQ5M9kqa6fB3JVKWggAdqwx2GJG4+SGkZKOWkOZxQ1QVqavWaF5g==" }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", @@ -629,19 +607,19 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==", + "resolved": "4.61.3", + "contentHash": "naJo/Qm35Caaoxp5utcw+R8eU8ZtLz2ALh8S+gkekOYQ1oazfCQMWVT4NJ/FnHzdIJlm8dMz0oMpMGCabx5odA==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "6.22.0" + "Microsoft.IdentityModel.Abstractions": "6.35.0", + "System.Diagnostics.DiagnosticSource": "6.0.1" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==", + "resolved": "4.61.3", + "contentHash": "PWnJcznrSGr25MN8ajlc2XIDW4zCFu0U6FkpaNLEWLgd1NgFCp5uDY3mqLDgM8zCN8hqj8yo5wHYfLB2HjcdGw==", "dependencies": { - "Microsoft.Identity.Client": "4.56.0", - "System.IO.FileSystem.AccessControl": "5.0.0", + "Microsoft.Identity.Client": "4.61.3", "System.Security.Cryptography.ProtectedData": "4.5.0" } }, @@ -699,8 +677,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -714,13 +692,12 @@ }, "MimeKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "39KDXuERDy5VmHIn7NnCWvIVp/Ar4qnxZWg9m06DfRqDbW1B6zFv9o3Tdoa4CCu71tE/0SRqRCN5Z+bbffw6uw==", + "resolved": "4.7.1", + "contentHash": "Qoj4aVvhX14A1FNvaJ33hzOP4VZI2j+Mr38I9wSGcjMq4BYDtWLJG89aJ9nRW2cNfH6Czjwyp7+Mh++xv3AZvg==", "dependencies": { - "BouncyCastle.Cryptography": "2.2.1", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Security.Cryptography.Pkcs": "7.0.3", - "System.Text.Encoding.CodePages": "7.0.0" + "BouncyCastle.Cryptography": "2.4.0", + "System.Formats.Asn1": "8.0.1", + "System.Security.Cryptography.Pkcs": "8.0.0" } }, "MiniProfiler.AspNetCore": { @@ -782,6 +759,15 @@ "resolved": "4.5.1", "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" }, + "System.ClientModel": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "I3CVkvxeqFYjIVEP59DnjbeoGNfo/+SZrCLpRz2v/g0gpCHaEMPtWSY0s9k/7jR1rAsLNg2z2u1JRB76tPjnIw==", + "dependencies": { + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, "System.CodeDom": { "type": "Transitive", "resolved": "8.0.0", @@ -930,8 +916,8 @@ }, "System.Formats.Asn1": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "+nfpV0afLmvJW8+pLlHxRjz3oZJw4fkyU9MMEaMhCsHi/SN9bGF9q79ROubDiwTiCHezmK0uCWkPP7tGFP/4yg==" + "resolved": "8.0.1", + "contentHash": "XqKba7Mm/koKSjKMfW82olQdmfbI5yqeoLV/tidRp7fbh5rmHAQ5raDI/7SU0swTzv+jgqtUGkzmFxuUg0it1A==" }, "System.Globalization": { "type": "Transitive", @@ -1001,15 +987,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.IO.FileSystem.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", - "dependencies": { - "System.Security.AccessControl": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, "System.IO.FileSystem.Primitives": { "type": "Transitive", "resolved": "4.3.0", @@ -1269,29 +1246,17 @@ "System.Runtime": "4.3.0" } }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, "System.Security.Cryptography.Cng": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", - "dependencies": { - "System.Formats.Asn1": "5.0.0" - } + "resolved": "4.5.0", + "contentHash": "WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==" }, "System.Security.Cryptography.Pkcs": { "type": "Transitive", - "resolved": "7.0.3", - "contentHash": "yhwEHH5Gzl/VoADrXtt5XC95OFoSjNSWLHNutE7GwdOgefZVRvEXRSooSpL8HHm3qmdd9epqzsWg28UJemt22w==", + "resolved": "8.0.0", + "contentHash": "ULmp3xoOwNYjOYp4JZ2NK/6NdTgiN1GQXzVVN1njQ7LOZ0d0B9vyMnhyqbIi9Qw4JXj1JgCsitkTShboHRx7Eg==", "dependencies": { - "System.Formats.Asn1": "7.0.0" + "System.Formats.Asn1": "8.0.0" } }, "System.Security.Cryptography.ProtectedData": { @@ -1299,11 +1264,6 @@ "resolved": "8.0.0", "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1316,8 +1276,11 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.Text.Encoding.Extensions": { "type": "Transitive", @@ -1397,8 +1360,8 @@ }, "Yarp.ReverseProxy": { "type": "Transitive", - "resolved": "2.0.1", - "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "resolved": "2.1.0", + "contentHash": "VgRuCBxmh5ND4VuFhvIN3AAeoxFhYkS2hNINk6AVCrOVTlpk7OwdrTXi8NHACfqfhDL+/oYCZrF9RxN+yiYnEg==", "dependencies": { "System.IO.Hashing": "7.0.0" } diff --git a/tests/Kentico.Xperience.MiniProfiler.Tests/packages.lock.json b/tests/Kentico.Xperience.MiniProfiler.Tests/packages.lock.json index efb3560..151e62a 100644 --- a/tests/Kentico.Xperience.MiniProfiler.Tests/packages.lock.json +++ b/tests/Kentico.Xperience.MiniProfiler.Tests/packages.lock.json @@ -55,10 +55,11 @@ }, "Azure.Core": { "type": "Transitive", - "resolved": "1.36.0", - "contentHash": "vwqFZdHS4dzPlI7FFRkPx9ctA+aGGeRev3gnzG8lntWvKMmBhAmulABi1O9CEvS3/jzYt7yA+0pqVdxkpAd7dQ==", + "resolved": "1.41.0", + "contentHash": "7OO8rPCVSvXj2IQET3NkRf8hU2ZDCCvCIUhlrE089qkLNpNfWufJnBwHRKLAOWF3bhKBGJS/9hPBgjJ8kupUIg==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.ClientModel": "1.0.0", "System.Diagnostics.DiagnosticSource": "6.0.1", "System.Memory.Data": "1.0.2", "System.Numerics.Vectors": "4.5.0", @@ -69,12 +70,12 @@ }, "Azure.Identity": { "type": "Transitive", - "resolved": "1.10.3", - "contentHash": "l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==", + "resolved": "1.11.4", + "contentHash": "Sf4BoE6Q3jTgFkgBkx7qztYOFELBCo+wQgpYDwal/qJ1unBH73ywPztIJKXBXORRzAeNijsuxhk94h0TIMvfYg==", "dependencies": { - "Azure.Core": "1.35.0", - "Microsoft.Identity.Client": "4.56.0", - "Microsoft.Identity.Client.Extensions.Msal": "4.56.0", + "Azure.Core": "1.38.0", + "Microsoft.Identity.Client": "4.61.3", + "Microsoft.Identity.Client.Extensions.Msal": "4.61.3", "System.Memory": "4.5.4", "System.Security.Cryptography.ProtectedData": "4.7.0", "System.Text.Json": "4.7.2", @@ -83,44 +84,44 @@ }, "Azure.Storage.Blobs": { "type": "Transitive", - "resolved": "12.19.1", - "contentHash": "x43hWFJ4sPQ23TD4piCwT+KlQpZT8pNDAzqj6yUCqh+WJ2qcQa17e1gh6ZOeT2QNFQTTDSuR56fm2bIV7i11/w==", + "resolved": "12.21.2", + "contentHash": "2J+sMgNbj2DJ+ydRSqYYADDd2AajFLfPzLGxASOxcoGx4iVxyF6jscHw2IY+8QyMPWA09wN3lCtYJ5S4zIsJkA==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Text.Json": "4.7.2" } }, "Azure.Storage.Common": { "type": "Transitive", - "resolved": "12.18.1", - "contentHash": "ohCslqP9yDKIn+DVjBEOBuieB1QwsUCz+BwHYNaJ3lcIsTSiI4Evnq81HcKe8CqM8qvdModbipVQKpnxpbdWqA==", + "resolved": "12.20.1", + "contentHash": "KKBFnc4WZ6m9HgsKgwfO1cIxd154b8cAnP3uWhuelvFkzxqBXQQgIsHF0n3DYBG2AoTJCZDXwJpKuVC7CsKJWg==", "dependencies": { - "Azure.Core": "1.36.0", + "Azure.Core": "1.41.0", "System.IO.Hashing": "6.0.0" } }, "Azure.Storage.Queues": { "type": "Transitive", - "resolved": "12.17.1", - "contentHash": "ziN15iQ4+h0zf9EbKzFd5Zj3LiDH21qIrCknkXhpqwftPfIvlftvdyXbKQLi9+sh8dwT6PFPi/wq4oLsKNGfcQ==", + "resolved": "12.19.1", + "contentHash": "s7jBfSrEScS2yk5n61Xx+rNQCV+4SkFag17Wux4l8OufdBUkQPmEskQbOQxlPqBJNX1ycJRWj55Wd9Cz8lOLtQ==", "dependencies": { - "Azure.Storage.Common": "12.18.1", + "Azure.Storage.Common": "12.20.1", "System.Memory.Data": "1.0.2", "System.Text.Json": "4.7.2" } }, "BananaCakePop.Middleware": { "type": "Transitive", - "resolved": "13.0.0", - "contentHash": "6Zj/vfmnCXLjBG7WNdtOgZZ5ZDR3Sy1FQSshZUonIYs3OdzozmsFmqPXMd9XJ0QE9aAildgVGq/lDLpLrMI4Yw==", + "resolved": "16.0.3", + "contentHash": "gwWk5ykS1uum2/++x3UnGhmjs+4itxce1lW5YnKdb8JeG4QxAMzSWVGh3B1ehiKJNAuvNtbfBwp2BAQvOsq02g==", "dependencies": { - "Yarp.ReverseProxy": "2.0.1" + "Yarp.ReverseProxy": "2.1.0" } }, "BouncyCastle.Cryptography": { "type": "Transitive", - "resolved": "2.2.1", - "contentHash": "A6Zr52zVqJKt18ZBsTnX0qhG0kwIQftVAjLmszmkiR/trSp8H+xj1gUOzk7XHwaKgyREMSV1v9XaKrBUeIOdvQ==" + "resolved": "2.4.0", + "contentHash": "SwXsAV3sMvAU/Nn31pbjhWurYSjJ+/giI/0n6tCrYoupEK34iIHCuk3STAd9fx8yudM85KkLSVdn951vTng/vQ==" }, "CommandLineParser": { "type": "Transitive", @@ -129,8 +130,8 @@ }, "GreenDonut": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "KgsJ88vcX0UfSKAO7uzbEPOGu8wwJU3Vkgz7AgeTrnfdgIVjZFkesvMxDqjzY6F3fmMbJmfAOLjufYLFs1Fq1g==", + "resolved": "13.9.12", + "contentHash": "w/nOY3tM8nVmjI1Gyhv5/JVk3VyD7itRhz1Ul0A8C4MHavsEyNFaMA7J+lwBFKwSRsW4R52F0BhUVbomIDA5uQ==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0", "System.Diagnostics.DiagnosticSource": "8.0.0", @@ -139,169 +140,169 @@ }, "HotChocolate": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Dfue5pJ99mNWaIBYv6VupDLtZo8KhIGC9blQy76BAvkipd7m9K3xhBLNyxnUA5AmTXDrKdS+RVZ21ghG/pqeAw==", + "resolved": "13.9.12", + "contentHash": "eRHrmy5rNq9rcPrIsWvoEw5BNMDntCkzGa044fpfwKayAvSvzhsMRNRtrY351jGlg5779n3fSsabwofPu3haYw==", "dependencies": { - "HotChocolate.Authorization": "13.8.1", - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1", - "HotChocolate.Types.Mutations": "13.8.1", - "HotChocolate.Types.OffsetPagination": "13.8.1", - "HotChocolate.Validation": "13.8.1" + "HotChocolate.Authorization": "13.9.12", + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12", + "HotChocolate.Types.Mutations": "13.9.12", + "HotChocolate.Types.OffsetPagination": "13.9.12", + "HotChocolate.Validation": "13.9.12" } }, "HotChocolate.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "+llX8ziARzp+aKsOaXQfZAtqE+lF8gSmTiMiRCdpf03M+IWl/uCD9965nhqkM4mauWufwBXlwA7TE4uIUu+UjQ==", + "resolved": "13.9.12", + "contentHash": "zCDFmDV0lzDJQd7KvLthQ/d9x0TsVIKLXG3t/v0SgcQBYXnMvBeV094d+3cx44xE3T4lU4DpDeRTgD3rLLA+Dw==", "dependencies": { - "HotChocolate.Language": "13.8.1", + "HotChocolate.Language": "13.9.12", "System.Collections.Immutable": "8.0.0" } }, "HotChocolate.AspNetCore": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Pg4/+sGPCn5qNwo9z8GP/LcGHKaCRsozOwNw2XVnLRY9EDIOoN2jzblgaFuDqWkXe+rd2yAnxE7NHcdBohTEFQ==", + "resolved": "13.9.12", + "contentHash": "lv4vBVGFfTOofb/T7Fm+i0rJgyS5ZCBkCmryCcNAOw3YYpt8dL67Mms8+oIEPes04N9Wbimev+1pyxmBh5SpZg==", "dependencies": { - "BananaCakePop.Middleware": "13.0.0", - "HotChocolate": "13.8.1", - "HotChocolate.Subscriptions.InMemory": "13.8.1", - "HotChocolate.Transport.Sockets": "13.8.1", - "HotChocolate.Types.Scalars.Upload": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1" + "BananaCakePop.Middleware": "16.0.3", + "HotChocolate": "13.9.12", + "HotChocolate.Subscriptions.InMemory": "13.9.12", + "HotChocolate.Transport.Sockets": "13.9.12", + "HotChocolate.Types.Scalars.Upload": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12" } }, "HotChocolate.Authorization": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y+eLkswOMnSsPaO0fmY1gfNQD6I55SzXtAXhJIqsai1NpPeG2pu5b29y5UoGXNRQgb5/243gazbQbdM5j1S6PQ==", + "resolved": "13.9.12", + "contentHash": "LuTW5qZhD0bpZqQ1sTZJav+u6jc4JO7DltKhGM1nFWsOEPxMAx9OgyehQfuAoiGp0CPKHUI+M/LxDbXu1HFJog==", "dependencies": { - "HotChocolate.Execution": "13.8.1" + "HotChocolate.Execution": "13.9.12" } }, "HotChocolate.Data": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "tgXDs0TuyyPUMAUbPJltjll+HDSU19lX14IVe8J9WdDHGQXTScjyn1px8tX537wYh6Fy1XfBgrCKwmTV21+IdQ==", + "resolved": "13.9.12", + "contentHash": "NFsErsZVyMZntDrA6TPHvCgLCaOQ9QhZvmQmnVqcozLQvfCLuS6cSGwdN5zy+DKYa+yTaMG5DK7uKcxVWT//Sg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types.CursorPagination": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types.CursorPagination": "13.9.12" } }, "HotChocolate.Execution": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "co/VtIsOf3wqabsQLwO6HbTPi4UfL8UnzFlRkP2K4NNsNRdDkurYDdECS89swAuvfttzNua4MFOA4PclbW6Y/Q==", + "resolved": "13.9.12", + "contentHash": "UsuKiq7ynoqa9LvOjUHJAb4XTtnreFmjT3unhU6wz5cVeJU02eqbIQQyiOPDlv/SEk75XxJ1EjiuXZ/sKzcsag==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Fetching": "13.8.1", - "HotChocolate.Types": "13.8.1", - "HotChocolate.Utilities.DependencyInjection": "13.8.1", - "HotChocolate.Validation": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Fetching": "13.9.12", + "HotChocolate.Types": "13.9.12", + "HotChocolate.Utilities.DependencyInjection": "13.9.12", + "HotChocolate.Validation": "13.9.12", "Microsoft.Extensions.DependencyInjection": "8.0.0", "System.Threading.Channels": "8.0.0" } }, "HotChocolate.Execution.Abstractions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "sAL6A/Qa23inTgu8sWiNoaKpaJ3MosXLsiP908+XUogMOjudpWnaSWPYu5THgl1deaQ6q55gbyiFvwJx5lRR8A==", + "resolved": "13.9.12", + "contentHash": "o65we+xKpSpn/z5uqeTT3SW8+JEu4tufMxRCXXe38K504+WNy1yuuf3DpmwKBP0I3zeXMaWOsLLFcqzYKMAMXA==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Fetching": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "b1o8+gKmaE7rVX+fq/vFNFj+lcY414LoadaCcriEGEsz5fwIX5+SadmUIiaSuFOhuL+T8VLngh0zJXvPBI3sSA==", + "resolved": "13.9.12", + "contentHash": "dl098a0FSo2z0k3WwHdrlCeAn4fwFGOC2oQnkWjNGmTZAIuUaOrT1zoxLgFGJ/FLSUdB58jgYAiW+tD4zVE1+Q==", "dependencies": { - "GreenDonut": "13.8.1", - "HotChocolate.Types": "13.8.1" + "GreenDonut": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Language": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "qlljQwU51ecUyYa0qdOGHnWgP481QwwZsZRGwFuH/RbUwDVQOF8Fz/9aZxFmECkpiaCBfb8fHJOlzQGE52V6JQ==", + "resolved": "13.9.12", + "contentHash": "rohvOiAmZ9Wo8cLjnm5UwtrYrHfLm0YNKAqD7ZqK8QBqv3DTqlZTs3WMaJdkG6BLdZR/l8dK/g1Bl3BGhqSBJA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1", - "HotChocolate.Language.Utf8": "13.8.1", - "HotChocolate.Language.Visitors": "13.8.1", - "HotChocolate.Language.Web": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12", + "HotChocolate.Language.Utf8": "13.9.12", + "HotChocolate.Language.Visitors": "13.9.12", + "HotChocolate.Language.Web": "13.9.12" } }, "HotChocolate.Language.SyntaxTree": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "0RYVxhsxR1vf0ue/V8GZnN8UVxh1bI74KPe0vFLLlNXRSq55LXTuGt3gYc6+LxSCc4KaItzRl6DwdgRuDRINjw==", + "resolved": "13.9.12", + "contentHash": "rEmQ0OFW+LjTtYZNenFW9IKWTPJny8ACl1XnPULcGF22mgtuxItLwGJRfceRaAKqpAV2g7oLdFfLYmjqeJc3Tw==", "dependencies": { "Microsoft.Extensions.ObjectPool": "8.0.0" } }, "HotChocolate.Language.Utf8": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "y7YY6usRd72eAHjPS/NffT9cX92FJLg1Q6litLSCdjps1PnYVYTPnkNu5Ys1ngCJjOLsB71Or5CyjO5+Q8XSxA==", + "resolved": "13.9.12", + "contentHash": "JfsKnk734a0PxEFo9XGHiAiXNKI5qV1X0mAMcqRetljaiLGKKwYM/1ndvz3JS/gvVP/oltBaRKNKk1pWO9desg==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Visitors": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "aMibQ+gWIB+L+jZhiq2Vq+Jr6DsKcLwXAwr0GY8Dx54GPq9f/UHgtMi0KWrZ3sJck5/FwvENjLAuOtb2DFBREA==", + "resolved": "13.9.12", + "contentHash": "I2T8u0gRY0TxmjLm+EYjIreihp7oJQLhRXOs8p3y7BZAmJNxfeuc6EkMn8VDca1EQeiroNmC9UTawtJNV7QNyQ==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Language.Web": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "rQ0jTiWoHuPyF58bZ17AdfYezmrpwcHthNhjYBcVfAxkATsvrHzoPqNDIgpv8xv3xaMlpxsv+nPg+i9mW/zS2Q==", + "resolved": "13.9.12", + "contentHash": "/1HpNKOImaJcy6XLDPQaWqIE1H4Dmu4ST2Sl9lPE9EwDfYe6gBv3dS9mQ7jteyQQ7az05QhotXl2zDHD/Zx7lg==", "dependencies": { - "HotChocolate.Language.Utf8": "13.8.1" + "HotChocolate.Language.Utf8": "13.9.12" } }, "HotChocolate.Subscriptions": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "RD0eebXDBvfILKsy8dF7kMyR1puoPDzp0/BPUBzfEQalGi66F76P/cuGHN1fJrzTr1x2MIINsPmQN2udlfTTKQ==", + "resolved": "13.9.12", + "contentHash": "2VnYGlN9E7e5kGV76JU4Z/5sOag0wgUh694qwx4aPG1Lc5hPQDOL2BIk9jX7PmftHDmbxpNT3ZBvTSJXvGIoPQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Execution.Abstractions": "13.8.1" + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Execution.Abstractions": "13.9.12" } }, "HotChocolate.Subscriptions.InMemory": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "8A0K4bTBd1CfWbPovj/b1WYb52S8ElaOxghlS8Dea3GN8q4CCF3vSwXrzfkdVynCmrv3AFQYIXV1ddMJG1YqFQ==", + "resolved": "13.9.12", + "contentHash": "yQxVqqLUdMcl7yvU4qVhIrsRA1WIb1pkiKsXuD3FQxxucW9M4qqqklx91tY33AwIGnBGva7UCnofNxHg2FRbYg==", "dependencies": { - "HotChocolate.Execution.Abstractions": "13.8.1", - "HotChocolate.Subscriptions": "13.8.1", + "HotChocolate.Execution.Abstractions": "13.9.12", + "HotChocolate.Subscriptions": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, "HotChocolate.Transport.Sockets": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "YVfn1O+B0UlGKtieqRoGEeZjnFpSNjK1ZQVLvfKZ/DfCh+7FR9CwZ6II7YXWCE+M9sCQTvEo9Cz5XCpsnJDhIw==", + "resolved": "13.9.12", + "contentHash": "7VWxYdWBKhNA1LxBIba7okMvQDcaGzHlYhkmBtPGKtfg7sKqOrF6TrwlJg0peLnN8luG7TfW8Fmz8cbD7teEdA==", "dependencies": { "System.IO.Pipelines": "8.0.0" } }, "HotChocolate.Types": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "EK5PodS+N+Oi77jmBFucS6Leq0mL4xYjC2fDTq6Le+cNxMLYx+cY8PE5Kjg3rMtrd/MFOOvUSQ/heAes5nuBHQ==", + "resolved": "13.9.12", + "contentHash": "bTPnQZ0zolwj3E37ma2NPS5SxX6jj2OTQj9bszonB+92t0BQLOuX2wlgz0ux7XSmdC+ch7reCxJcrJEnPDs2QQ==", "dependencies": { - "HotChocolate.Abstractions": "13.8.1", - "HotChocolate.Types.Shared": "13.8.1", - "HotChocolate.Utilities": "13.8.1", + "HotChocolate.Abstractions": "13.9.12", + "HotChocolate.Types.Shared": "13.9.12", + "HotChocolate.Utilities": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.ObjectPool": "8.0.0", "System.ComponentModel.Annotations": "5.0.0", @@ -310,74 +311,74 @@ }, "HotChocolate.Types.CursorPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Nu7ERbmzIkZKeCx/dwMQDIEVXDk7fgMrGGsnBTBVNyk5YA/hyto54CNhlM7TeUqqhYUze3wKynA8rB1sr0f+cw==", + "resolved": "13.9.12", + "contentHash": "gjYxrEgQlcYTIcLMRUbF4/++C5c87OP7JU+f+YP6+BPID+r9tfEjC0U5KuRgbSg83t5jtgK1RpMLrbdTOUUGJg==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Mutations": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "euXYibxZS11BTQ+nhY991u4mfd72xK/25KYaA6/mkLR/to9z9Xb27QSukVF5cdCTEWnqBix6CdX3S5fq2YIYGw==", + "resolved": "13.9.12", + "contentHash": "Uvm+FfZISLM5+/vYuq4Rphns1UrfhiCfoLmdUtjMIPq4jVVl4unLxfcy1GrXdHVoBO7bOL1+gHl96e9S422+6w==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.OffsetPagination": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cwspQsQEOUBxjOAOvcmYObf4ol5pcI6epKQahrwfOX7v8GJd+FU0Sh8YmqOA1bks4VyjueDR06t88lw6XNeJIw==", + "resolved": "13.9.12", + "contentHash": "ipcyM/APH4J5oUFSE+TMYlCZ0n3lVvvap4eOHSXiriHlNM9/deLy5CooAlMmBkFbMsiFR8XcD9Ebc7od/xwm+g==", "dependencies": { - "HotChocolate.Execution": "13.8.1", - "HotChocolate.Types": "13.8.1" + "HotChocolate.Execution": "13.9.12", + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Scalars.Upload": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "cUMEyPMt57kEhB8kXvF5/lCyBZQkzkTFuSpTIZwTX3RmJ08bYWaXxpYLpor/jxjoe4qTIyGR+z7z2p8sIearMg==", + "resolved": "13.9.12", + "contentHash": "3cAHgOwyl0O6qznO7SyjYsUa/RdnSK1JnKxPkQ4lk5Y3pDpl4iLLKuGtReoS+n74h5WLE88U3RPR4x6JcWMDlw==", "dependencies": { - "HotChocolate.Types": "13.8.1" + "HotChocolate.Types": "13.9.12" } }, "HotChocolate.Types.Shared": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "vPpDZdVLahXD+a9xweLclWyIy3GH8IcKHmzZpOz4zeoZlxUuQCrx0ViXrSdiX1WdtOoV0nc5c26WKPIgCAVJIw==", + "resolved": "13.9.12", + "contentHash": "zWDYduCtLFxGqMV3vJ5lMfUv4h9ebU8dLwtG1Irtv5W5zOze0S+U6C0853hzDwL8/o6Torb5knQj56n78WBnAA==", "dependencies": { - "HotChocolate.Language.SyntaxTree": "13.8.1" + "HotChocolate.Language.SyntaxTree": "13.9.12" } }, "HotChocolate.Utilities": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "Z33UtFR96+iDR6uyjIW3qU3skvYEnhE/DGYnCoZUCh119t9OebvDW7ANCeL6oGXv0sZDJERvGQRhOZiBWZnqKA==" + "resolved": "13.9.12", + "contentHash": "Bo7aY9qaZ+8rcpDZFz9V03oVu4IWHmVgxlCDbMLYx1VJWOOyJA7pQb25ILxYVzScadn+lMkLy+4iq55GetLMhw==" }, "HotChocolate.Utilities.DependencyInjection": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "4tEg4xfDfiahuLrC59gH+BYfAFqDPEvoyBK7PU3ep7O2cmQgnqeE3tKMqJ1UovGMsVQ5nYwcQ98LhqrPOxECUw==", + "resolved": "13.9.12", + "contentHash": "iSTJZCLfpg7l+ExXFQbWsPPvkAPL+JLU3UA1E6avgTEzPvMpzo9I1c5mA2ItyoOrmTewKSWmnQBlv25oEFQF6g==", "dependencies": { "Microsoft.Extensions.DependencyInjection": "8.0.0" } }, "HotChocolate.Validation": { "type": "Transitive", - "resolved": "13.8.1", - "contentHash": "kmPmYrtCt1NtmyZiSvfjDU+Abc/4hI2wDLe1uDEZW8JC8O2uwH0becZm1K6j9ZUfVMLp/5ZNsQONOXzL1VwxLA==", + "resolved": "13.9.12", + "contentHash": "7DyCifF5kBD2hbrsFoQX+nVYMURaHDzAt8gFm3+Ubedqx91cV39iP/Mam1qgx3gh/shaKYSRQFw4Ao8TTpFj2Q==", "dependencies": { - "HotChocolate.Types": "13.8.1", + "HotChocolate.Types": "13.9.12", "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", "Microsoft.Extensions.Options": "8.0.0" } }, "HtmlSanitizer": { "type": "Transitive", - "resolved": "8.0.843", - "contentHash": "XfmHK4rFz9PPN0gcv7J7pc+MRpcni1mrnO04mwA+9/1zIHLgdOvLJeDwWnX5a+up4tioPvGreB+p+KljLJ32wg==", + "resolved": "8.1.870", + "contentHash": "bQWYaKg8PrlgnhM9sPALl0UorpjWQkPTQiSTVyvm8imqF9lCLqBmtC0adUDi8xUYcdg6SJC+aHCw1MOjcg+Wnw==", "dependencies": { "AngleSharp": "[0.17.1]", "AngleSharp.Css": "[0.17.0]", @@ -386,50 +387,32 @@ }, "Kentico.Xperience.Core": { "type": "Transitive", - "resolved": "28.3.1", - "contentHash": "pNl19ECq6pIFdcMxVmGF8o7q7azE0Bkdj7YTAcLlhIqGzzIlFRFc5J/2RARds5v1zPmbEfaJaU4UMwxWU8TGWA==", + "resolved": "29.5.3", + "contentHash": "8o6O60DtlCa2YZqFrKfMeb9F26/HXWXTEZNcUAhi7/zX8S9lWsFt1/ik1U21d6VRy2HA13EJIpuGbzbAQA+2nA==", "dependencies": { "AngleSharp": "0.17.1", - "MailKit": "4.3.0", - "Microsoft.AspNetCore.Http.Abstractions": "2.1.1", - "Microsoft.Data.SqlClient": "5.1.5", + "MailKit": "4.7.1.1", + "Microsoft.Data.SqlClient": "5.2.2", "Microsoft.Extensions.Caching.Memory": "6.0.1", "Microsoft.Extensions.Configuration": "6.0.1", "Microsoft.Extensions.Configuration.Binder": "6.0.0", "Microsoft.Extensions.DependencyInjection": "6.0.1", "Microsoft.Extensions.FileProviders.Physical": "6.0.0", "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization": "6.0.27", + "Microsoft.Extensions.Localization": "6.0.33", "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", "Mono.Cecil": "0.11.5", "Newtonsoft.Json": "13.0.3", - "System.CodeDom": "8.0.0", - "System.Configuration.ConfigurationManager": "6.0.1" + "System.CodeDom": "8.0.0" } }, "MailKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "jVmB3Nr0JpqhyMiXOGWMin+QvRKpucGpSFBCav9dG6jEJPdBV+yp1RHVpKzxZPfT+0adaBuZlMFdbIciZo1EWA==", - "dependencies": { - "MimeKit": "4.3.0" - } - }, - "Microsoft.AspNetCore.Http.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "kQUEVOU4loc8CPSb2WoHFTESqwIa8Ik7ysCBfTwzHAd0moWovc9JQLmhDIHlYLjHbyexqZAlkq/FPRUZqokebw==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "2.1.1", - "System.Text.Encodings.Web": "4.5.0" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VklZ7hWgSvHBcDtwYYkdMdI/adlf7ebxTZ9kdzAhX+gUs5jSHE9mZlTamdgf9miSsxc1QjNazHXTDJdVPZKKTw==", + "resolved": "4.7.1.1", + "contentHash": "Y3okmIxu8g/ZcoJiE2i+dCeKgnNyddsXmcJslZnCPGVPP0aRyeVINHV1h97V+OVMdqjQI6O12J2p8Duwq5UEqQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" + "MimeKit": "4.7.1", + "System.Formats.Asn1": "8.0.1" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -449,28 +432,23 @@ }, "Microsoft.Data.SqlClient": { "type": "Transitive", - "resolved": "5.1.5", - "contentHash": "6kvhQjY5uBCdBccezFD2smfnpQjQ33cZtUZVrNvxlwoBu6uopM5INH6uSgLI7JRLtlQ3bMPwnhMq4kchsXeZ5w==", + "resolved": "5.2.2", + "contentHash": "mtoeRMh7F/OA536c/Cnh8L4H0uLSKB5kSmoi54oN7Fp0hNJDy22IqyMhaMH4PkDCqI7xL//Fvg9ldtuPHG0h5g==", "dependencies": { - "Azure.Identity": "1.10.3", - "Microsoft.Data.SqlClient.SNI.runtime": "5.1.1", - "Microsoft.Identity.Client": "4.56.0", + "Azure.Identity": "1.11.4", + "Microsoft.Data.SqlClient.SNI.runtime": "5.2.0", + "Microsoft.Identity.Client": "4.61.3", "Microsoft.IdentityModel.JsonWebTokens": "6.35.0", "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0", "Microsoft.SqlServer.Server": "1.0.0", - "System.Configuration.ConfigurationManager": "6.0.1", - "System.Diagnostics.DiagnosticSource": "6.0.1", - "System.Runtime.Caching": "6.0.0", - "System.Security.Cryptography.Cng": "5.0.0", - "System.Security.Principal.Windows": "5.0.0", - "System.Text.Encoding.CodePages": "6.0.0", - "System.Text.Encodings.Web": "6.0.0" + "System.Configuration.ConfigurationManager": "8.0.0", + "System.Runtime.Caching": "8.0.0" } }, "Microsoft.Data.SqlClient.SNI.runtime": { "type": "Transitive", - "resolved": "5.1.1", - "contentHash": "wNGM5ZTQCa2blc9ikXQouybGiyMd6IHPVJvAlBEPtr6JepZEOYeDxGyprYvFVeOxlCXs7avridZQ0nYkHzQWCQ==" + "resolved": "5.2.0", + "contentHash": "po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==" }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", @@ -540,8 +518,8 @@ }, "Microsoft.Extensions.FileProviders.Embedded": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "trrI4tXQsOIB56H3u/wD4aVu5QtF8nJPtBuQ6wm8phlYSFTR3Rj3/9fXA5Mrz4X2B0lwOk1QndCPL/fWhH9Izw==", + "resolved": "6.0.33", + "contentHash": "A5HxR46JT3B81XtfYY1/vr4RvICcue7/7lkOjrTMhGX0RdDXqQHXL1NpeYB27S1CLlsjuJn2fF1LSeGRnYJbgg==", "dependencies": { "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } @@ -573,19 +551,19 @@ }, "Microsoft.Extensions.Localization": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "sqwoeaqGTeSMBTrUV8ysD8JPfUcH8sdkmv4oCfz9i5WHAGfsS/eHCpoff87sukoxwgaEBBd9YPhTwdaFE9njlw==", + "resolved": "6.0.33", + "contentHash": "o4I6H5vdDoILQvHJXvVdo33ts4zTb4FXcdc+Et1FYG0dao9GLrDQ3HXwgV8yU2M/JeEJJnsQvUwtaANJFDnjQQ==", "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", - "Microsoft.Extensions.Localization.Abstractions": "6.0.27", + "Microsoft.Extensions.Localization.Abstractions": "6.0.33", "Microsoft.Extensions.Logging.Abstractions": "6.0.4", "Microsoft.Extensions.Options": "6.0.0" } }, "Microsoft.Extensions.Localization.Abstractions": { "type": "Transitive", - "resolved": "6.0.27", - "contentHash": "virsfnfbV6uJASaNKUXLQpdY0qGr48R6dUFwY00Qja5ea+kgntRgm7qzAH6GLeJjfW3zjoltrTiTrCbrAP3KCA==" + "resolved": "6.0.33", + "contentHash": "Hbq0a3DswFjen1K6hDljNENpy6bDbA/s2qsQ5M9kqa6fB3JVKWggAdqwx2GJG4+SGkZKOWkOZxQ1QVqavWaF5g==" }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", @@ -625,19 +603,19 @@ }, "Microsoft.Identity.Client": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==", + "resolved": "4.61.3", + "contentHash": "naJo/Qm35Caaoxp5utcw+R8eU8ZtLz2ALh8S+gkekOYQ1oazfCQMWVT4NJ/FnHzdIJlm8dMz0oMpMGCabx5odA==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "6.22.0" + "Microsoft.IdentityModel.Abstractions": "6.35.0", + "System.Diagnostics.DiagnosticSource": "6.0.1" } }, "Microsoft.Identity.Client.Extensions.Msal": { "type": "Transitive", - "resolved": "4.56.0", - "contentHash": "H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==", + "resolved": "4.61.3", + "contentHash": "PWnJcznrSGr25MN8ajlc2XIDW4zCFu0U6FkpaNLEWLgd1NgFCp5uDY3mqLDgM8zCN8hqj8yo5wHYfLB2HjcdGw==", "dependencies": { - "Microsoft.Identity.Client": "4.56.0", - "System.IO.FileSystem.AccessControl": "5.0.0", + "Microsoft.Identity.Client": "4.61.3", "System.Security.Cryptography.ProtectedData": "4.5.0" } }, @@ -695,8 +673,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -728,13 +706,12 @@ }, "MimeKit": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "39KDXuERDy5VmHIn7NnCWvIVp/Ar4qnxZWg9m06DfRqDbW1B6zFv9o3Tdoa4CCu71tE/0SRqRCN5Z+bbffw6uw==", + "resolved": "4.7.1", + "contentHash": "Qoj4aVvhX14A1FNvaJ33hzOP4VZI2j+Mr38I9wSGcjMq4BYDtWLJG89aJ9nRW2cNfH6Czjwyp7+Mh++xv3AZvg==", "dependencies": { - "BouncyCastle.Cryptography": "2.2.1", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Security.Cryptography.Pkcs": "7.0.3", - "System.Text.Encoding.CodePages": "7.0.0" + "BouncyCastle.Cryptography": "2.4.0", + "System.Formats.Asn1": "8.0.1", + "System.Security.Cryptography.Pkcs": "8.0.0" } }, "MiniProfiler.AspNetCore": { @@ -783,6 +760,15 @@ "resolved": "4.5.1", "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" }, + "System.ClientModel": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "I3CVkvxeqFYjIVEP59DnjbeoGNfo/+SZrCLpRz2v/g0gpCHaEMPtWSY0s9k/7jR1rAsLNg2z2u1JRB76tPjnIw==", + "dependencies": { + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, "System.CodeDom": { "type": "Transitive", "resolved": "8.0.0", @@ -931,8 +917,8 @@ }, "System.Formats.Asn1": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "+nfpV0afLmvJW8+pLlHxRjz3oZJw4fkyU9MMEaMhCsHi/SN9bGF9q79ROubDiwTiCHezmK0uCWkPP7tGFP/4yg==" + "resolved": "8.0.1", + "contentHash": "XqKba7Mm/koKSjKMfW82olQdmfbI5yqeoLV/tidRp7fbh5rmHAQ5raDI/7SU0swTzv+jgqtUGkzmFxuUg0it1A==" }, "System.Globalization": { "type": "Transitive", @@ -980,15 +966,6 @@ "System.Threading.Tasks": "4.3.0" } }, - "System.IO.FileSystem.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", - "dependencies": { - "System.Security.AccessControl": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, "System.IO.FileSystem.Primitives": { "type": "Transitive", "resolved": "4.3.0", @@ -1217,29 +1194,17 @@ "System.Runtime": "4.3.0" } }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, "System.Security.Cryptography.Cng": { "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", - "dependencies": { - "System.Formats.Asn1": "5.0.0" - } + "resolved": "4.5.0", + "contentHash": "WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==" }, "System.Security.Cryptography.Pkcs": { "type": "Transitive", - "resolved": "7.0.3", - "contentHash": "yhwEHH5Gzl/VoADrXtt5XC95OFoSjNSWLHNutE7GwdOgefZVRvEXRSooSpL8HHm3qmdd9epqzsWg28UJemt22w==", + "resolved": "8.0.0", + "contentHash": "ULmp3xoOwNYjOYp4JZ2NK/6NdTgiN1GQXzVVN1njQ7LOZ0d0B9vyMnhyqbIi9Qw4JXj1JgCsitkTShboHRx7Eg==", "dependencies": { - "System.Formats.Asn1": "7.0.0" + "System.Formats.Asn1": "8.0.0" } }, "System.Security.Cryptography.ProtectedData": { @@ -1247,11 +1212,6 @@ "resolved": "8.0.0", "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, "System.Text.Encoding": { "type": "Transitive", "resolved": "4.3.0", @@ -1264,8 +1224,11 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "7.0.0", - "contentHash": "LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==" + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.Text.Encodings.Web": { "type": "Transitive", @@ -1334,8 +1297,8 @@ }, "Yarp.ReverseProxy": { "type": "Transitive", - "resolved": "2.0.1", - "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "resolved": "2.1.0", + "contentHash": "VgRuCBxmh5ND4VuFhvIN3AAeoxFhYkS2hNINk6AVCrOVTlpk7OwdrTXi8NHACfqfhDL+/oYCZrF9RxN+yiYnEg==", "dependencies": { "System.IO.Hashing": "7.0.0" } @@ -1344,36 +1307,36 @@ "type": "Project", "dependencies": { "MiniProfiler.AspNetCore.Mvc": "[4.3.8, )", - "kentico.xperience.azurestorage": "[28.3.1, )", - "kentico.xperience.webapp": "[28.3.1, )" + "kentico.xperience.azurestorage": "[29.5.3, )", + "kentico.xperience.webapp": "[29.5.3, )" } }, "Kentico.Xperience.AzureStorage": { "type": "CentralTransitive", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "uBOgWJHlMzmO6+BZk1o2BDrSvdDioKftpQ/ljVm+4y/qVBBXqFli7vHbW/bEmdla9rj1T8bTw37OgklM/gGNRA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "d27b5FANBrdWR4uJEeEVnqfta97FLi5vreWr0lmdwqfHaUQMpI87vJ7Q+v+u/NQ+qtlBtyor6fN03vYwOLln4Q==", "dependencies": { - "Azure.Storage.Blobs": "12.19.1", - "Azure.Storage.Queues": "12.17.1", - "Kentico.Xperience.Core": "28.3.1", + "Azure.Storage.Blobs": "12.21.2", + "Azure.Storage.Queues": "12.19.1", + "Kentico.Xperience.Core": "29.5.3", "Newtonsoft.Json": "13.0.3" } }, "Kentico.Xperience.WebApp": { "type": "CentralTransitive", - "requested": "[28.3.1, )", - "resolved": "28.3.1", - "contentHash": "I9gz6Gq1XLbXTQ/RtCDuWpBVMYurT4+KrwfKublmxXQILpLwQzvFv5GRYe9Fa3AaHEThIdttSSv2l1y3ybzbqA==", + "requested": "[29.5.3, )", + "resolved": "29.5.3", + "contentHash": "n4V4V3fVq8ZRrus2I9RF8KcD0fX0QWE2aGsbC6Pb8g+kcai1TFHk/dsiOzDCSLSRFGMVyl/xt0o1OOBedXdWUg==", "dependencies": { "CommandLineParser": "2.9.1", - "HotChocolate.AspNetCore": "13.8.1", - "HotChocolate.Data": "13.8.1", - "HtmlSanitizer": "8.0.843", - "Kentico.Xperience.Core": "[28.3.1]", - "Microsoft.Extensions.FileProviders.Embedded": "6.0.27", - "Microsoft.Extensions.Localization": "6.0.27", - "System.Runtime.Caching": "8.0.0" + "HotChocolate.AspNetCore": "13.9.12", + "HotChocolate.Data": "13.9.12", + "HtmlSanitizer": "8.1.870", + "Kentico.Xperience.Core": "[29.5.3]", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.33", + "Microsoft.Extensions.Localization": "6.0.33" } }, "MiniProfiler.AspNetCore.Mvc": {