try new way to create URLs

This commit is contained in:
2020-10-22 00:32:44 +02:00
parent 2671d34f4e
commit bf8a0664ef
6 changed files with 309 additions and 2 deletions
+10
View File
@@ -0,0 +1,10 @@
namespace zero.Core.Entities
{
public interface IRoutedEntity
{
/// <summary>
/// Url for this entity
/// </summary>
public string Url { get; set; }
}
}
+4 -1
View File
@@ -10,6 +10,9 @@ namespace zero.Core.Entities
/// </summary>
public class Page : ZeroEntity, IPage
{
/// <inheritdoc />
public string Url { get; set; }
/// <inheritdoc />
public string ParentId { get; set; }
@@ -25,7 +28,7 @@ namespace zero.Core.Entities
[Collection("Pages")]
public interface IPage : IZeroEntity, IAppAwareEntity, IZeroDbConventions
public interface IPage : IZeroEntity, IAppAwareEntity, IZeroDbConventions, IRoutedEntity
{
/// <summary>
/// Id of the parent page
+6
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zero.Core.Api;
using zero.Core.Entities;
@@ -9,6 +10,11 @@ namespace zero.Core.Routing
{
public interface IPageUrlResolver
{
/// <summary>
/// Get URL for a page
/// </summary>
Task<string> GetUrl(IPage page);
/// <summary>
/// Get URL for a page
/// </summary>
+136
View File
@@ -0,0 +1,136 @@
using Raven.Client.Documents;
using Raven.Client.Documents.Linq;
using Raven.Client.Documents.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zero.Core.Api;
using zero.Core.Entities;
using zero.Core.Entities.Messages;
using zero.Core.Extensions;
using zero.Core.Messages;
using zero.Core.Utils;
namespace zero.Core.Routing
{
public class PageUrlProviderOld : IUrlProvider<PageRoute>
{
public string Alias => "zero.pages";
public const string PAGE_COLLECTION = "page";
public const string PAGE_TYPE = "pageType";
protected IDocumentStore Raven { get; private set; }
protected IMessageAggregator Messages { get; private set; }
protected IPageUrlResolver PageUrlResolver { get; set; }
protected IApplicationContext Context { get; private set; }
public PageUrlProviderOld(IDocumentStore raven, IMessageAggregator messages, IPageUrlResolver pageUrlResolver, IApplicationContext context)
{
Raven = raven;
Messages = messages;
PageUrlResolver = pageUrlResolver;
Context = context;
}
/// <inheritdoc />
public async Task<PageRoute> Resolve(IRoute route)
{
PageRoute resolved = new PageRoute(route);
List<string> ids = new List<string>();
RouteReference reference = route.References.SingleOrDefault(x => x.Collection == PAGE_COLLECTION);
ids.Add(reference.Id);
ids.AddRange(route.Dependencies);
using IAsyncDocumentSession session = Raven.OpenAsyncSession();
Dictionary<string, IPage> pages = await session.LoadAsync<IPage>(ids);
if (!pages.TryGetValue(reference.Id, out IPage page) || page.AppId != route.AppId)
{
return null;
}
resolved.Page = page;
resolved.Parents = pages.Where(x => x.Key != reference.Id).Select(x => x.Value).ToList();
return resolved;
}
/// <inheritdoc />
public async Task<IList<IRoute>> Run()
{
using IAsyncDocumentSession session = Raven.OpenAsyncSession();
List<IRoute> allRoutes = new List<IRoute>();
IList<IPage> pages = await session.Query<IPage>().ToListAsync();
IEnumerable<IGrouping<string, IPage>> groupedPages = pages.GroupBy(x => x.AppId);
foreach (var group in groupedPages)
{
IApplicationContext context = await Context.ForId(group.Key);
IList<IRoute> routes = TraversePageChildren(context, null, new List<IPage>() { }, group);
allRoutes.AddRange(routes);
}
return allRoutes;
}
protected IRoute BuildRoute(IApplicationContext context, IPage page, IEnumerable<IPage> parents)
{
UrlInfo info = PageUrlResolver.GetUrl(context, page, parents);
IRoute route = new Route()
{
Id = String.Concat("routes.", IdGenerator.Create()),
AppId = context.AppId,
Url = info.IsUrl ? info.Text.EnsureStartsWith('/') : null,
ProviderAlias = Alias
};
route.Params.Add(PAGE_TYPE, page.PageTypeAlias);
route.References.Add(new RouteReference(page.Id, PAGE_COLLECTION));
if (parents != null)
{
foreach (IPage parent in parents)
{
route.Dependencies.Add(parent.Id);
}
}
return route;
}
IList<IRoute> TraversePageChildren(IApplicationContext context, IPage parent, IEnumerable<IPage> parents, IEnumerable<IPage> allPages)
{
List<IRoute> routes = new List<IRoute>();
IEnumerable<IPage> currentPages = allPages.Where(x => x.ParentId == parent?.Id);
foreach (IPage page in currentPages)
{
IRoute route = BuildRoute(context, page, parents);
routes.Add(route);
routes.AddRange(TraversePageChildren(context, page, parents.Union(new List<IPage>() { page }), allPages));
}
return routes;
}
}
}
+105
View File
@@ -0,0 +1,105 @@
using Raven.Client.Documents;
using Raven.Client.Documents.Linq;
using Raven.Client.Documents.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zero.Core.Api;
using zero.Core.Database.Indexes;
using zero.Core.Entities;
using zero.Core.Entities.Messages;
using zero.Core.Extensions;
using zero.Core.Messages;
using zero.Core.Utils;
namespace zero.Core.Routing
{
public class PageUrlProviderTest
{
public string Alias => "zero.pages";
public const string PAGE_COLLECTION = "page";
public const string PAGE_TYPE = "pageType";
protected IDocumentStore Raven { get; private set; }
protected IMessageAggregator Messages { get; private set; }
protected IPageUrlResolver PageUrlResolver { get; set; }
protected IApplicationContext Context { get; private set; }
public PageUrlProviderTest(IDocumentStore raven, IMessageAggregator messages, IPageUrlResolver pageUrlResolver, IApplicationContext context)
{
Raven = raven;
Messages = messages;
PageUrlResolver = pageUrlResolver;
Context = context;
}
/// <inheritdoc />
public bool UrlChanged(IPage previous, IPage current)
{
return previous == null || !previous.Alias.Equals(current.Alias) || !previous.ParentId.Equals(current.ParentId);
}
/// <inheritdoc />
public Task GetDependencies(IPage model)
{
// TODO get all pages (and other routes) which have this page as a dependency and update them
throw new NotImplementedException();
}
/// <inheritdoc />
public async Task<IRoute> CreateRoute(IPage model)
{
using IAsyncDocumentSession session = Raven.OpenAsyncSession();
Pages_ByHierarchy.Result result = await session.Query<Pages_ByHierarchy.Result, Pages_ByHierarchy>()
.ProjectInto<Pages_ByHierarchy.Result>()
.Include<Pages_ByHierarchy.Result, IPage>(x => x.Path.Select(p => p.Id))
.FirstOrDefaultAsync(x => x.Id == model.Id);
IList<IPage> parents = (await session.LoadAsync<IPage>(result.Path.Select(x => x.Id))).Select(x => x.Value).ToList();
return new Route()
{
Id = String.Concat("routes.", IdGenerator.Create()),
AppId = model.AppId,
Url = GetUrl(model, parents),
ProviderAlias = Alias
};
}
/// <summary>
/// Create url for page
/// </summary>
protected string GetUrl(IPage page, IEnumerable<IPage> parents)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append('/');
if (parents != null)
{
foreach (IPage parent in parents)
{
stringBuilder.Append(parent.Alias);
stringBuilder.Append('/');
}
}
stringBuilder.Append(page.Alias);
return stringBuilder.ToString();
}
}
}
+48 -1
View File
@@ -1,8 +1,12 @@
using System;
using Raven.Client.Documents;
using Raven.Client.Documents.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zero.Core.Api;
using zero.Core.Database.Indexes;
using zero.Core.Entities;
namespace zero.Core.Routing
@@ -13,6 +17,49 @@ namespace zero.Core.Routing
const bool TRAILING_SLASH = false;
protected IDocumentStore Raven { get; private set; }
public PageUrlResolver(IDocumentStore raven)
{
Raven = raven;
}
/// <inheritdoc />
public async Task<string> GetUrl(IPage page)
{
using IAsyncDocumentSession session = Raven.OpenAsyncSession();
Pages_ByHierarchy.Result result = await session.Query<Pages_ByHierarchy.Result, Pages_ByHierarchy>()
.ProjectInto<Pages_ByHierarchy.Result>()
.Include<Pages_ByHierarchy.Result, IPage>(x => x.Path.Select(p => p.Id))
.FirstOrDefaultAsync(x => x.Id == page.Id);
IList<IPage> parents = (await session.LoadAsync<IPage>(result.Path.Select(x => x.Id))).Select(x => x.Value).ToList();
StringBuilder stringBuilder = new StringBuilder();
if (parents != null)
{
foreach (IPage parent in parents)
{
stringBuilder.Append(parent.Alias);
stringBuilder.Append(PATH_SEPARATOR);
}
}
stringBuilder.Append(page.Alias);
stringBuilder.Append(PATH_SEPARATOR);
if (!TRAILING_SLASH)
{
stringBuilder.Remove(stringBuilder.Length - 1, 1);
}
return stringBuilder.ToString();
}
/// <inheritdoc />
public UrlInfo GetUrl(IApplicationContext context, IPage page, IEnumerable<IPage> parents)