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