diff --git a/old/zero.Core/Entities/Settings/SettingsArea.cs b/old/zero.Core/Entities/Settings/SettingsArea.cs
deleted file mode 100644
index b2315949..00000000
--- a/old/zero.Core/Entities/Settings/SettingsArea.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-namespace zero.Core.Entities
-{
- ///
- /// Defines an area in the settings section
- ///
- public class SettingsArea
- {
- ///
- /// Alias which used for the URL part
- ///
- public string Alias { get; }
-
- ///
- /// Name of the settings area
- ///
- public string Name { get; }
-
- ///
- /// Icon displayed next to the area name
- ///
- public string Icon { get; }
-
- ///
- /// Further describe the area
- ///
- public string Description { get; }
-
- ///
- /// Set a custom URL for this settings area link
- ///
- public string CustomUrl { get; set; }
-
-
- public SettingsArea() { }
-
- public SettingsArea(string alias, string name, string description = null, string icon = null, string customUrl = null)
- {
- Alias = alias;
- Name = name;
- Icon = icon;
- Description = description;
- CustomUrl = customUrl;
- }
- }
-
-
- public class InternalSettingsArea : SettingsArea
- {
- public InternalSettingsArea() { }
- public InternalSettingsArea(string alias, string name, string description = null, string icon = null) : base(alias, name, description, icon) { }
- }
-}
diff --git a/old/zero.Core/Entities/Settings/SettingsGroup.cs b/old/zero.Core/Entities/Settings/SettingsGroup.cs
deleted file mode 100644
index 501f0cfe..00000000
--- a/old/zero.Core/Entities/Settings/SettingsGroup.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Collections.Generic;
-
-namespace zero.Core.Entities
-{
- public class InternalSettingsGroup : SettingsGroup { }
-
- public class SettingsGroup
- {
- public string Name { get; set; }
-
- public IList Items { get; set; } = new List();
-
- public SettingsGroup() { }
-
- public SettingsGroup(string name)
- {
- Name = name;
- }
-
- public void Add(string alias, string name, string description = null, string icon = null, string customUrl = null)
- {
- Items.Add(new SettingsArea(alias, name, description, icon, customUrl));
- }
-
- public void AddInternal(string alias, string name, string description = null, string icon = null)
- {
- Items.Add(new InternalSettingsArea(alias, name, description, icon));
- }
- }
-}
diff --git a/old/zero.Web/Controllers/ZeroBackofficeCollectionController.cs b/old/zero.Web/Controllers/ZeroBackofficeCollectionController.cs
deleted file mode 100644
index 454256e5..00000000
--- a/old/zero.Web/Controllers/ZeroBackofficeCollectionController.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Raven.Client.Documents.Linq;
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using zero.Core;
-using zero.Core.Entities;
-using zero.Web.Models;
-
-
-namespace zero.Web.Controllers
-{
- public abstract class ZeroBackofficeCollectionController : BackofficeController
- where TEntity : ZeroIdEntity, new()
- where TCollection : IEntityCollection
- {
- protected TCollection Collection { get; private set; }
-
- [Obsolete]
- protected Func, IRavenQueryable> DefaultQuery { get; set; }
-
- protected Action PreviewTransform { get; set; }
-
- protected Action PickerTransform { get; set; }
-
-
- public ZeroBackofficeCollectionController(TCollection collection)
- {
- Collection = collection;
- }
-
- public override void OnScopeChanged(string scope)
- {
- //Collection.ApplyScope(scope);
- }
-
-
- public virtual async Task> GetById([FromQuery] string id, [FromQuery] string changeVector = null) => Edit(await Collection.Load(id, changeVector));
-
-
- public virtual async Task> GetByIds([FromQuery] string[] ids) => await Collection.Load(ids);
-
-
- public virtual async Task> GetEmpty() => Edit(await Collection.Empty());
-
-
- public virtual async Task> GetByQuery([FromQuery] ListBackofficeQuery query)
- {
- return await Collection.Load(query);
- }
-
-
- public virtual async Task> GetRevisions([FromQuery] string id, [FromQuery] ListBackofficeQuery query)
- {
- return null; // TODO
- //return await Collection.GetRevisions(id, query.Page, query.PageSize);
- }
-
-
- public virtual async Task> GetForPicker() => await SelectList(Collection.Stream(), PickerTransform);
-
-
- public virtual async Task> GetPreviews([FromQuery] List ids) => Previews(await Collection.Load(ids), PreviewTransform);
-
-
- [HttpPost]
- public virtual async Task> Save([FromBody] TEntity model) => await Collection.Save(model);
-
-
- [HttpDelete]
- public virtual async Task> Delete([FromQuery] string id) => await Collection.Delete(id);
- }
-}
diff --git a/old/zero.Web/Controllers/ZeroBackofficeController.cs b/old/zero.Web/Controllers/ZeroBackofficeController.cs
deleted file mode 100644
index 36bec8f4..00000000
--- a/old/zero.Web/Controllers/ZeroBackofficeController.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Options;
-using zero.Core.Extensions;
-using zero.Core.Identity;
-using zero.Core.Options;
-using zero.Web.Models;
-using Zero.Web.DevServer;
-
-namespace zero.Web.Controllers
-{
- [ZeroAuthorize(false)]
- public class ZeroBackofficeController : Controller
- {
- IZeroVue ZeroVue { get; set; }
- IZeroOptions Options { get; set; }
- IOptions DevServerOptions { get; set; }
-
- public ZeroBackofficeController(IZeroVue zeroVue, IZeroOptions options, IOptions devServerOptions)
- {
- ZeroVue = zeroVue;
- Options = options;
- DevServerOptions = devServerOptions;
- }
-
-
- public IActionResult Index()
- {
- if (Options.ZeroVersion.IsNullOrEmpty())
- {
- return RedirectToAction("ZeroBackoffice", "Setup");
- }
-
- return View("Views/Zero/Index.cshtml", new ZeroBackofficeModel()
- {
- Port = DevServerOptions.Value.Port,
- Vue = ZeroVue
- });
- }
- }
-}
diff --git a/old/zero.Web/Controllers/ZeroBackofficeControllerModelConvention.cs b/old/zero.Web/Controllers/ZeroBackofficeControllerModelConvention.cs
deleted file mode 100644
index c84ac3db..00000000
--- a/old/zero.Web/Controllers/ZeroBackofficeControllerModelConvention.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.ApplicationModels;
-using System;
-
-namespace zero.Web.Controllers
-{
- public class ZeroBackofficeControllerModelConvention : IControllerModelConvention
- {
- readonly AttributeRouteModel RouteModel;
-
- readonly Type BaseClass = typeof(BackofficeController);
-
-
- public ZeroBackofficeControllerModelConvention(string backofficePath)
- {
- RouteModel = new AttributeRouteModel(new RouteAttribute(backofficePath + "/api/[controller]/[action]"));
- }
-
-
- public void Apply(ControllerModel controller)
- {
- if (!controller.ControllerType.IsSubclassOf(BaseClass))
- {
- return;
- }
-
- foreach (var selector in controller.Selectors)
- {
- selector.AttributeRouteModel = RouteModel;
- }
- }
- }
-}
diff --git a/old/zero.Web/Controllers/ZeroController.cs b/old/zero.Web/Controllers/ZeroController.cs
deleted file mode 100644
index 09e44799..00000000
--- a/old/zero.Web/Controllers/ZeroController.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.DependencyInjection;
-using zero.Core;
-using zero.Core.Entities;
-using zero.Core.Routing;
-
-namespace zero.Web.Controllers
-{
- public abstract class ZeroController : ZeroController { }
-
-
- public abstract class ZeroController : Controller where T : class, IRouteModel
- {
- public virtual Application Application => Context?.Application;
-
- T _route;
- public virtual T Route => _route ?? (_route = HttpContext.Features.Get() as T);
-
- IZeroContext _context;
- public IZeroContext Context => _context ?? (_context = HttpContext?.RequestServices?.GetService());
- }
-}
diff --git a/old/zero.Web/Controllers/ZeroFrontendController.cs b/old/zero.Web/Controllers/ZeroFrontendController.cs
deleted file mode 100644
index 9df072fd..00000000
--- a/old/zero.Web/Controllers/ZeroFrontendController.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Newtonsoft.Json;
-using System;
-using System.Linq.Expressions;
-using zero.Core.Routing;
-
-namespace zero.Web.Controllers
-{
- public class ZeroFrontendController : ZeroController
- {
- public ZeroFrontendController()
- {
- }
-
- public IActionResult Index()
- {
- return Json(new { Application, Route }, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None });
- }
- }
-}
diff --git a/old/zero.Web/Defaults/ApplicationSettings.cs b/old/zero.Web/Defaults/ApplicationSettings.cs
deleted file mode 100644
index d581b8bf..00000000
--- a/old/zero.Web/Defaults/ApplicationSettings.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using zero.Core;
-using zero.Core.Entities;
-
-namespace zero.Web.Defaults
-{
- public class ApplicationSettings : SettingsGroup
- {
- public ApplicationSettings()
- {
- Name = "@settings.groups.application";
-
- //AddInternal(Constants.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text", "fth-check-circle");
- AddInternal(Constants.Settings.Languages, "@settings.application.languages.name", "@settings.application.languages.text", "fth-globe");
- AddInternal(Constants.Settings.Countries, "@settings.application.countries.name", "@settings.application.countries.text", "fth-map-pin");
- AddInternal(Constants.Settings.Translations, "@settings.application.translations.name", "@settings.application.translations.text", "fth-type");
- AddInternal(Constants.Settings.Mails, "@settings.application.mails.name", "@settings.application.mails.text", "fth-mail");
- AddInternal(Constants.Settings.Integrations, "@settings.application.integrations.name", "@settings.application.integrations.text", "fth-sliders");
- //AddInternal(Constants.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", "fth-file-text");
- }
- }
-}
diff --git a/old/zero.Web/Defaults/SettingsPermissions.cs b/old/zero.Web/Defaults/SettingsPermissions.cs
deleted file mode 100644
index 3ccd4186..00000000
--- a/old/zero.Web/Defaults/SettingsPermissions.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using zero.Core;
-using zero.Core.Identity;
-
-namespace zero.Web.Defaults
-{
- public class SettingsPermissions : PermissionCollection
- {
- public SettingsPermissions()
- {
- Alias = Constants.PermissionCollections.Settings;
- Label = "@permission.collections.settings";
- Description = "@permission.collections.settings_description";
-
- Items.Add(new Permission(Permissions.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text_default", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Applications, "@settings.system.applications.name", "@settings.system.applications.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Users, "@settings.system.users.name", "@settings.system.users.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Languages, "@settings.system.languages.name", "@settings.system.languages.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Countries, "@settings.system.countries.name", "@settings.system.countries.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Translations, "@settings.system.translations.name", "@settings.system.translations.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Mails, "@settings.system.mails.name", "@settings.system.mails.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.Plugins, "@settings.plugins.installed.name", "@settings.plugins.installed.text_default", PermissionValueType.CRUD));
- Items.Add(new Permission(Permissions.Settings.CreatePlugin, "@settings.plugins.create.name", "@settings.plugins.create.text", PermissionValueType.CRUD));
- }
- }
-}
diff --git a/old/zero.Web/Defaults/SystemSettings.cs b/old/zero.Web/Defaults/SystemSettings.cs
deleted file mode 100644
index c34fe026..00000000
--- a/old/zero.Web/Defaults/SystemSettings.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using zero.Core;
-using zero.Core.Entities;
-
-namespace zero.Web.Defaults
-{
- public class SystemSettings : SettingsGroup
- {
- public SystemSettings()
- {
- Name = "@settings.groups.system";
-
- //AddInternal(Constants.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text", "fth-check-circle");
- AddInternal(Constants.Settings.Applications, "@settings.system.applications.name", "@settings.system.applications.text", "fth-layers");
- AddInternal(Constants.Settings.Users, "@settings.system.users.name", "@settings.system.users.text", "fth-users");
- AddInternal(Constants.Settings.Plugins, "@settings.system.plugins.name", "@settings.system.plugins.text", "fth-package");
- //AddInternal(Constants.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", "fth-file-text");
- }
- }
-}
diff --git a/old/zero.Web/Defaults/ZeroBackofficePlugin.cs b/old/zero.Web/Defaults/ZeroBackofficePlugin.cs
index 35b98896..54fece7c 100644
--- a/old/zero.Web/Defaults/ZeroBackofficePlugin.cs
+++ b/old/zero.Web/Defaults/ZeroBackofficePlugin.cs
@@ -8,12 +8,7 @@ namespace zero.Web.Defaults
{
public override void Configure(IZeroOptions zero)
{
- zero.Settings.AddGroup();
- zero.Settings.AddGroup();
-
zero.Permissions.AddCollection();
- zero.Permissions.AddCollection();
- zero.Permissions.AddCollection();
zero.Pages.Add(Constants.Pages.FolderAlias, "@page.folder.name", "@page.folder.description", "fth-folder");
}
@@ -51,9 +46,6 @@ namespace zero.Web.Defaults
services.AddTransient();
services.AddTransient();
- services.AddScoped();
- services.AddScoped(typeof(ICollectionContext<>), typeof(CollectionContext<>));
-
services.AddScoped();
}
}
diff --git a/old/zero.Web/ViewHelpers/ZeroMediaHelper.cs b/old/zero.Web/ViewHelpers/ZeroMediaHelper.cs
deleted file mode 100644
index e51b201e..00000000
--- a/old/zero.Web/ViewHelpers/ZeroMediaHelper.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using zero.Core.Database;
-using zero.Core.Entities;
-using zero.Core.Extensions;
-
-namespace zero.Web.ViewHelpers
-{
- public class ZeroMediaHelper : IZeroMediaHelper
- {
- IZeroStore Store;
-
- public IZeroMediaHelper Core { get; private set; }
-
- protected bool Global { get; set; }
-
- ///
- /// Media cache for repetitive queries within an HTTP request
- ///
- ConcurrentDictionary Cache { get; set; } = new();
-
-
- public ZeroMediaHelper(IZeroStore store, bool global = false)
- {
- Store = store;
-
- if (!global)
- {
- Core = new ZeroMediaHelper(store, true);
- }
- }
-
-
- ///
- public async Task GetById(string id)
- {
- if (id.IsNullOrEmpty())
- {
- return null;
- }
-
- if (!Cache.TryGetValue(id, out Media media))
- {
- media = await Store.Session(Global).LoadAsync(id);
- Cache.TryAdd(id, media);
- }
-
- return media;
- }
-
-
- ///
- public async Task> GetByIds(string[] ids)
- {
- HashSet remoteIds = new HashSet();
- Dictionary items = new Dictionary();
-
- foreach (string id in ids)
- {
- if (Cache.TryGetValue(id, out Media media))
- {
- items.TryAdd(id, media);
- }
- else
- {
- remoteIds.Add(id);
- }
- }
-
- if (remoteIds.Count > 0)
- {
- Dictionary remoteItems = await Store.Session(Global).LoadAsync(remoteIds);
-
- foreach (var item in remoteItems)
- {
- items.TryAdd(item.Key, item.Value);
- Cache.TryAdd(item.Key, item.Value);
- }
- }
-
- return items;
- }
-
-
- ///
- public async Task GetUrl(string id, bool isAbsolute = false)
- {
- Media media = await GetById(id);
- return media?.Source.TrimStart("url://");
- }
-
-
- ///
- public async Task> GetUrls(string[] ids, bool isAbsolute = false)
- {
- Dictionary medias = await GetByIds(ids);
- return medias.ToDictionary(x => x.Key, x => x.Value?.Source.TrimStart("url://"));
- }
- }
-
-
- public interface IZeroMediaHelper
- {
- IZeroMediaHelper Core { get; }
-
- ///
- /// Get media by Id
- ///
- Task GetById(string id);
-
- ///
- /// Get media items by Ids
- ///
- Task> GetByIds(string[] ids);
-
- ///
- /// Get source for a media item
- ///
- Task GetUrl(string id, bool isAbsolute = false);
-
- ///
- /// Get source for media items
- ///
- Task> GetUrls(string[] ids, bool isAbsolute = false);
- }
-}
diff --git a/old/zero.Web/ViewHelpers/ZeroPageHelper.cs b/old/zero.Web/ViewHelpers/ZeroPageHelper.cs
deleted file mode 100644
index 5d366cbc..00000000
--- a/old/zero.Web/ViewHelpers/ZeroPageHelper.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-using Microsoft.AspNetCore.Http;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using zero.Core.Collections;
-using zero.Core.Entities;
-using zero.Core.Extensions;
-
-namespace zero.Web.ViewHelpers
-{
- public class ZeroPageHelper : IZeroPageHelper
- {
- HttpContext HttpContext;
-
- IMediaCollection Media;
-
- ///
- /// Media cache for repetitive queries within an HTTP request
- ///
- Dictionary Cache { get; set; } = new Dictionary();
-
-
- public ZeroPageHelper(IHttpContextAccessor httpContextAccessor, IMediaCollection media)
- {
- HttpContext = httpContextAccessor.HttpContext;
- Media = media;
- }
-
-
- ///
- public async Task GetById(string id)
- {
- if (id.IsNullOrEmpty())
- {
- return null;
- }
-
- if (!Cache.TryGetValue(id, out Media media))
- {
- media = await Media.Load(id);
- Cache.Add(id, media);
- }
-
- return media;
- }
-
-
- ///
- public async Task> GetByIds(string[] ids)
- {
- HashSet remoteIds = new HashSet();
- Dictionary items = new Dictionary();
-
- foreach (string id in ids)
- {
- if (Cache.TryGetValue(id, out Media media))
- {
- items.Add(id, media);
- }
- else
- {
- remoteIds.Add(id);
- }
- }
-
- if (remoteIds.Count > 0)
- {
- Dictionary remoteItems = await Media.Load(remoteIds);
-
- foreach (var item in remoteItems)
- {
- items.Add(item.Key, item.Value);
- Cache.Add(item.Key, item.Value);
- }
- }
-
- return items;
- }
-
-
- ///
- public async Task GetUrl(string id, bool isAbsolute = false)
- {
- Media media = await GetById(id);
- return media?.Source;
- }
-
-
- ///
- public async Task> GetUrls(string[] ids, bool isAbsolute = false)
- {
- Dictionary medias = await GetByIds(ids);
- return medias.ToDictionary(x => x.Key, x => x.Value?.Source);
- }
- }
-
-
- public interface IZeroPageHelper
- {
- ///
- /// Get media by Id
- ///
- Task GetById(string id);
-
- ///
- /// Get media items by Ids
- ///
- Task> GetByIds(string[] ids);
-
- ///
- /// Get source for a media item
- ///
- Task GetUrl(string id, bool isAbsolute = false);
-
- ///
- /// Get source for media items
- ///
- Task> GetUrls(string[] ids, bool isAbsolute = false);
- }
-}
diff --git a/old/zero.Web/Controllers/BackofficeCollectionController.cs b/zero.Backoffice/Endpoints/BackofficeCollectionController.cs
similarity index 100%
rename from old/zero.Web/Controllers/BackofficeCollectionController.cs
rename to zero.Backoffice/Endpoints/BackofficeCollectionController.cs
diff --git a/old/zero.Web/Controllers/BackofficeController.cs b/zero.Backoffice/Endpoints/BackofficeController.cs
similarity index 100%
rename from old/zero.Web/Controllers/BackofficeController.cs
rename to zero.Backoffice/Endpoints/BackofficeController.cs
diff --git a/old/zero.Web/Controllers/ZeroSetupController.cs b/zero.Backoffice/Endpoints/ZeroSetupController.cs
similarity index 100%
rename from old/zero.Web/Controllers/ZeroSetupController.cs
rename to zero.Backoffice/Endpoints/ZeroSetupController.cs
diff --git a/old/zero.Web/Controllers/ZeroVueController.cs b/zero.Backoffice/Endpoints/ZeroVueController.cs
similarity index 100%
rename from old/zero.Web/Controllers/ZeroVueController.cs
rename to zero.Backoffice/Endpoints/ZeroVueController.cs
diff --git a/zero.Backoffice/Registrations.cs b/zero.Backoffice/Registrations.cs
index e34a3f58..30496ba3 100644
--- a/zero.Backoffice/Registrations.cs
+++ b/zero.Backoffice/Registrations.cs
@@ -6,6 +6,6 @@ internal class Registrations
{
new CountriesModule(),
new SearchModule(),
- new BackofficeSectionModule()
+ new BackofficeUICompositionModule()
};
}
\ No newline at end of file
diff --git a/zero.Backoffice/Sections/Module.cs b/zero.Backoffice/UIComposition/Module.cs
similarity index 73%
rename from zero.Backoffice/Sections/Module.cs
rename to zero.Backoffice/UIComposition/Module.cs
index 9ff474b5..308e5338 100644
--- a/zero.Backoffice/Sections/Module.cs
+++ b/zero.Backoffice/UIComposition/Module.cs
@@ -1,8 +1,8 @@
using Microsoft.Extensions.DependencyInjection;
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
-internal class BackofficeSectionModule : ZeroModule
+internal class BackofficeUICompositionModule : ZeroModule
{
///
public override void Register(IZeroModuleConfiguration config)
@@ -12,6 +12,10 @@ internal class BackofficeSectionModule : ZeroModule
config.Services.AddSingleton();
config.Services.AddSingleton();
config.Services.AddSingleton();
+
+ config.Services.AddSingleton();
+ config.Services.AddSingleton();
+
config.Services.AddScoped();
}
diff --git a/zero.Backoffice/Sections/BackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/BackofficeSection.cs
similarity index 94%
rename from zero.Backoffice/Sections/BackofficeSection.cs
rename to zero.Backoffice/UIComposition/Sections/BackofficeSection.cs
index 00ea1047..311d2c13 100644
--- a/zero.Backoffice/Sections/BackofficeSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/BackofficeSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// A section is a main part of the backoffice application
diff --git a/zero.Backoffice/Sections/BackofficeSectionPermissions.cs b/zero.Backoffice/UIComposition/Sections/BackofficeSectionPermissions.cs
similarity index 94%
rename from zero.Backoffice/Sections/BackofficeSectionPermissions.cs
rename to zero.Backoffice/UIComposition/Sections/BackofficeSectionPermissions.cs
index 967980d1..27e6f0c1 100644
--- a/zero.Backoffice/Sections/BackofficeSectionPermissions.cs
+++ b/zero.Backoffice/UIComposition/Sections/BackofficeSectionPermissions.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Modules;
+namespace zero.Backoffice.UIComposition;
public class BackofficeSectionPermissions : PermissionProvider
{
diff --git a/zero.Backoffice/Sections/DashboardSection.cs b/zero.Backoffice/UIComposition/Sections/DashboardSection.cs
similarity index 92%
rename from zero.Backoffice/Sections/DashboardSection.cs
rename to zero.Backoffice/UIComposition/Sections/DashboardSection.cs
index d0229929..0768ad2a 100644
--- a/zero.Backoffice/Sections/DashboardSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/DashboardSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// The dashboard aggregates data from all sections
diff --git a/zero.Backoffice/Sections/IBackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs
similarity index 95%
rename from zero.Backoffice/Sections/IBackofficeSection.cs
rename to zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs
index 6128763d..6f0f8c28 100644
--- a/zero.Backoffice/Sections/IBackofficeSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// Internal section
diff --git a/zero.Backoffice/Sections/IChildBackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs
similarity index 90%
rename from zero.Backoffice/Sections/IChildBackofficeSection.cs
rename to zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs
index e683d708..f25c6e5b 100644
--- a/zero.Backoffice/Sections/IChildBackofficeSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// A child section is a sub-navigation item of a section
diff --git a/zero.Backoffice/Sections/MediaSection.cs b/zero.Backoffice/UIComposition/Sections/MediaSection.cs
similarity index 92%
rename from zero.Backoffice/Sections/MediaSection.cs
rename to zero.Backoffice/UIComposition/Sections/MediaSection.cs
index 32038580..7ec463ae 100644
--- a/zero.Backoffice/Sections/MediaSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/MediaSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// Media items (images, videos, documents) grouped in folders
diff --git a/zero.Backoffice/Sections/PagesSection.cs b/zero.Backoffice/UIComposition/Sections/PagesSection.cs
similarity index 91%
rename from zero.Backoffice/Sections/PagesSection.cs
rename to zero.Backoffice/UIComposition/Sections/PagesSection.cs
index 5d4f2a38..46ba5fa3 100644
--- a/zero.Backoffice/Sections/PagesSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/PagesSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// Manage the page tree in this section
diff --git a/zero.Backoffice/Sections/SettingsSection.cs b/zero.Backoffice/UIComposition/Sections/SettingsSection.cs
similarity index 91%
rename from zero.Backoffice/Sections/SettingsSection.cs
rename to zero.Backoffice/UIComposition/Sections/SettingsSection.cs
index 608ade93..c6c80462 100644
--- a/zero.Backoffice/Sections/SettingsSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/SettingsSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// Website and backoffice settings
diff --git a/zero.Backoffice/Sections/SpacesSection.cs b/zero.Backoffice/UIComposition/Sections/SpacesSection.cs
similarity index 91%
rename from zero.Backoffice/Sections/SpacesSection.cs
rename to zero.Backoffice/UIComposition/Sections/SpacesSection.cs
index 1bde0485..934ddae0 100644
--- a/zero.Backoffice/Sections/SpacesSection.cs
+++ b/zero.Backoffice/UIComposition/Sections/SpacesSection.cs
@@ -1,4 +1,4 @@
-namespace zero.Backoffice.Sections;
+namespace zero.Backoffice.UIComposition;
///
/// Global list entities
diff --git a/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs b/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs
new file mode 100644
index 00000000..cf2f9035
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs
@@ -0,0 +1,15 @@
+namespace zero.Backoffice.UIComposition;
+
+public class ApplicationSettings : SettingsGroup
+{
+ public ApplicationSettings() : base("@settings.groups.application")
+ {
+ //Add(Constants.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text", "fth-check-circle");
+ Add(Constants.Settings.Languages, "@settings.application.languages.name", "@settings.application.languages.text", "fth-globe");
+ Add(Constants.Settings.Countries, "@settings.application.countries.name", "@settings.application.countries.text", "fth-map-pin");
+ Add(Constants.Settings.Translations, "@settings.application.translations.name", "@settings.application.translations.text", "fth-type");
+ Add(Constants.Settings.Mails, "@settings.application.mails.name", "@settings.application.mails.text", "fth-mail");
+ Add(Constants.Settings.Integrations, "@settings.application.integrations.name", "@settings.application.integrations.text", "fth-sliders");
+ //Add(Constants.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", "fth-file-text");
+ }
+}
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs b/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs
new file mode 100644
index 00000000..309ce944
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs
@@ -0,0 +1,32 @@
+namespace zero.Backoffice.UIComposition;
+
+///
+/// Defines an area in the settings section
+///
+public interface ISettingsArea
+{
+ ///
+ /// Alias which used for the URL part
+ ///
+ string Alias { get; }
+
+ ///
+ /// Name of the settings area
+ ///
+ string Name { get; }
+
+ ///
+ /// Icon displayed next to the area name
+ ///
+ string Icon { get; }
+
+ ///
+ /// Further describe the area
+ ///
+ string Description { get; }
+
+ ///
+ /// Set a custom URL for this settings area link
+ ///
+ string CustomUrl { get; set; }
+}
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/ISettingsGroup.cs b/zero.Backoffice/UIComposition/Settings/ISettingsGroup.cs
new file mode 100644
index 00000000..548ca37e
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/ISettingsGroup.cs
@@ -0,0 +1,22 @@
+namespace zero.Backoffice.UIComposition;
+
+///
+/// Creates a new settings group in the backoffice application settings section
+///
+public interface ISettingsGroup
+{
+ ///
+ /// The name of the group (either a string or a translation key with @ prefix)
+ ///
+ string Name { get; set; }
+
+ ///
+ /// Areas/items within the group
+ ///
+ List Areas { get; set; }
+
+ ///
+ /// Add a new area to the group
+ ///
+ void Add(string alias, string name, string description = null, string icon = null, string customUrl = null);
+}
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/SettingsArea.cs b/zero.Backoffice/UIComposition/Settings/SettingsArea.cs
new file mode 100644
index 00000000..afa933f1
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/SettingsArea.cs
@@ -0,0 +1,30 @@
+namespace zero.Backoffice.UIComposition;
+
+///
+public class SettingsArea : ISettingsArea
+{
+ ///
+ public string Alias { get; }
+
+ ///
+ public string Name { get; }
+
+ ///
+ public string Icon { get; }
+
+ ///
+ public string Description { get; }
+
+ ///
+ public string CustomUrl { get; set; }
+
+
+ public SettingsArea(string alias, string name, string description = null, string icon = null, string customUrl = null)
+ {
+ Alias = alias;
+ Name = name;
+ Icon = icon;
+ Description = description;
+ CustomUrl = customUrl;
+ }
+}
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/SettingsGroup.cs b/zero.Backoffice/UIComposition/Settings/SettingsGroup.cs
new file mode 100644
index 00000000..6107b59c
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/SettingsGroup.cs
@@ -0,0 +1,23 @@
+namespace zero.Backoffice.UIComposition;
+
+///
+public class SettingsGroup : ISettingsGroup
+{
+ ///
+ public string Name { get; set; }
+
+ ///
+ public List Areas { get; set; } = new();
+
+
+ public SettingsGroup(string name)
+ {
+ Name = name;
+ }
+
+ ///
+ public void Add(string alias, string name, string description = null, string icon = null, string customUrl = null)
+ {
+ Areas.Add(new SettingsArea(alias, name, description, icon, customUrl));
+ }
+}
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs b/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs
new file mode 100644
index 00000000..4bce5e6f
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs
@@ -0,0 +1,42 @@
+using zero.Core;
+using zero.Core.Identity;
+
+//namespace zero.Backoffice.UIComposition;
+
+//public class BackofficeUISettingsPermissions : PermissionProvider
+//{
+// public BackofficeUISettingsPermissions() : base("@permission.collections.settings") { }
+
+// static string Prefix = "settings.";
+
+// public static readonly Permission Create = new(Prefix + "create", "@permission.states.create");
+// public static readonly Permission Read = new(Prefix + "read", "@permission.states.read");
+// public static readonly Permission Update = new(Prefix + "update", "@permission.states.update");
+// public static readonly Permission Delete = new(Prefix + "delete", "@permission.states.delete");
+
+
+// ///
+// public override IEnumerable GetPermissions() => new[] { Create, Read, Update, Delete };
+//}
+
+
+// public class SettingsPermissions : PermissionCollection
+// {
+// public SettingsPermissions()
+// {
+// Alias = Constants.PermissionCollections.Settings;
+// Label = "@permission.collections.settings";
+// Description = "@permission.collections.settings_description";
+
+// Items.Add(new Permission(Permissions.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text_default", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Applications, "@settings.system.applications.name", "@settings.system.applications.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Users, "@settings.system.users.name", "@settings.system.users.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Languages, "@settings.system.languages.name", "@settings.system.languages.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Countries, "@settings.system.countries.name", "@settings.system.countries.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Translations, "@settings.system.translations.name", "@settings.system.translations.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Mails, "@settings.system.mails.name", "@settings.system.mails.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.Plugins, "@settings.plugins.installed.name", "@settings.plugins.installed.text_default", PermissionValueType.CRUD));
+// Items.Add(new Permission(Permissions.Settings.CreatePlugin, "@settings.plugins.create.name", "@settings.plugins.create.text", PermissionValueType.CRUD));
+// }
+// }
\ No newline at end of file
diff --git a/zero.Backoffice/UIComposition/Settings/SystemSettings.cs b/zero.Backoffice/UIComposition/Settings/SystemSettings.cs
new file mode 100644
index 00000000..3e38d26a
--- /dev/null
+++ b/zero.Backoffice/UIComposition/Settings/SystemSettings.cs
@@ -0,0 +1,13 @@
+namespace zero.Backoffice.UIComposition;
+
+public class SystemSettings : SettingsGroup
+{
+ public SystemSettings() : base("@settings.groups.system")
+ {
+ //Add(Constants.Settings.Updates, "@settings.system.updates.name", "@settings.system.updates.text", "fth-check-circle");
+ Add(Constants.Settings.Applications, "@settings.system.applications.name", "@settings.system.applications.text", "fth-layers");
+ Add(Constants.Settings.Users, "@settings.system.users.name", "@settings.system.users.text", "fth-users");
+ Add(Constants.Settings.Plugins, "@settings.system.plugins.name", "@settings.system.plugins.text", "fth-package");
+ //Add(Constants.Settings.Logging, "@settings.system.logs.name", "@settings.system.logs.text", "fth-file-text");
+ }
+}
diff --git a/zero.Backoffice/Usings.cs b/zero.Backoffice/Usings.cs
index 308b7b5a..d215cdf0 100644
--- a/zero.Backoffice/Usings.cs
+++ b/zero.Backoffice/Usings.cs
@@ -26,4 +26,4 @@ global using zero.Backoffice;
global using zero.Backoffice.Models;
global using zero.Backoffice.Modules;
global using zero.Backoffice.Configuration;
-global using zero.Backoffice.Sections;
\ No newline at end of file
+global using zero.Backoffice.UIComposition;
\ No newline at end of file
diff --git a/zero.Core/zero.Core.csproj b/zero.Core/zero.Core.csproj
index dac059fc..e8cffa71 100644
--- a/zero.Core/zero.Core.csproj
+++ b/zero.Core/zero.Core.csproj
@@ -28,4 +28,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/zero.Web/ViewHelpers/ZeroMediaHelper.cs b/zero.Web/ViewHelpers/ZeroMediaHelper.cs
new file mode 100644
index 00000000..79ed5d74
--- /dev/null
+++ b/zero.Web/ViewHelpers/ZeroMediaHelper.cs
@@ -0,0 +1,126 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using zero.Extensions;
+using zero.Persistence;
+
+namespace zero.Web.ViewHelpers;
+
+public class ZeroMediaHelper : IZeroMediaHelper
+{
+ IZeroStore Store;
+
+ public IZeroMediaHelper Core { get; private set; }
+
+ protected bool Global { get; set; }
+
+ ///
+ /// Media cache for repetitive queries within an HTTP request
+ ///
+ ConcurrentDictionary Cache { get; set; } = new();
+
+
+ public ZeroMediaHelper(IZeroStore store, bool global = false)
+ {
+ Store = store;
+
+ if (!global)
+ {
+ Core = new ZeroMediaHelper(store, true);
+ }
+ }
+
+
+ ///
+ public async Task GetById(string id)
+ {
+ if (id.IsNullOrEmpty())
+ {
+ return null;
+ }
+
+ if (!Cache.TryGetValue(id, out Media media))
+ {
+ media = await Store.Session(Global).LoadAsync(id);
+ Cache.TryAdd(id, media);
+ }
+
+ return media;
+ }
+
+
+ ///
+ public async Task> GetByIds(string[] ids)
+ {
+ HashSet remoteIds = new HashSet();
+ Dictionary items = new Dictionary();
+
+ foreach (string id in ids)
+ {
+ if (Cache.TryGetValue(id, out Media media))
+ {
+ items.TryAdd(id, media);
+ }
+ else
+ {
+ remoteIds.Add(id);
+ }
+ }
+
+ if (remoteIds.Count > 0)
+ {
+ Dictionary remoteItems = await Store.Session(Global).LoadAsync(remoteIds);
+
+ foreach (var item in remoteItems)
+ {
+ items.TryAdd(item.Key, item.Value);
+ Cache.TryAdd(item.Key, item.Value);
+ }
+ }
+
+ return items;
+ }
+
+
+ ///
+ public async Task GetUrl(string id, bool isAbsolute = false)
+ {
+ Media media = await GetById(id);
+ return media?.Source.TrimStart("url://");
+ }
+
+
+ ///
+ public async Task> GetUrls(string[] ids, bool isAbsolute = false)
+ {
+ Dictionary medias = await GetByIds(ids);
+ return medias.ToDictionary(x => x.Key, x => x.Value?.Source.TrimStart("url://"));
+ }
+}
+
+
+public interface IZeroMediaHelper
+{
+ IZeroMediaHelper Core { get; }
+
+ ///
+ /// Get media by Id
+ ///
+ Task GetById(string id);
+
+ ///
+ /// Get media items by Ids
+ ///
+ Task> GetByIds(string[] ids);
+
+ ///
+ /// Get source for a media item
+ ///
+ Task GetUrl(string id, bool isAbsolute = false);
+
+ ///
+ /// Get source for media items
+ ///
+ Task> GetUrls(string[] ids, bool isAbsolute = false);
+}
\ No newline at end of file
diff --git a/zero.Web/ViewHelpers/ZeroPageHelper.cs b/zero.Web/ViewHelpers/ZeroPageHelper.cs
new file mode 100644
index 00000000..11041522
--- /dev/null
+++ b/zero.Web/ViewHelpers/ZeroPageHelper.cs
@@ -0,0 +1,117 @@
+using Microsoft.AspNetCore.Http;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using zero.Extensions;
+
+namespace zero.Web.ViewHelpers;
+
+public class ZeroPageHelper : IZeroPageHelper
+{
+ HttpContext HttpContext;
+
+ IMediaCollection Media;
+
+ ///
+ /// Media cache for repetitive queries within an HTTP request
+ ///
+ Dictionary Cache { get; set; } = new Dictionary();
+
+
+ public ZeroPageHelper(IHttpContextAccessor httpContextAccessor, IMediaCollection media)
+ {
+ HttpContext = httpContextAccessor.HttpContext;
+ Media = media;
+ }
+
+
+ ///
+ public async Task GetById(string id)
+ {
+ if (id.IsNullOrEmpty())
+ {
+ return null;
+ }
+
+ if (!Cache.TryGetValue(id, out Media media))
+ {
+ media = await Media.Load(id);
+ Cache.Add(id, media);
+ }
+
+ return media;
+ }
+
+
+ ///
+ public async Task> GetByIds(string[] ids)
+ {
+ HashSet remoteIds = new HashSet();
+ Dictionary items = new Dictionary();
+
+ foreach (string id in ids)
+ {
+ if (Cache.TryGetValue(id, out Media media))
+ {
+ items.Add(id, media);
+ }
+ else
+ {
+ remoteIds.Add(id);
+ }
+ }
+
+ if (remoteIds.Count > 0)
+ {
+ Dictionary remoteItems = await Media.Load(remoteIds);
+
+ foreach (var item in remoteItems)
+ {
+ items.Add(item.Key, item.Value);
+ Cache.Add(item.Key, item.Value);
+ }
+ }
+
+ return items;
+ }
+
+
+ ///
+ public async Task GetUrl(string id, bool isAbsolute = false)
+ {
+ Media media = await GetById(id);
+ return media?.Source;
+ }
+
+
+ ///
+ public async Task> GetUrls(string[] ids, bool isAbsolute = false)
+ {
+ Dictionary medias = await GetByIds(ids);
+ return medias.ToDictionary(x => x.Key, x => x.Value?.Source);
+ }
+}
+
+
+public interface IZeroPageHelper
+{
+ ///
+ /// Get media by Id
+ ///
+ Task GetById(string id);
+
+ ///
+ /// Get media items by Ids
+ ///
+ Task> GetByIds(string[] ids);
+
+ ///
+ /// Get source for a media item
+ ///
+ Task GetUrl(string id, bool isAbsolute = false);
+
+ ///
+ /// Get source for media items
+ ///
+ Task> GetUrls(string[] ids, bool isAbsolute = false);
+}
diff --git a/zero.Web/ZeroController.cs b/zero.Web/ZeroController.cs
new file mode 100644
index 00000000..47a00dbd
--- /dev/null
+++ b/zero.Web/ZeroController.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using zero.Applications;
+using zero.Context;
+using zero.Routing;
+
+namespace zero.Web;
+
+public abstract class ZeroController : ZeroController { }
+
+
+public abstract class ZeroController : Controller where T : class, IRouteModel
+{
+ public virtual Application Application => Context?.Application;
+
+ T _route;
+ public virtual T Route => _route ?? (_route = HttpContext.Features.Get() as T);
+
+ IZeroContext _context;
+ public IZeroContext Context => _context ?? (_context = HttpContext?.RequestServices?.GetService());
+}
\ No newline at end of file
diff --git a/zero.Web/ZeroFallbackController.cs b/zero.Web/ZeroFallbackController.cs
new file mode 100644
index 00000000..eefae5ce
--- /dev/null
+++ b/zero.Web/ZeroFallbackController.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using zero.Routing;
+
+namespace zero.Web;
+
+public class ZeroFallbackController : ZeroController
+{
+ public IActionResult Index()
+ {
+ return Json(new { Application, Route }, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None });
+ }
+}
\ No newline at end of file
diff --git a/zero.Web/zero.Web.csproj b/zero.Web/zero.Web.csproj
new file mode 100644
index 00000000..0f770c0a
--- /dev/null
+++ b/zero.Web/zero.Web.csproj
@@ -0,0 +1,20 @@
+
+
+
+ zero.Web
+ 0.1.0
+ preview
+ net6.0
+ true
+ zero.Web
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/zero.sln b/zero.sln
index e16cafe4..22f5fdf3 100644
--- a/zero.sln
+++ b/zero.sln
@@ -49,6 +49,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "old", "old", "{DECD7B35-5EC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Core", "zero.Core\zero.Core.csproj", "{CED2A7FA-8D35-4A2A-AF57-8B95307547CB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "zero.Web", "zero.Web\zero.Web.csproj", "{1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -87,6 +89,10 @@ Global
{CED2A7FA-8D35-4A2A-AF57-8B95307547CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CED2A7FA-8D35-4A2A-AF57-8B95307547CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CED2A7FA-8D35-4A2A-AF57-8B95307547CB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE