diff --git a/zero.Api/Abstractions/ZeroApiController.cs b/zero.Api/Abstractions/ZeroApiController.cs deleted file mode 100644 index dcc5a69e..00000000 --- a/zero.Api/Abstractions/ZeroApiController.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Abstractions; - -[ApiController] -[ZeroAuthorize] -[ApiMetadataFilter] -[ApiResponseFilter] -[TypeFilter(typeof(ApiExceptionFilter))] -//[MiddlewareFilter(typeof(ApiUnhandledExceptionMiddlewareFilter))] -//[ServiceFilter(typeof(ModelStateValidationFilterAttribute))] -//[ServiceFilter(typeof(BackofficeFilterAttribute))] -public abstract class ZeroApiController : ControllerBase -{ - IZeroMapper _mapper; - protected IZeroMapper Mapper => _mapper ?? (_mapper = HttpContext?.RequestServices?.GetService()); - - IZeroContext _context; - protected IZeroContext ZeroContext => _context ?? (_context = HttpContext?.RequestServices?.GetService()); - - - public ApiRequestHints Hints { get; protected set; } = new(); -} diff --git a/zero.Api/Abstractions/ZeroApiEntityStoreController.cs b/zero.Api/Abstractions/ZeroApiEntityStoreController.cs deleted file mode 100644 index c0d12b6c..00000000 --- a/zero.Api/Abstractions/ZeroApiEntityStoreController.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Abstractions; - -public abstract class ZeroApiEntityStoreController : ZeroApiController - where TModel : ZeroEntity, new() - where TStore : IEntityStore -{ - protected TStore Store { get; set; } - - protected ZeroApiEntityStoreOperations Ops { get; set; } - - public ZeroApiEntityStoreController(TStore store) - { - Store = store; - Ops = new ZeroApiEntityStoreOperations(this, store); - } - - - protected Task> EmptyModel(string flavorAlias = null, Action modify = null) => Ops.EmptyModel(flavorAlias, modify); - protected Task> EmptyModel(string flavorAlias = null, Action modify = null) => Ops.EmptyModel(flavorAlias, modify); - protected Task> GetModel(string id, string changeVector = null) => Ops.GetModel(id, changeVector); - protected Task> GetModel(string id, string changeVector = null) => Ops.GetModel(id, changeVector); - protected Task> GetModels(ListQuery query) => Ops.GetModels(query); - protected Task> GetModels(ListQuery query) => Ops.GetModels(query); - protected Task> GetModelsByIndex(ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() => Ops.GetModelsByIndex(query); - protected Task> GetModelsByIndex(ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() => Ops.GetModelsByIndex(query); - protected Task> CreateModel(T saveModel) where T : ISupportsFlavors => Ops.CreateModel(saveModel); - protected Task> CreateModel(TModel saveModel) => Ops.CreateModel(saveModel); - protected Task> UpdateModel(string id, T updateModel, string changeToken = null) where T : ZeroIdEntity => Ops.UpdateModel(id, updateModel, changeToken); - protected Task> UpdateModel(string id, TModel updateModel, string changeToken = null) => Ops.UpdateModel(id, updateModel, changeToken); - protected Task> SortModels(string[] ids) => Ops.SortModels(ids); - protected Task> DeleteModel(string id) => Ops.DeleteModel(id); -} diff --git a/zero.Api/Abstractions/ZeroApiEntityStoreOperations.cs b/zero.Api/Abstractions/ZeroApiEntityStoreOperations.cs deleted file mode 100644 index b70ff4ce..00000000 --- a/zero.Api/Abstractions/ZeroApiEntityStoreOperations.cs +++ /dev/null @@ -1,255 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Abstractions; - -public class ZeroApiEntityStoreOperations - where TModel : ZeroEntity, new() - where TStore : IEntityStore -{ - public TStore Store { get; set; } - - IZeroMapper _mapper; - protected IZeroMapper Mapper => _mapper ?? (_mapper = Controller.HttpContext?.RequestServices?.GetService()); - - protected ZeroApiController Controller { get; private set; } - - public ZeroApiEntityStoreOperations(ZeroApiController controller, TStore store) - { - Controller = controller; - Store = store; - Store.Config.IncludeInactive = true; - } - - - protected string GetActionMethod { get; set; } = "Get"; - - protected virtual string GetAction(TModel model) - { - return "/"; // TODO Url.Action does not work anymore, - // probably due to ZeroApiControllerModelConvention, which rewrites AttributeRouteModel - //return Url.Action(GetActionMethod, ControllerContext.ActionDescriptor.ControllerName, new { id = model.Id, changeVector = default(string) }); - } - - - public async Task> EmptyModel(string flavorAlias = null, Action modify = null) - { - TModel model = await Store.Empty(flavorAlias); - - if (model == null) - { - return Controller.NotFound(); - } - - T result = Mapper.Map(model); - modify?.Invoke(result); - return result; - } - - - public async Task> EmptyModel(string flavorAlias = null, Action modify = null) - { - TModel model = await Store.Empty(flavorAlias); - - if (model == null) - { - return Controller.NotFound(); - } - - modify?.Invoke(model); - return model; - } - - - public async Task> GetModel(string id, string changeVector = null) - { - TModel model = await Store.Load(id, changeVector); - - if (model == null) - { - return Controller.NotFound(); - } - - Controller.HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model); - - return Mapper.Map(model); - } - - - public async Task> GetModel(string id, string changeVector = null) - { - TModel model = await Store.Load(id, changeVector); - - if (model == null) - { - return Controller.NotFound(); - } - - Controller.HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model); - - return model; - } - - - public async Task> GetModels(ListQuery query) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query)); - - return Mapper.Map(result); - } - - - public async Task> GetModels(ListQuery query) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query)); - return result; - } - - - public async Task> GetModelsByIndex(ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query)); - - return Mapper.Map(result); - } - - - public async Task> GetModelsByIndex(ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Store.Load(query.Page, query.PageSize, q => q.Filter(query)); - return result; - } - - - public async Task> CreateModel(T saveModel) where T : ISupportsFlavors - { - TModel emptyModel = saveModel.Flavor.IsNullOrEmpty() ? await Store.Empty() : await Store.Empty(saveModel.Flavor); - TModel model = Mapper.Map(saveModel, emptyModel); - - Result result = await Store.Create(model); - - bool minimalResponse = false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal; - - if (result.IsSuccess) - { - Result mappedResult = Mapper.Map(result); - return Controller.Created(GetAction(model), minimalResponse ? null : mappedResult); - } - - return result.WithoutModel(); - } - - - public async Task> CreateModel(TModel saveModel) - { - Result result = await Store.Create(saveModel); - - bool minimalResponse = false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal; - - if (result.IsSuccess) - { - return Controller.Created(GetAction(saveModel), minimalResponse ? null : saveModel); - } - - return result.WithoutModel(); - } - - - public async Task> UpdateModel(string id, T updateModel, string changeToken = null) where T : ZeroIdEntity - { - if (id != updateModel.Id) - { - return Controller.BadRequest(Result.Fail(nameof(id), "@errors.onupdate.noidmatch")); - } - - TModel model = await Store.Load(id); - - if (model == null) - { - return Controller.BadRequest(Result.Fail(nameof(id), "@errors.idnotfound")); - } - - string storedChangeToken = Store.GetChangeToken(model); - - if (!changeToken.IsNullOrEmpty() && storedChangeToken != changeToken) - { - return Controller.BadRequest(Result.Fail("@errors.onupdate.changetokenmismatch")); - } - - Mapper.Map(updateModel, model); - - Result result = await Store.Update(model); - - if (false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - // TODO add Preference-Applied header, see https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#76-standard-response-headers - return Mapper.Map(result); - } - - - public async Task> UpdateModel(string id, TModel updateModel, string changeToken = null) - { - if (id != updateModel.Id) - { - return Controller.BadRequest(Result.Fail(nameof(id), "@errors.onupdate.noidmatch")); - } - - // TODO throws error on save: Attempted to associate a different object with id ... - // we need to map props to new object - //TModel model = await Store.Load(id); - - //if (model == null) - //{ - // return BadRequest(Result.Fail(nameof(id), "@errors.idnotfound")); - //} - - //string storedChangeToken = Store.GetChangeToken(model); - - //if (!changeToken.IsNullOrEmpty() && storedChangeToken != changeToken) - //{ - // return BadRequest(Result.Fail("@errors.onupdate.changetokenmismatch")); - //} - - Result result = await Store.Update(updateModel); - - if (false && Controller.Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - public async Task> SortModels(string[] ids) - { - return await Store.Sort(ids); - } - - - public async Task> DeleteModel(string id) - { - TModel model = await Store.Load(id); - - if (model == null) - { - return Controller.NotFound(); - } - - Result result = await Store.Delete(model); - - return result.WithoutModel(); - } -} diff --git a/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs b/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs deleted file mode 100644 index 747ede85..00000000 --- a/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Abstractions; - -public abstract class ZeroApiTreeEntityStoreController : ZeroApiEntityStoreController - where TModel : ZeroEntity, ISupportsTrees, new() - where TStore : ITreeEntityStore -{ - public ZeroApiTreeEntityStoreController(TStore store) : base(store) { } - - - protected async Task> GetChildModels(string parentId, ListQuery query) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query)); - - return Mapper.Map(result); - } - - - protected async Task> GetChildModels(string parentId, ListQuery query) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query)); - - return result; - } - - - protected async Task> GetChildModelsByIndex(string parentId, ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query)); - - return Mapper.Map(result); - } - - - protected async Task> GetChildModelsByIndex(string parentId, ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(NormalizeParentId(parentId), query.Page, query.PageSize, q => q.Filter(query)); - - return result; - } - - - protected async Task> MoveModel(string id, string newParentId) - { - return await PutOperation(async () => await Store.Move(id, NormalizeParentId(newParentId))); - } - - - protected async Task> MoveModel(string id, string newParentId) - { - return await PutOperation(async () => await Store.Move(id, NormalizeParentId(newParentId))); - } - - - protected async Task> CopyModel(string id, string newParentId) - { - return await PutOperation(async () => await Store.Copy(id, NormalizeParentId(newParentId))); - } - - - protected async Task> CopyModel(string id, string newParentId) - { - return await PutOperation(async () => await Store.Copy(id, NormalizeParentId(newParentId))); - } - - - protected async Task> CopyModelWithDescendants(string id, string newParentId) - { - return await PutOperation(async () => await Store.CopyWithDescendants(id, NormalizeParentId(newParentId))); - } - - - protected async Task> CopyModelWithDescendants(string id, string newParentId) - { - return await PutOperation(async () => await Store.CopyWithDescendants(id, NormalizeParentId(newParentId))); - } - - - protected async Task>> DeleteModelWithDescendants(string id) - { - TModel model = await Store.Load(id); - - if (model == null) - { - return NotFound(); - } - - Result result = await Store.DeleteWithDescendants(model); - - return result; - } - - - async Task> PutOperation(Func>> action) - { - Result result = await action(); - - if (false && Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return Mapper.Map(result); - } - - - async Task> PutOperation(Func>> action) - { - Result result = await action(); - - if (false && Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - protected string NormalizeParentId(string id) - { - return id == "root" ? null : id; - } -} diff --git a/zero.Api/ApiApplicationResolverHandler.cs b/zero.Api/ApiApplicationResolverHandler.cs deleted file mode 100644 index 232c3ee2..00000000 --- a/zero.Api/ApiApplicationResolverHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.AspNetCore.Http; - -namespace zero.Api; - -public class ApiApplicationResolverHandler : IBackofficeApplicationResolverHandler -{ - readonly IZeroOptions options; - - public ApiApplicationResolverHandler(IZeroOptions options) - { - this.options = options; - } - - - public bool TryResolve(HttpContext context, IEnumerable applications, ZeroUser user, out Application resolved) - { - string path = options.ZeroPath.EnsureStartsWith('/').TrimEnd('/'); - - if (!context.Request.Path.ToString().StartsWith(path)) - { - resolved = null; - return false; - } - - resolved = applications.FirstOrDefault(); - return resolved != null; - - //string appKey = context.Request.Path.Value.Substring(path.Length).TrimStart('/').Split('/').ElementAtOrDefault(1); - - //if (appKey.HasValue()) - //{ - // resolved = applications.FirstOrDefault(x => x.Alias == appKey); - // return resolved != null; - //} - - //resolved = null; - //return false; - } -} \ No newline at end of file diff --git a/zero.Api/ApiErrorCodes.cs b/zero.Api/ApiErrorCodes.cs deleted file mode 100644 index df4e42a6..00000000 --- a/zero.Api/ApiErrorCodes.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace zero.Api; - -public static class ApiErrorCodes -{ - public static class Categories - { - public const string Server = "server"; - public const string Validation = "validation"; - } - - public static class Server - { - public const string Exception = "server.error"; - } -} diff --git a/zero.Api/ApiParameterTransformer.cs b/zero.Api/ApiParameterTransformer.cs deleted file mode 100644 index 16fd80e9..00000000 --- a/zero.Api/ApiParameterTransformer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Routing; - -namespace zero.Api; - -public class ApiParameterTransformer : IOutboundParameterTransformer -{ - public string TransformOutbound(object value) - { - return value == null ? null : Safenames.Alias(value); - } -} \ No newline at end of file diff --git a/zero.Api/ApiRequestHints.cs b/zero.Api/ApiRequestHints.cs deleted file mode 100644 index e3a62cdb..00000000 --- a/zero.Api/ApiRequestHints.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace zero.Api; - -public struct ApiRequestHints -{ - public ApiRequestHints(ApiResponsePreference responsePreference) - { - ResponsePreference = responsePreference; - } - - public ApiResponsePreference ResponsePreference { get; set; } = ApiResponsePreference.Representation; -} - - -/// -/// Preference for POST + PUT requests -/// see https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#75-standard-request-headers -/// -public enum ApiResponsePreference -{ - /// - /// Returns a minimal repsonse for inserts and updates - /// - Minimal = 0, - /// - /// Returns status as well as model for inserts and updates - /// - Representation = 1 -} \ No newline at end of file diff --git a/zero.Api/ApplicationBuilderExtensions.cs b/zero.Api/ApplicationBuilderExtensions.cs deleted file mode 100644 index c82f1a8c..00000000 --- a/zero.Api/ApplicationBuilderExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api; - -public static class ApplicationBuilderExtensions -{ - public static IApplicationBuilder UseZeroApi(this IApplicationBuilder builder) - { - return builder; - } -} \ No newline at end of file diff --git a/zero.Api/Attributes/ZeroSystemApiAttribute.cs b/zero.Api/Attributes/ZeroSystemApiAttribute.cs deleted file mode 100644 index cac98491..00000000 --- a/zero.Api/Attributes/ZeroSystemApiAttribute.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace zero.Api.Attributes; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] -public class ZeroSystemApiAttribute : Attribute { } \ No newline at end of file diff --git a/zero.Api/Configuration/Constants.cs b/zero.Api/Configuration/Constants.cs deleted file mode 100644 index f12985b1..00000000 --- a/zero.Api/Configuration/Constants.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Configuration; - -public static class ApiConstants -{ - public const string ChangeToken = "zero.api.change_vector"; -} \ No newline at end of file diff --git a/zero.Api/ConfigureApiJsonOptions.cs b/zero.Api/ConfigureApiJsonOptions.cs deleted file mode 100644 index 52546180..00000000 --- a/zero.Api/ConfigureApiJsonOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -using System.Text.Json; - -namespace zero.Api; - - -public class ConfigureApiJsonOptions : IConfigureOptions -{ - public void Configure(JsonOptions options) - { - // TODO this matches all serialization, not limited to API - options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/ApplicationModule.cs b/zero.Api/Endpoints/Applications/ApplicationModule.cs deleted file mode 100644 index 30d508df..00000000 --- a/zero.Api/Endpoints/Applications/ApplicationModule.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Applications; - -public class ApplicationModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/ApplicationPermissions.cs b/zero.Api/Endpoints/Applications/ApplicationPermissions.cs deleted file mode 100644 index 4fcb9b71..00000000 --- a/zero.Api/Endpoints/Applications/ApplicationPermissions.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace zero.Api.Endpoints.Applications; - -public class ApplicationPermissions : PermissionProvider -{ - // TODO wrong - public const string Create = "zero.settings.country.create"; - public const string Read = "zero.settings.country.read"; - public const string Update = "zero.settings.country.update"; - public const string Delete = "zero.settings.country.delete"; - - - public override Task Configure(IPermissionContext context) - { - if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group)) - { - group.Permissions.Add(new Permission("zero.settings.country", "@settings.application.countries.name") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/ApplicationsController.cs b/zero.Api/Endpoints/Applications/ApplicationsController.cs deleted file mode 100644 index 77442225..00000000 --- a/zero.Api/Endpoints/Applications/ApplicationsController.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Applications; - -[ZeroSystemApi] -public class ApplicationsController : ZeroApiEntityStoreController -{ - public ApplicationsController(IApplicationStore store) : base(store) { } - - - [HttpGet("empty")] - [ZeroAuthorize(ApplicationPermissions.Create)] - public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); - - - [HttpGet("{id}")] - [ZeroAuthorize(ApplicationPermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("")] - [ZeroAuthorize(ApplicationPermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) => GetModels(query); - - - [HttpPost("")] - [ZeroAuthorize(ApplicationPermissions.Create)] - public virtual Task> Create(Application saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(ApplicationPermissions.Update)] - public virtual Task> Update(string id, Application updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(ApplicationPermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/Maps/ApplicationBasic.cs b/zero.Api/Endpoints/Applications/Maps/ApplicationBasic.cs deleted file mode 100644 index 7d106e82..00000000 --- a/zero.Api/Endpoints/Applications/Maps/ApplicationBasic.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Endpoints.Applications; - -public class ApplicationBasic : BasicModel -{ - public string FullName { get; set; } - - public string ImageId { get; set; } - - public Uri[] Domains { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/Maps/ApplicationEdit.cs b/zero.Api/Endpoints/Applications/Maps/ApplicationEdit.cs deleted file mode 100644 index 2d706db1..00000000 --- a/zero.Api/Endpoints/Applications/Maps/ApplicationEdit.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace zero.Api.Endpoints.Applications; - -public class ApplicationEdit : DisplayModel -{ - public string ImageId { get; set; } - - public string IconId { get; set; } - - public Uri[] Domains { get; set; } = Array.Empty(); - - public string FullName { get; set; } - - public string Email { get; set; } - - public List Features { get; set; } = new(); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/Maps/ApplicationMapperProfile.cs b/zero.Api/Endpoints/Applications/Maps/ApplicationMapperProfile.cs deleted file mode 100644 index 073c25e3..00000000 --- a/zero.Api/Endpoints/Applications/Maps/ApplicationMapperProfile.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace zero.Api.Endpoints.Applications; - -public class ApplicationMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(Application source, ApplicationBasic target, IZeroMapperContext ctx) - { - this.MapBasicData(source, target); - target.ImageId = source.ImageId; - target.Domains = source.Domains; - target.FullName = source.FullName; - } - - protected virtual void Map(Application source, ApplicationEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.ImageId = source.ImageId; - target.IconId = source.IconId; - target.Domains = source.Domains; - target.FullName = source.FullName; - target.Email = source.Email; - target.Features = source.Features; -} - - protected virtual void Map(ApplicationSave source, Application target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - target.ImageId = source.ImageId; - target.IconId = source.IconId; - target.Domains = source.Domains; - target.FullName = source.FullName; - target.Email = source.Email; - target.Features = source.Features; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Applications/Maps/ApplicationSave.cs b/zero.Api/Endpoints/Applications/Maps/ApplicationSave.cs deleted file mode 100644 index 00f9fb0f..00000000 --- a/zero.Api/Endpoints/Applications/Maps/ApplicationSave.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace zero.Api.Endpoints.Applications; - -public class ApplicationSave : SaveModel -{ - public string ImageId { get; set; } - - public string IconId { get; set; } - - public Uri[] Domains { get; set; } = Array.Empty(); - - public string FullName { get; set; } - - public string Email { get; set; } - - public List Features { get; set; } = new(); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/CountriesController.cs b/zero.Api/Endpoints/Countries/CountriesController.cs deleted file mode 100644 index c6cbdbb9..00000000 --- a/zero.Api/Endpoints/Countries/CountriesController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Countries; - -public class CountriesController : ZeroApiEntityStoreController -{ - public CountriesController(ICountryStore store) : base(store) { } - - - [HttpGet("empty")] - [ZeroAuthorize(CountryPermissions.Create)] - public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); - - - [HttpGet("{id}")] - [ZeroAuthorize(CountryPermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("")] - [ZeroAuthorize(CountryPermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) - { - query.OrderQuery = q => q.OrderByDescending(x => x.IsPreferred).ThenBy(x => x.Name); - return GetModelsByIndex(query); - } - - - [HttpPost("")] - [ZeroAuthorize(CountryPermissions.Create)] - public virtual Task> Create(Country saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(CountryPermissions.Update)] - public virtual Task> Update(string id, Country updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(CountryPermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/CountryModule.cs b/zero.Api/Endpoints/Countries/CountryModule.cs deleted file mode 100644 index 9296efdc..00000000 --- a/zero.Api/Endpoints/Countries/CountryModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Countries; - -public class CountryModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/CountryPermissions.cs b/zero.Api/Endpoints/Countries/CountryPermissions.cs deleted file mode 100644 index 5c36ce84..00000000 --- a/zero.Api/Endpoints/Countries/CountryPermissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace zero.Api.Endpoints.Countries; - -public class CountryPermissions : PermissionProvider -{ - public const string Create = "zero.settings.country.create"; - public const string Read = "zero.settings.country.read"; - public const string Update = "zero.settings.country.update"; - public const string Delete = "zero.settings.country.delete"; - - - public override Task Configure(IPermissionContext context) - { - if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group)) - { - group.Permissions.Add(new Permission("zero.settings.country", "@settings.application.countries.name") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/Indexes/zero_Api_Countries_Listing.cs b/zero.Api/Endpoints/Countries/Indexes/zero_Api_Countries_Listing.cs deleted file mode 100644 index 94dba27b..00000000 --- a/zero.Api/Endpoints/Countries/Indexes/zero_Api_Countries_Listing.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Countries; - -public class zero_Api_Countries_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - IsPreferred = item.IsPreferred - }); - - Index(x => x.Name, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/Maps/CountryBasic.cs b/zero.Api/Endpoints/Countries/Maps/CountryBasic.cs deleted file mode 100644 index 8954f575..00000000 --- a/zero.Api/Endpoints/Countries/Maps/CountryBasic.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Countries; - -public class CountryBasic : BasicModel -{ - public bool IsPreferred { get; set; } - - public string Code { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/Maps/CountryEdit.cs b/zero.Api/Endpoints/Countries/Maps/CountryEdit.cs deleted file mode 100644 index b5500ea6..00000000 --- a/zero.Api/Endpoints/Countries/Maps/CountryEdit.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Countries; - -public class CountryEdit : DisplayModel -{ - public bool IsPreferred { get; set; } - - public string Code { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/Maps/CountryMapperProfile.cs b/zero.Api/Endpoints/Countries/Maps/CountryMapperProfile.cs deleted file mode 100644 index 38defec4..00000000 --- a/zero.Api/Endpoints/Countries/Maps/CountryMapperProfile.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace zero.Api.Endpoints.Countries; - -public class CountryMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(Country source, CountryBasic target, IZeroMapperContext ctx) - { - this.MapBasicData(source, target); - target.Code = source.Code; - target.IsPreferred = source.IsPreferred; - } - - protected virtual void Map(Country source, CountryEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.Code = source.Code; - target.IsPreferred = source.IsPreferred; - } - - protected virtual void Map(CountrySave source, Country target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - target.Code = source.Code; - target.IsPreferred = source.IsPreferred; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Countries/Maps/CountrySave.cs b/zero.Api/Endpoints/Countries/Maps/CountrySave.cs deleted file mode 100644 index 101ae933..00000000 --- a/zero.Api/Endpoints/Countries/Maps/CountrySave.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Countries; - -public class CountrySave : SaveModel -{ - public bool IsPreferred { get; set; } - - public string Code { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Error/ErrorController.cs b/zero.Api/Endpoints/Error/ErrorController.cs deleted file mode 100644 index f13d54a5..00000000 --- a/zero.Api/Endpoints/Error/ErrorController.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Microsoft.AspNetCore.Diagnostics; -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Error; - -public class ErrorController : ZeroApiController -{ - [HttpGet("")] - public virtual ActionResult Index() - { - return new ErrorApiResponse() - { - Success = false, - Status = HttpContext.Response.StatusCode - }; - - //IExceptionHandlerFeature exception = HttpContext.Features.Get(); - - //return new ErrorApiResponse() - //{ - // Success = false, - // Status = HttpContext.Response.StatusCode, - // Error = new() - // { - // ApiPath = exception.Path, - // Message = exception.Error.Message - // } - //}; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Error/ServiceCollectionExtensions.cs b/zero.Api/Endpoints/Error/ServiceCollectionExtensions.cs deleted file mode 100644 index 63baea1e..00000000 --- a/zero.Api/Endpoints/Error/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Error; - -public static class ServiceCollectionExtensions -{ - public static IServiceCollection AddZeroBackofficeErrorHandler(this IServiceCollection services) - { - return services; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Integrations/IntegrationModule.cs b/zero.Api/Endpoints/Integrations/IntegrationModule.cs deleted file mode 100644 index d23a7ff6..00000000 --- a/zero.Api/Endpoints/Integrations/IntegrationModule.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Integrations; - -public class IntegrationModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - - //services.Configure(opts => - //{ - // opts.Indexes.Add(); - //}); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Integrations/IntegrationsController.cs b/zero.Api/Endpoints/Integrations/IntegrationsController.cs deleted file mode 100644 index 54bc668c..00000000 --- a/zero.Api/Endpoints/Integrations/IntegrationsController.cs +++ /dev/null @@ -1,172 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System.Collections; -using zero.Mapper; - -namespace zero.Api.Endpoints.Integrations; - -public class IntegrationsController : ZeroApiController -{ - readonly IIntegrationTypeService IntegrationTypes; - readonly IIntegrationStore Store; - - public IntegrationsController(IIntegrationTypeService integrationTypes, IIntegrationStore store) - { - IntegrationTypes = integrationTypes; - Store = store; - } - - - - [HttpGet("types")] - //[ZeroAuthorize(SpacePermissions.Read)] - public virtual async Task> GetTypes() - { - IEnumerable result = Mapper.Map(IntegrationTypes.GetAll()).ToList(); - - foreach (IntegrationTypeDisplay display in result) - { - Integration model = await Store.Load(display.Alias); - - if (model != null) - { - display.IsConfigured = true; - display.IsActivated = model.IsActive; - display.ModelId = model.Id; - } - } - - return Ok(result); - } - - - [HttpGet("types/{alias}")] - //[ZeroAuthorize(SpacePermissions.Read)] - public virtual async Task> GetType(string alias) - { - IntegrationTypeDisplay result = Mapper.Map(IntegrationTypes.GetByAlias(alias)); - - if (result == null) - { - return NotFound(); - } - - Integration model = await Store.Load(result.Alias); - - if (model != null) - { - result.IsConfigured = true; - result.IsActivated = model.IsActive; - result.ModelId = model.Id; - } - - return Ok(result); - } - - - [HttpGet("empty/{alias}")] - //[ZeroAuthorize(CountryPermissions.Create)] - public virtual async Task> Empty(string alias) - { - Integration model = await Store.Empty(alias); - - if (model == null) - { - return NotFound(); - } - - return model; - } - - - [HttpGet("{alias}")] - //[ZeroAuthorize(CountryPermissions.Read)] - public virtual async Task> Get(string alias) - { - Integration model = await Store.Load(alias); - - if (model == null) - { - return NotFound(); - } - - HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model); - - return model; - } - - - [HttpPost("")] - //[ZeroAuthorize(CountryPermissions.Create)] - public virtual async Task> Create(Integration saveModel) - { - Result result = await Store.Create(saveModel); - - bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal; - - if (result.IsSuccess) - { - return Created("/", minimalResponse ? null : saveModel); - } - - return result.WithoutModel(); - } - - - [HttpPut("{alias}")] - //[ZeroAuthorize(CountryPermissions.Update)] - public virtual async Task> Update(string alias, Integration updateModel, [FromQuery] string changeToken = null) - { - if (alias != updateModel.Flavor) - { - return BadRequest(Result.Fail(nameof(alias), "@integration.errors.noaliasmatch")); - } - - Result result = await Store.Update(updateModel); - - if (Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - [HttpPut("{alias}/activate")] - //[ZeroAuthorize(CountryPermissions.Update)] - public virtual async Task> Activate(string alias) - { - Result result = await Store.Activate(alias); - - if (Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - [HttpPut("{alias}/deactivate")] - //[ZeroAuthorize(CountryPermissions.Update)] - public virtual async Task> Deactivate(string alias) - { - Result result = await Store.Deactivate(alias); - - if (Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - [HttpDelete("{alias}")] - //[ZeroAuthorize(CountryPermissions.Delete)] - public virtual async Task> Delete(string alias) - { - Result result = await Store.Delete(alias); - return result.WithoutModel(); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Integrations/Maps/IntegrationMapperProfile.cs b/zero.Api/Endpoints/Integrations/Maps/IntegrationMapperProfile.cs deleted file mode 100644 index fdfb0dcf..00000000 --- a/zero.Api/Endpoints/Integrations/Maps/IntegrationMapperProfile.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace zero.Api.Endpoints.Integrations; - -public class IntegrationMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(IntegrationType source, IntegrationTypeDisplay target, IZeroMapperContext ctx) - { - target.Description = source.Description; - target.Name = source.Name; - target.Alias = source.Alias; - target.EditorAlias = source.EditorAlias; - target.ImagePath = source.ImagePath; - target.Tags = source.Tags; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Integrations/Maps/IntegrationTypeDisplay.cs b/zero.Api/Endpoints/Integrations/Maps/IntegrationTypeDisplay.cs deleted file mode 100644 index ff069ea1..00000000 --- a/zero.Api/Endpoints/Integrations/Maps/IntegrationTypeDisplay.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace zero.Api.Endpoints.Integrations; - -public class IntegrationTypeDisplay -{ - public string EditorAlias { get; set; } - - public string Alias { get; set; } - - public string Name { get; set; } - - public List Tags { get; set; } = new(); - - public string Description { get; set; } - - public string ImagePath { get; set; } - - public bool IsActivated { get; set; } - - public bool IsConfigured { get; set; } - - public string ModelId { get; set; } -} diff --git a/zero.Api/Endpoints/Languages/Indexes/zero_Api_Languages_Listing.cs b/zero.Api/Endpoints/Languages/Indexes/zero_Api_Languages_Listing.cs deleted file mode 100644 index 093127c1..00000000 --- a/zero.Api/Endpoints/Languages/Indexes/zero_Api_Languages_Listing.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Languages; - -public class zero_Api_Languages_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - CreatedDate = item.CreatedDate, - IsDefault = item.IsDefault - }); - - Index(x => x.Name, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/LanguageModule.cs b/zero.Api/Endpoints/Languages/LanguageModule.cs deleted file mode 100644 index a951d5e2..00000000 --- a/zero.Api/Endpoints/Languages/LanguageModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Languages; - -public class LanguageModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/LanguagePermissions.cs b/zero.Api/Endpoints/Languages/LanguagePermissions.cs deleted file mode 100644 index 75237912..00000000 --- a/zero.Api/Endpoints/Languages/LanguagePermissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace zero.Api.Endpoints.Languages; - -public class LanguagePermissions : PermissionProvider -{ - public const string Create = "zero.settings.language.create"; - public const string Read = "zero.settings.language.read"; - public const string Update = "zero.settings.language.update"; - public const string Delete = "zero.settings.language.delete"; - - - public override Task Configure(IPermissionContext context) - { - if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group)) - { - group.Permissions.Add(new Permission("zero.settings.language", "@settings.application.languages.name") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/LanguagesController.cs b/zero.Api/Endpoints/Languages/LanguagesController.cs deleted file mode 100644 index 262e3014..00000000 --- a/zero.Api/Endpoints/Languages/LanguagesController.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Languages; - -public class LanguagesController : ZeroApiEntityStoreController -{ - public LanguagesController(ILanguageStore store) : base(store) - { - - } - - - [HttpGet("empty")] - [ZeroAuthorize(LanguagePermissions.Create)] - public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); - - - [HttpGet("{id}")] - [ZeroAuthorize(LanguagePermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("")] - [ZeroAuthorize(LanguagePermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) => GetModelsByIndex(query); - - - [HttpPost("")] - [ZeroAuthorize(LanguagePermissions.Create)] - public virtual Task> Create(Language saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(LanguagePermissions.Update)] - public virtual Task> Update(string id, Language updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(LanguagePermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/Maps/LanguageBasic.cs b/zero.Api/Endpoints/Languages/Maps/LanguageBasic.cs deleted file mode 100644 index a25cc28c..00000000 --- a/zero.Api/Endpoints/Languages/Maps/LanguageBasic.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Endpoints.Languages; - -public class LanguageBasic : BasicModel -{ - public string Code { get; set; } - - public bool IsDefault { get; set; } - - public string InheritedLanguageId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/Maps/LanguageEdit.cs b/zero.Api/Endpoints/Languages/Maps/LanguageEdit.cs deleted file mode 100644 index 4a21661c..00000000 --- a/zero.Api/Endpoints/Languages/Maps/LanguageEdit.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Endpoints.Languages; - -public class LanguageEdit : DisplayModel -{ - public string Code { get; set; } - - public bool IsDefault { get; set; } - - public string InheritedLanguageId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/Maps/LanguageMapperProfile.cs b/zero.Api/Endpoints/Languages/Maps/LanguageMapperProfile.cs deleted file mode 100644 index 4a999439..00000000 --- a/zero.Api/Endpoints/Languages/Maps/LanguageMapperProfile.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace zero.Api.Endpoints.Languages; - -public class LanguageMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(Language source, LanguageBasic target, IZeroMapperContext ctx) - { - this.MapBasicData(source, target); - target.Code = source.Code; - target.IsDefault = source.IsDefault; - target.InheritedLanguageId = source.InheritedLanguageId; - } - - protected virtual void Map(Language source, LanguageEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.Code = source.Code; - target.IsDefault = source.IsDefault; - target.InheritedLanguageId = source.InheritedLanguageId; - } - - protected virtual void Map(LanguageSave source, Language target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - target.Code = source.Code; - target.IsDefault = source.IsDefault; - target.InheritedLanguageId = source.InheritedLanguageId; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Languages/Maps/LanguageSave.cs b/zero.Api/Endpoints/Languages/Maps/LanguageSave.cs deleted file mode 100644 index e0417756..00000000 --- a/zero.Api/Endpoints/Languages/Maps/LanguageSave.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Endpoints.Languages; - -public class LanguageSave : SaveModel -{ - public string Code { get; set; } - - public bool IsDefault { get; set; } - - public string InheritedLanguageId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/Indexes/zero_Api_MailTemplates_Listing.cs b/zero.Api/Endpoints/Mails/Indexes/zero_Api_MailTemplates_Listing.cs deleted file mode 100644 index a2a8d8e0..00000000 --- a/zero.Api/Endpoints/Mails/Indexes/zero_Api_MailTemplates_Listing.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Mails; - -public class zero_Api_MailTemplates_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - item.Name, - item.Key, - item.Subject, - item.CreatedDate - }); - - Index(x => x.Name, FieldIndexing.Search); - Index(x => x.Key, FieldIndexing.Search); - Index(x => x.Subject, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/MailModule.cs b/zero.Api/Endpoints/Mails/MailModule.cs deleted file mode 100644 index 15d2fdb1..00000000 --- a/zero.Api/Endpoints/Mails/MailModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Mails; - -public class MailModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/MailPermissions.cs b/zero.Api/Endpoints/Mails/MailPermissions.cs deleted file mode 100644 index 86946f1b..00000000 --- a/zero.Api/Endpoints/Mails/MailPermissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace zero.Api.Endpoints.Mails; - -public class MailPermissions : PermissionProvider -{ - public const string Create = "zero.settings.mail.create"; - public const string Read = "zero.settings.mail.read"; - public const string Update = "zero.settings.mail.update"; - public const string Delete = "zero.settings.mail.delete"; - - - public override Task Configure(IPermissionContext context) - { - if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group)) - { - group.Permissions.Add(new Permission("zero.settings.mail", "@settings.application.mails.name") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/MailTemplatesController.cs b/zero.Api/Endpoints/Mails/MailTemplatesController.cs deleted file mode 100644 index 01b5c47c..00000000 --- a/zero.Api/Endpoints/Mails/MailTemplatesController.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Mails; - -public class MailTemplatesController : ZeroApiEntityStoreController -{ - public MailTemplatesController(IMailTemplatesStore store) : base(store) - { - - } - - - [HttpGet("empty")] - [ZeroAuthorize(MailPermissions.Create)] - public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); - - - [HttpGet("{id}")] - [ZeroAuthorize(MailPermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("")] - [ZeroAuthorize(MailPermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) - { - query.SearchFor(entity => entity.Name, entity => entity.Key, entity => entity.Subject); - return GetModelsByIndex(query); - } - - - [HttpPost("")] - [ZeroAuthorize(MailPermissions.Create)] - public virtual Task> Create(MailSave saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(MailPermissions.Update)] - public virtual Task> Update(string id, MailSave updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(MailPermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/Maps/MailBasic.cs b/zero.Api/Endpoints/Mails/Maps/MailBasic.cs deleted file mode 100644 index 875332ac..00000000 --- a/zero.Api/Endpoints/Mails/Maps/MailBasic.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Endpoints.Mails; - -public class MailBasic : BasicModel -{ - public string Subject { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/Maps/MailEdit.cs b/zero.Api/Endpoints/Mails/Maps/MailEdit.cs deleted file mode 100644 index 9161b9b1..00000000 --- a/zero.Api/Endpoints/Mails/Maps/MailEdit.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace zero.Api.Endpoints.Mails; - -public class MailEdit : DisplayModel -{ - public string SenderEmail { get; set; } - - public string SenderName { get; set; } - - public string RecipientEmail { get; set; } - - public string Cc { get; set; } - - public string Bcc { get; set; } - - public string Subject { get; set; } - - public string Body { get; set; } - - public string Preheader { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/Maps/MailMapperProfile.cs b/zero.Api/Endpoints/Mails/Maps/MailMapperProfile.cs deleted file mode 100644 index 6e357751..00000000 --- a/zero.Api/Endpoints/Mails/Maps/MailMapperProfile.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace zero.Api.Endpoints.Mails; - -public class MailMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(MailTemplate source, MailBasic target, IZeroMapperContext ctx) - { - this.MapBasicData(source, target); - target.Subject = source.Subject; - } - - protected virtual void Map(MailTemplate source, MailEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.Subject = source.Subject; - target.SenderEmail = source.SenderEmail; - target.SenderName = source.SenderName; - target.RecipientEmail = source.RecipientEmail; - target.Cc = source.Cc; - target.Bcc = source.Bcc; - target.Body = source.Body; - target.Preheader = source.Preheader; -} - - protected virtual void Map(MailSave source, MailTemplate target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - target.Subject = source.Subject; - target.SenderEmail = source.SenderEmail; - target.SenderName = source.SenderName; - target.RecipientEmail = source.RecipientEmail; - target.Cc = source.Cc; - target.Bcc = source.Bcc; - target.Body = source.Body; - target.Preheader = source.Preheader; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Mails/Maps/MailSave.cs b/zero.Api/Endpoints/Mails/Maps/MailSave.cs deleted file mode 100644 index c6df05ab..00000000 --- a/zero.Api/Endpoints/Mails/Maps/MailSave.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace zero.Api.Endpoints.Mails; - -public class MailSave : SaveModel -{ - public string SenderEmail { get; set; } - - public string SenderName { get; set; } - - public string RecipientEmail { get; set; } - - public string Cc { get; set; } - - public string Bcc { get; set; } - - public string Subject { get; set; } - - public string Body { get; set; } - - public string Preheader { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_ChildCounts.cs b/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_ChildCounts.cs deleted file mode 100644 index 08ac9d2d..00000000 --- a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_ChildCounts.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Media; - -public class zero_Api_Media_ChildCounts : ZeroIndex -{ - public class Result : ZeroIdEntity - { - public int ChildCount { get; set; } - - public int ChildFolderCount { get; set; } - } - - protected override void Create() - { - Map = items => items.Where(x => x.ParentId != null).Select(item => new Result - { - Id = item.ParentId, - ChildCount = 1, - ChildFolderCount = item.IsFolder ? 1 : 0 - }); - - Reduce = results => results.GroupBy(x => new { x.Id }).Select(group => new Result() - { - Id = group.Key.Id, - ChildCount = group.Sum(x => x.ChildCount), - ChildFolderCount = group.Sum(x => x.ChildFolderCount) - }); - - StoreAllFields(FieldStorage.Yes); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Hierarchy.cs b/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Hierarchy.cs deleted file mode 100644 index fffb40ff..00000000 --- a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Hierarchy.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Media; - - -public class MediaTreeHierarchyIndexResult : ZeroTreeHierarchyIndexResult -{ - public bool IsFolder { get; set; } -} - -public class zero_Api_Media_Hierarchy : ZeroTreeHierarchyIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new MediaTreeHierarchyIndexResult - { - Id = item.Id, - IsFolder = item.IsFolder, - Path = Recurse(item, x => LoadDocument(x.ParentId)) - .Where(x => x != null && x.Id != null && x.Id != item.Id) - .Reverse() - .Select(current => current.Id) - .ToList() - }); - - StoreAllFields(FieldStorage.Yes); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs b/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs deleted file mode 100644 index a0ce4f20..00000000 --- a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Media; - -public class zero_Api_Media_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - ParentId = item.ParentId, - CreatedDate = item.CreatedDate, - IsFolder = item.IsFolder - }); - - Index(x => x.Name, FieldIndexing.Search); - Index(x => x.ParentId, FieldIndexing.Exact); - Index(x => x.CreatedDate, FieldIndexing.Exact); - Index(x => x.IsFolder, FieldIndexing.Exact); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaBasic.cs b/zero.Api/Endpoints/Media/Maps/MediaBasic.cs deleted file mode 100644 index 948804cd..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaBasic.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaBasic : ZeroIdEntity -{ - public string ParentId { get; set; } - - public string Name { get; set; } - - public bool IsFolder { get; set; } - - public string Source { get; set; } - - public string Preview { get; set; } - - public int Children { get; set; } - - public long Size { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaBulkDeleteOperation.cs b/zero.Api/Endpoints/Media/Maps/MediaBulkDeleteOperation.cs deleted file mode 100644 index 5436cd0d..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaBulkDeleteOperation.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaBulkDeleteOperation -{ - public string[] Ids { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaBulkMoveOperation.cs b/zero.Api/Endpoints/Media/Maps/MediaBulkMoveOperation.cs deleted file mode 100644 index 27203fd2..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaBulkMoveOperation.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaBulkMoveOperation -{ - public string ParentId { get; set; } - - public string[] Ids { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaDescendantStatistics.cs b/zero.Api/Endpoints/Media/Maps/MediaDescendantStatistics.cs deleted file mode 100644 index 88a13c8d..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaDescendantStatistics.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaDescendantStatistics -{ - public int Folders { get; set; } - - public int Files { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaEdit.cs b/zero.Api/Endpoints/Media/Maps/MediaEdit.cs deleted file mode 100644 index dfec7c05..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaEdit.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaEdit : DisplayModel -{ - public bool IsFolder { get; set; } - - public string ParentId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaFileEdit.cs b/zero.Api/Endpoints/Media/Maps/MediaFileEdit.cs deleted file mode 100644 index 7fd795d3..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaFileEdit.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaFileEdit : MediaEdit -{ - public string AlternativeText { get; set; } - - public string Caption { get; set; } - - public string Path { get; set; } - - public Dictionary Thumbnails { get; set; } = new(); - - public long Size { get; set; } - - public MediaImageMetadata ImageMeta { get; set; } - - public MediaFocalPoint FocalPoint { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaFolderEdit.cs b/zero.Api/Endpoints/Media/Maps/MediaFolderEdit.cs deleted file mode 100644 index d48284f3..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaFolderEdit.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaFolderEdit : MediaEdit -{ - -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs b/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs deleted file mode 100644 index eb459283..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs +++ /dev/null @@ -1,77 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaMapperProfile : ZeroMapperProfile -{ - protected IMediaFileSystem FileSystem { get; private set; } - - - public MediaMapperProfile(IMediaFileSystem fileSystem) - { - FileSystem = fileSystem; - } - - - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(zero.Media.Media source, MediaBasic target, IZeroMapperContext ctx) - { - target.Id = source.Id; - target.Name = source.Name; - target.ParentId = source.ParentId; - target.IsFolder = source.IsFolder; - target.Children = 0; - target.Size = source.Size; - - if (source.Path.HasValue()) - { - target.Source = FileSystem.MapToPublicPath(source.Path); - } - - if (source.ImageMeta != null && source.ImageMeta.Thumbnails.Any()) - { - string path = source.ImageMeta.Thumbnails.GetValueOrDefault("preview"); - target.Preview = path.IsNullOrEmpty() ? null : FileSystem.MapToPublicPath(path); - } - } - - protected virtual void Map(zero.Media.Media source, MediaEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.IsFolder = source.IsFolder; - target.ParentId = source.ParentId; - } - - - protected virtual void Map(zero.Media.Media source, MediaFolderEdit target, IZeroMapperContext ctx) - { - Map(source, (MediaEdit)target, ctx); - } - - - protected virtual void Map(zero.Media.Media source, MediaFileEdit target, IZeroMapperContext ctx) - { - Map(source, (MediaEdit)target, ctx); - target.AlternativeText = source.ImageMeta?.AlternativeText; - target.Caption = source.Caption; - target.Path = source.Path; - target.Thumbnails = source.ImageMeta?.Thumbnails; - target.Size = source.Size; - target.ImageMeta = source.ImageMeta; - target.FocalPoint = source.ImageMeta?.FocalPoint; -} - - - protected virtual void Map(MediaSave source, zero.Media.Media target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaSave.cs b/zero.Api/Endpoints/Media/Maps/MediaSave.cs deleted file mode 100644 index d1cd9276..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaSave.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaSave : SaveModel -{ - public bool IsFolder { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaSourceResult.cs b/zero.Api/Endpoints/Media/Maps/MediaSourceResult.cs deleted file mode 100644 index 755ff85e..00000000 --- a/zero.Api/Endpoints/Media/Maps/MediaSourceResult.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaSourceResult -{ - public string Path { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/MediaController.cs b/zero.Api/Endpoints/Media/MediaController.cs deleted file mode 100644 index 2a4378f2..00000000 --- a/zero.Api/Endpoints/Media/MediaController.cs +++ /dev/null @@ -1,380 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Net.Http.Headers; -using Raven.Client.Documents; -using Raven.Client.Documents.Linq; -using System.IO; - -namespace zero.Api.Endpoints.Media; - -/// -/// GET /empty -/// GET / -/// GET /{id} -/// GET /{id}/hierarchy -/// GET /{id}/{size}.tmp -/// POS / -/// PUT /{id} -/// PUT /{id/move/{folderId} -/// DEL /{id} -/// -/// GET /folders/empty -/// GET /folders/{id} -/// GET /folders/{id}/children -/// GET /folders/{id}/hierarchy -/// POS /folders/ -/// PUT /folders/{id} -/// PUT /folders/{id/move/{folderId} -/// DEL /folders/{id} -/// -/// GET /bulk/descendants -/// PUT /bulk/move -/// DEL /bulk/delete -/// -public class MediaController : ZeroApiTreeEntityStoreController -{ - IMediaManagement Media; - - public MediaController(IMediaStore store, IMediaManagement media) : base(store) - { - Media = media; - } - - #region bulk operations - - [HttpPut("bulk/move")] - [ZeroAuthorize(MediaPermissions.Update)] - public virtual async Task>> BulkMove(MediaBulkMoveOperation operation) - { - List> results = new(); - - foreach (string id in operation.Ids) - { - Result result = await Store.Move(id, NormalizeParentId(operation.ParentId)); - results.Add(result.ConvertTo(id)); - } - - return results; - } - - - [HttpDelete("bulk/delete")] - [ZeroAuthorize(MediaPermissions.Update)] - public virtual async Task>> BulkDelete(MediaBulkDeleteOperation operation) - { - List> results = new(); - - foreach (string id in operation.Ids) - { - Result result = await Store.DeleteWithDescendants(id); - results.Add(result.ConvertTo(id)); - } - - return results; - } - - - [HttpGet("bulk/descendants")] - [ZeroAuthorize(MediaPermissions.Update)] - public virtual async Task> GetDescendantStatistics([FromQuery] string[] ids) - { - List> results = new(); - - Dictionary parents = await Store.Load(ids); - - int folderCount = parents.Count(x => x.Value != null && x.Value.IsFolder); - int fileCount = parents.Count(x => x.Value != null && !x.Value.IsFolder); - - folderCount += await Store.Session.Query().CountAsync(x => x.Path.ContainsAny(ids) && x.IsFolder); - fileCount += await Store.Session.Query().CountAsync(x => x.Path.ContainsAny(ids) && !x.IsFolder); - - return new MediaDescendantStatistics() - { - Files = fileCount, - Folders = folderCount - }; - } - - #endregion - - - #region folder operations - - [HttpGet("folders/empty")] - [ZeroAuthorize(MediaPermissions.Create)] - public virtual async Task> EmptyFolder(string flavor = null) => await EmptyModel(flavor, x => x.IsFolder = true); - - - [HttpGet("folders")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual Task> GetFoldersByQuery([FromQuery] ListQuery query) - { - query.AdditionalQuery = q => q.Where(x => x.IsFolder); - return GetModelsByIndex(query); - } - - - [HttpGet("folders/{id}")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> GetFolder(string id, string changeVector = null) => await GetModel(id, changeVector); - - - [HttpGet("folders/{id}/children")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> GetFolderChildren(string id, [FromQuery] ListQuery query, [FromQuery] bool files = true) - { - id = NormalizeParentId(id); - - zero.Media.Media parent = null; - - if (id.HasValue()) - { - parent = await Store.Load(id); - - if (parent == null) - { - return NotFound(); - } - } - - query.OrderQuery = q => q.OrderByDescending(x => x.IsFolder).ThenByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(id, query.Page, query.PageSize, q => q.WhereIf(x => x.IsFolder, !files).Filter(query)); - Paged mappedResult = Mapper.Map(result); - - // get children for all folders - string[] folderIds = mappedResult.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray(); - IList children = await Store.Session.Query() - .ProjectInto() - .Where(x => x.Id.In(folderIds)) - .ToListAsync(); - - foreach (MediaBasic item in mappedResult.Items) - { - if (item.IsFolder) - { - zero_Api_Media_ChildCounts.Result childCounts = children.FirstOrDefault(x => x.Id == item.Id); - - if (childCounts != null) - { - item.Children = !files ? childCounts.ChildFolderCount : childCounts.ChildCount; - } - } - } - - mappedResult.Properties.Add("parentId", parent?.ParentId); - - return mappedResult; - } - - - [HttpGet("folders/{id}/hierarchy")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> GetFolderHierarchy(string id) - { - return await Store.GetHierarchy(NormalizeParentId(id)); - } - - - [HttpPost("folders")] - [ZeroAuthorize(MediaPermissions.Create)] - public virtual Task> CreateFolder(zero.Media.Media saveModel) - { - saveModel.IsFolder = true; - return CreateModel(saveModel); - } - - - [HttpPut("folders/{id}")] - [ZeroAuthorize(MediaPermissions.Update)] - public virtual Task> UpdateFolder(string id, zero.Media.Media updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpPut("folders/{id}/move/{destinationId}")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> MoveFolder(string id, string destinationId) => await MoveModel(id, NormalizeParentId(destinationId)); - - - [HttpDelete("folders/{id}")] - [ZeroAuthorize(MediaPermissions.Delete)] - public virtual Task>> DeleteFolder(string id) => DeleteModelWithDescendants(id); - - #endregion - - - #region file operations - - [HttpGet("empty")] - [ZeroAuthorize(MediaPermissions.Create)] - public virtual async Task> Empty(string flavor = null) => await EmptyModel(flavor, x => x.IsFolder = false); - - - [HttpGet("")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual Task> GetByQuery([FromQuery] ListQuery query) - { - query.AdditionalQuery = q => q.Where(x => !x.IsFolder); - return GetModelsByIndex(query); - } - - - [HttpGet("search")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> Search([FromQuery] ListQuery query, [FromQuery(Name = "q")] string searchQuery, [FromQuery] string parent = null, [FromQuery] bool includeSubfolders = true) - { - query.OrderQuery = q => q.OrderByScoreDescending().ThenByDescending(x => x.IsFolder).ThenByDescending(x => x.CreatedDate); - query.Search = null; - - if (searchQuery.IsNullOrWhiteSpace()) - { - return NotFound(); - } - - if (parent.HasValue()) - { - List descendantIds = await Store.Session.Query().Where(x => x.Path.Contains(parent) && x.IsFolder).Select(x => x.Id).ToListAsync(); - descendantIds.Add(parent); - query.AdditionalQuery = q => q.Where(x => x.ParentId.In(descendantIds)); - } - - Paged result = await Store.Load(query.Page, query.PageSize, q => q - .SearchIf(x => x.Name, searchQuery, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And) - .Filter(query) - ); - - Paged mappedResult = Mapper.Map(result); - - // get children for all folders - string[] folderIds = mappedResult.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray(); - IList children = await Store.Session.Query() - .ProjectInto() - .Where(x => x.Id.In(folderIds)) - .ToListAsync(); - - foreach (MediaBasic item in mappedResult.Items) - { - if (item.IsFolder) - { - zero_Api_Media_ChildCounts.Result childCounts = children.FirstOrDefault(x => x.Id == item.Id); - item.Children = childCounts?.ChildCount ?? 0; - } - } - - return mappedResult; - } - - - [HttpGet("{id}")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> Get(string id, string changeVector = null) => await GetModel(id, changeVector); - - - [HttpGet("{id}/source")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> GetSource(string id) - { - string path = await Media.GetPublicFilePath(id); - - if (path.IsNullOrEmpty()) - { - return NotFound(); - } - - return new MediaSourceResult() - { - Path = path - }; - } - - - [HttpGet("{id}/hierarchy")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> GetHierarchy(string id) => await Store.GetHierarchy(NormalizeParentId(id)); - - - [HttpGet("{id}/search")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> SearchByQueryAndParent(string id, [FromQuery] ListQuery query) - { - List folderIds = await Store.Session.Query().Where(x => x.Path.Contains(id) && x.IsFolder).Select(x => x.Id).ToListAsync(); - folderIds.Add(id); - - query.AdditionalQuery = q => q.Where(x => x.ParentId.In(folderIds)); - - return await GetModelsByIndex(query); - } - - - [HttpPost("")] - [ZeroAuthorize(MediaPermissions.Create)] - public virtual async Task> Create([FromForm] IFormFile file, [FromForm] string folderId = null) - { - Result result = await Media.UploadFile(file, folderId); - - bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal; - - if (result.IsSuccess) - { - return Created("/", minimalResponse ? null : result.Model); // TODO correct URL - } - - return result.WithoutModel(); - } - - - [HttpPut("{id}")] - [ZeroAuthorize(MediaPermissions.Update)] - public virtual Task> Update(string id, zero.Media.Media updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpPut("{id}/move/{destinationId}")] - [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> Move(string id, string destinationId) => await MoveModel(id, NormalizeParentId(destinationId)); - - - [HttpDelete("{id}")] - [ZeroAuthorize(MediaPermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); - - - [HttpGet("{id}/{size}.tmp")] - public async Task GetThumbnail(string id, string size) - { - zero.Media.Media media = await Media.GetFile(id); - - if (media == null) - { - return NotFound(); - } - - string path = Media.GetPublicFilePath(media); - - if (path == null) - { - return NotFound(); - } - - if (path.StartsWith("url://")) - { - path = path.Substring(6); - } - - FileExtensionContentTypeProvider provider = new(); - string contentType; - if (!provider.TryGetContentType(Path.GetFileName(path), out contentType)) - { - contentType = "application/octet-stream"; - } - - try - { - return File(await Media.GetFileStream(media), contentType, DateTimeOffset.Now, EntityTagHeaderValue.Any); - } - catch (FileSystemException) - { - return NotFound(); - } - } - - #endregion -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/MediaModule.cs b/zero.Api/Endpoints/Media/MediaModule.cs deleted file mode 100644 index c5b3dd21..00000000 --- a/zero.Api/Endpoints/Media/MediaModule.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Media; - -public class MediaModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - opts.Indexes.Add(); - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/MediaPermissions.cs b/zero.Api/Endpoints/Media/MediaPermissions.cs deleted file mode 100644 index a49f0b3e..00000000 --- a/zero.Api/Endpoints/Media/MediaPermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace zero.Api.Endpoints.Media; - -public class MediaPermissions : PermissionProvider -{ - public const string Group = "zero.media"; - - public const string Create = "zero.settings.media.create"; - public const string Read = "zero.settings.media.read"; - public const string Update = "zero.settings.media.update"; - public const string Delete = "zero.settings.media.delete"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@media.list"); - group.Permissions.Add(new Permission("zero.media.defaults", "Default permissions") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/_Media/MediaController.cs b/zero.Api/Endpoints/Media/_Media/MediaController.cs deleted file mode 100644 index f952a3a0..00000000 --- a/zero.Api/Endpoints/Media/_Media/MediaController.cs +++ /dev/null @@ -1,72 +0,0 @@ -//using Microsoft.AspNetCore.Http; -//using Microsoft.AspNetCore.Mvc; -//using Microsoft.AspNetCore.StaticFiles; -//using Microsoft.Net.Http.Headers; -//using System; -//using System.Collections.Generic; -//using System.IO; -//using System.Net.Http; -//using System.Threading.Tasks; -//using zero.Core; -//using zero.Core.Collections; -//using zero.Core.Entities; -//using zero.Core.Identity; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// [ZeroAuthorize(Permissions.Sections.Media, PermissionsValue.True)] -// public class MediaController : ZeroBackofficeCollectionController -// { -// IPaths Paths; - -// public MediaController(IMediaCollection collection, IPaths paths) : base(collection) -// { -// Paths = paths; -// PreviewTransform = (item, model) => model.Icon = "fth-globe"; -// } - - -// public async Task> GetListByQuery([FromQuery] MediaListItemQuery query) -// { -// query.IncludeInactive = true; -// return await Collection.Load(query); -// } - - -// [HttpPost] -// public async Task> Upload(IFormFile file, [FromForm] string folderId) => await Collection.Save(await Collection.Upload(file, folderId)); - -// [HttpPost] -// public async Task UploadTemporary(IFormFile file, [FromForm] string folderId) => await Collection.Upload(file, folderId); - -// [HttpPost] -// public async Task> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId); - - -// public async Task GetAll([FromQuery] MediaListQuery query) -// { -// query.IncludeInactive = true; -// Paged items = (await Collection.Load(query)).MapTo(x => new MediaListModel() -// { -// Id = x.Id, -// IsFolder = false, -// Name = x.Name, -// Size = x.Size, -// Source = x.PreviewSource ?? x.Source, -// Type = x.Type -// }); - -// IList hierarchy = null; -// MediaFolder folder = null; - -// if (!String.IsNullOrEmpty(query.FolderId)) -// { -// folder = await Collection.Folders.Load(query.FolderId); -// hierarchy = await Collection.Folders.GetHierarchy(query.FolderId); -// } - -// return new MediaListResultModel(items, null, folder, hierarchy); -// } -// } -//} diff --git a/zero.Api/Endpoints/Media/_Media/MediaFolderController.cs b/zero.Api/Endpoints/Media/_Media/MediaFolderController.cs deleted file mode 100644 index effc44bf..00000000 --- a/zero.Api/Endpoints/Media/_Media/MediaFolderController.cs +++ /dev/null @@ -1,26 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using System.Collections.Generic; -//using System.Threading.Tasks; -//using zero.Core.Collections; -//using zero.Core.Entities; -//using zero.Core.Identity; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// [ZeroAuthorize(Permissions.Sections.Media, PermissionsValue.True)] -// public class MediaFolderController : ZeroBackofficeCollectionController -// { -// public MediaFolderController(IMediaFolderCollection collection) : base(collection) { } - - -// public async Task> GetHierarchy([FromQuery] string id) => await Collection.GetHierarchy(id); - - -// public async Task> GetAllAsTree([FromQuery] string parent = null, [FromQuery] string active = null) => await Collection.LoadAsTree(parent, active); - - -// [HttpPost] -// public async Task> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId); -// } -//} diff --git a/zero.Api/Endpoints/Media/_Media/MediaTreeService.cs b/zero.Api/Endpoints/Media/_Media/MediaTreeService.cs deleted file mode 100644 index a07c3b4e..00000000 --- a/zero.Api/Endpoints/Media/_Media/MediaTreeService.cs +++ /dev/null @@ -1,250 +0,0 @@ -//using Raven.Client.Documents; -//using Raven.Client.Documents.Linq; -//using Raven.Client.Documents.Session; - -//namespace zero.Backoffice.Modules; - -//public class MediaTreeService : IMediaTreeService -//{ -// protected IMediaStore Media { get; private set; } - -// protected PageOptions PageOptions { get; set; } - - -// public PageTreeService(IPagesStore pages, IZeroOptions options, IRoutes routes) -// { -// Media = pages; -// Routes = routes; -// PageOptions = options.For(); -// } - - -// /// -// /// FOR MEDIA -// public virtual async Task> Load(MediaListItemQuery query) -// { -// bool hasSearch = !query.Search.IsNullOrWhiteSpace(); -// bool isRoot = query.FolderId.IsNullOrWhiteSpace(); - -// query.SearchFor(entity => entity.Name); - -// query.OrderQuery = q => q -// .OrderByDescending(x => x.IsFolder) -// .ThenBy(query.OrderBy, query.OrderIsDescending, query.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double); - -// IRavenQueryable dbQuery = Session.Query().ProjectInto(); - -// if (!hasSearch || !query.SearchIsGlobal) -// { -// dbQuery = dbQuery.WhereIf(x => x.ParentId == query.FolderId, !query.FolderId.IsNullOrEmpty(), x => x.ParentId == null); -// } - -// Paged result = await dbQuery.ToQueriedListAsyncX(query); - -// string[] ids = result.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray(); - -// List children = await Session.Query() -// .Where(x => x.ParentId.In(ids)) -// .ToListAsync(); - -// foreach (MediaListItem item in result.Items) -// { -// item.Children = children.FirstOrDefault(x => x.ParentId == item.Id)?.ChildrenCount ?? 0; -// } - -// return result; -// } - - -// /// -// /// FOR MEDIA FOLDER -// public async Task> LoadAsTree(string parentId = null, string activeId = null) -// { -// List items = new(); -// string[] openIds = Array.Empty(); - -// IList folders = await Session.Query() -// .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) -// .OrderByDescending(x => x.CreatedDate).ThenBy(x => x.Name) -// .ToListAsync(); - - -// // get hierarchy so we know if we should set the folder to open -// if (!activeId.IsNullOrEmpty()) -// { -// MediaFolder_ByHierarchy.Result result = await Session.Query() -// .ProjectInto() -// .Include(x => x.Path.Select(p => p.Id)) -// .FirstOrDefaultAsync(x => x.Id == activeId); - -// if (result != null) -// { -// openIds = result.Path.Select(x => x.Id).ToArray(); -// } -// } - - -// // get children for all folders -// string[] folderIds = folders.Select(x => x.Id).ToArray(); - -// IList children = await Session.Query() -// .ProjectInto() -// .Where(x => x.Id.In(folderIds)) -// .ToListAsync(); - - -// foreach (MediaFolder folder in folders) -// { -// int childCount = children.Count(x => x.Id == folder.Id); - -// items.Add(new TreeItem() -// { -// Id = folder.Id, -// Name = folder.Name, -// HasChildren = childCount > 0, -// ChildCount = childCount, -// ParentId = folder.ParentId, -// Sort = folder.Sort, -// Icon = "fth-folder", -// IsOpen = openIds.Contains(folder.Id), -// IsInactive = !folder.IsActive, -// HasActions = true, -// Modifier = !folder.IsActive ? new TreeItemModifier() -// { -// Icon = "fth-minus-circle color-yellow", -// Name = "Inactive" -// } : null -// }); -// } - -// return items; -// } - - -// /// -// public async Task> GetChildren(string parentId = null, string activeId = null, string search = null) -// { -// IList items = new List(); -// IReadOnlyCollection pageTypes = PageOptions.GetAllItems(); -// string[] openIds = new string[0] { }; -// Paged pages = null; -// IList children = null; -// bool isSearch = !search.IsNullOrWhiteSpace(); - -// if (isSearch) -// { -// pages = await Media.Load(1, Int32.MaxValue, q => q.SearchIf(x => x.Name, search, "*").OrderBy(x => x.Sort, OrderingType.Long)); - -// var urls = await Routes.GetUrls(pages.Items.ToArray()); - -// foreach (Page page in pages.Items) -// { -// if (urls.TryGetValue(page, out string url)) -// { -// page.Url = url; -// } -// } -// } -// else -// { -// pages = await Media.Load(1, Int32.MaxValue, q => q -// .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) -// .OrderBy(x => x.Sort, OrderingType.Long)); - - -// // get hierarchy so we know if we should set the page to open -// if (!activeId.IsNullOrEmpty()) -// { -// Pages_ByHierarchy.Result result = await Media.Session.Query() -// .ProjectInto() -// .Include(x => x.Path.Select(p => p.Id)) -// .FirstOrDefaultAsync(x => x.Id == activeId); - -// if (result != null) -// { -// openIds = result.Path.Select(x => x.Id).ToArray(); // .Union(new string[1] { activeId }) -// } -// } - - -// // get children for all pages -// string[] pageIds = pages.Items.Select(x => x.Id).ToArray(); - -// children = await Media.Session.Query() -// .ProjectInto() -// .Where(x => x.Id.In(pageIds)) -// .ToListAsync(); -// } - - -// // function to get modifier icon -// TreeItemModifier GetModifier(Page page) -// { -// if (page.PublishDate > DateTimeOffset.Now || page.UnpublishDate > DateTimeOffset.Now) -// { -// return new TreeItemModifier("@page.schedule.scheduled", "fth-clock"); -// } -// if (!page.IsActive) -// { -// return new TreeItemModifier("@ui.inactive", "fth-minus-circle color-red"); -// } -// return null; -// } - - -// // build tree -// foreach (Page page in pages.Items) -// { -// PageType pageType = pageTypes.FirstOrDefault(x => x.Alias == page.PageTypeAlias); - -// if (pageType == null) -// { -// continue; -// // TODO the page type does not exist anymore -// } - -// int childCount = isSearch ? 0 : children.Count(x => x.Id == page.Id); - -// items.Add(new TreeItem() -// { -// Id = page.Id, -// Name = page.Name, -// HasChildren = childCount > 0, -// ChildCount = childCount, -// ParentId = page.ParentId, -// Sort = page.Sort, -// Icon = pageType.Icon, -// IsOpen = openIds.Contains(page.Id), -// IsInactive = !page.IsActive, -// HasActions = true, -// Modifier = GetModifier(page), -// Description = isSearch ? page.Url : null -// }); -// } - -// if (parentId.IsNullOrEmpty()) -// { -// items.Add(new TreeItem() -// { -// Id = "recyclebin", -// ParentId = null, -// Sort = 99999, -// Name = "@recyclebin.name", -// Icon = "fth-trash", -// HasChildren = false, -// HasActions = true -// }); -// } - -// return items; -// } -//} - - -//public interface IMediaTreeService -//{ -// /// -// /// Get media children as tree items -// /// -// Task> GetChildren(string parentId = null, string activeId = null, string search = null); -//} \ No newline at end of file diff --git a/zero.Api/Endpoints/NotFound/NotFoundController.cs b/zero.Api/Endpoints/NotFound/NotFoundController.cs deleted file mode 100644 index 1abeae49..00000000 --- a/zero.Api/Endpoints/NotFound/NotFoundController.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.NotFound; - -public class NotFoundZeroApiController : Controller -{ - public virtual ActionResult Index() - { - return NotFound(); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/PageModules/PageModuleModule.cs b/zero.Api/Endpoints/PageModules/PageModuleModule.cs deleted file mode 100644 index 7f819fe0..00000000 --- a/zero.Api/Endpoints/PageModules/PageModuleModule.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.PageModules; - -public class PageModuleModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/PageModules/PageModulePermissions.cs b/zero.Api/Endpoints/PageModules/PageModulePermissions.cs deleted file mode 100644 index 82269abc..00000000 --- a/zero.Api/Endpoints/PageModules/PageModulePermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace zero.Api.Endpoints.PageModules; - -public class PageModulePermissions : PermissionProvider -{ - public const string Group = "zero.pagemodules"; - - public const string Create = "zero.pagemodules.create"; - public const string Read = "zero.pagemodules.read"; - public const string Update = "zero.pagemodules.update"; - public const string Delete = "zero.pagemodules.delete"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@module.list"); - group.Permissions.Add(new Permission("zero.pagemodules.defaults", "Default permissions") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/PageModules/PageModulesController.cs b/zero.Api/Endpoints/PageModules/PageModulesController.cs deleted file mode 100644 index 13ba6624..00000000 --- a/zero.Api/Endpoints/PageModules/PageModulesController.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.PageModules; - -public class PageModulesController : ZeroApiController -{ - readonly IPageModuleTypeService ModuleTypeService; - - public PageModulesController(IPageModuleTypeService moduleTypeService) - { - ModuleTypeService = moduleTypeService; - } - - - [HttpGet("")] - [ZeroAuthorize(PageModulePermissions.Read)] - public async Task>> GetModuleTypes([FromQuery] string[] tags = default, [FromQuery] string pageId = default) => Ok(await ModuleTypeService.GetModuleTypes(tags, pageId)); - - - [HttpGet("{alias}")] - [ZeroAuthorize(PageModulePermissions.Read)] - public ActionResult GetModuleType(string alias) => Ok(ModuleTypeService.GetModuleType(alias)); - - - [HttpGet("{alias}/empty")] - [ZeroAuthorize(PageModulePermissions.Read)] - public ActionResult GetEmpty(string alias) - { - PageModule module = ModuleTypeService.GetEmpty(alias); - - if (module == null) - { - return NotFound(); - } - - return module; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_ChildCounts.cs b/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_ChildCounts.cs deleted file mode 100644 index e0a2e52a..00000000 --- a/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_ChildCounts.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Pages; - -public class zero_Api_Pages_ChildCounts : ZeroIndex -{ - public class Result : ZeroIdEntity - { - public int ChildCount { get; set; } - } - - protected override void Create() - { - Map = items => items.Where(x => x.ParentId != null).Select(item => new Result - { - Id = item.ParentId, - ChildCount = 1 - }); - - Reduce = results => results.GroupBy(x => new { x.Id }).Select(group => new Result() - { - Id = group.Key.Id, - ChildCount = group.Sum(x => x.ChildCount) - }); - - StoreAllFields(FieldStorage.Yes); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_Listing.cs b/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_Listing.cs deleted file mode 100644 index 517c0ca5..00000000 --- a/zero.Api/Endpoints/Pages/Indexes/zero_Api_Pages_Listing.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Pages; - -public class zero_Api_Pages_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - ParentId = item.ParentId, - CreatedDate = item.CreatedDate, - Sort = item.Sort - }); - - Index(x => x.Name, FieldIndexing.Search); - Index(x => x.ParentId, FieldIndexing.Exact); - Index(x => x.CreatedDate, FieldIndexing.Exact); - Index(x => x.Sort, FieldIndexing.Exact); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/Maps/PageBasic.cs b/zero.Api/Endpoints/Pages/Maps/PageBasic.cs deleted file mode 100644 index e68e39f1..00000000 --- a/zero.Api/Endpoints/Pages/Maps/PageBasic.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Endpoints.Pages; - -public class PageBasic : ZeroIdEntity -{ - public string ParentId { get; set; } - - public string Name { get; set; } - - public int Children { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/Maps/PageEdit.cs b/zero.Api/Endpoints/Pages/Maps/PageEdit.cs deleted file mode 100644 index e4b02663..00000000 --- a/zero.Api/Endpoints/Pages/Maps/PageEdit.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace zero.Api.Endpoints.Pages; - -public class PageEdit : ZeroIdEntity -{ - // we can't use Page as property type here - // cause that would serialize flavors to Page and remove additional properties. - // according to the System.Text.Json docs using "object" will serialize to the implementing type - public object Page { get; set; } - - public FlavorConfig PageType { get; set; } - - public List Urls { get; set; } = new(); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/Maps/PageMapperProfile.cs b/zero.Api/Endpoints/Pages/Maps/PageMapperProfile.cs deleted file mode 100644 index 930eafbd..00000000 --- a/zero.Api/Endpoints/Pages/Maps/PageMapperProfile.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace zero.Api.Endpoints.Pages; - -public class PageMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - // mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(Page source, PageBasic target, IZeroMapperContext ctx) - { - //this.MapBasicData(source, target); - } - - //protected virtual void Map(CountrySave source, Country target, IZeroMapperContext ctx) - //{ - // this.MapSaveData(source, target); - // target.Code = source.Code; - // target.IsPreferred = source.IsPreferred; - //} -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/ModulesController.cs b/zero.Api/Endpoints/Pages/ModulesController.cs deleted file mode 100644 index 9752200d..00000000 --- a/zero.Api/Endpoints/Pages/ModulesController.cs +++ /dev/null @@ -1,40 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using System; -//using System.Collections.Generic; -//using System.Threading.Tasks; -//using zero.Core.Api; -//using zero.Core.Entities; -//using zero.Core.Utils; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// public class ModulesController : BackofficeController -// { -// IModulesApi Api; - -// public ModulesController(IModulesApi api) -// { -// Api = api; -// } - - -// public async Task> GetModuleTypes([FromQuery] string[] tags = default, [FromQuery] string pageId = default) => await Api.GetModuleTypes(tags, pageId); - - -// public ModuleType GetModuleType([FromQuery] string alias) => Api.GetModuleType(alias); - - -// public EditModel GetEmpty(string alias) -// { -// ModuleType moduleType = Api.GetModuleType(alias); -// Module module = Activator.CreateInstance(moduleType.ContentType) as Module; - -// module.ModuleTypeAlias = moduleType.Alias; -// module.Id = IdGenerator.Create(8); -// module.IsActive = true; - -// return Edit(module); -// } -// } -//} diff --git a/zero.Api/Endpoints/Pages/PageModule.cs b/zero.Api/Endpoints/Pages/PageModule.cs deleted file mode 100644 index 5c63470e..00000000 --- a/zero.Api/Endpoints/Pages/PageModule.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Pages; - -public class PageModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/PagePermissions.cs b/zero.Api/Endpoints/Pages/PagePermissions.cs deleted file mode 100644 index 01e9878a..00000000 --- a/zero.Api/Endpoints/Pages/PagePermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace zero.Api.Endpoints.Pages; - -public class PagePermissions : PermissionProvider -{ - public const string Group = "zero.page"; - - public const string Create = "zero.page.create"; - public const string Read = "zero.page.read"; - public const string Update = "zero.page.update"; - public const string Delete = "zero.page.delete"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@page.list"); - group.Permissions.Add(new Permission("zero.page.defaults", "Default permissions") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/PagesController.cs b/zero.Api/Endpoints/Pages/PagesController.cs deleted file mode 100644 index 8121e27b..00000000 --- a/zero.Api/Endpoints/Pages/PagesController.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Pages; - -public class PagesController : ZeroApiTreeEntityStoreController -{ - IPageTypeService PageTypeService; - IRoutes Routes; - - public PagesController(IPagesStore store, IPageTypeService pageTypeService, IRoutes routes) : base(store) - { - PageTypeService = pageTypeService; - Routes = routes; - } - - - [HttpGet("empty")] - [ZeroAuthorize(PagePermissions.Create)] - public virtual async Task> Empty(string flavor, string parentId = null) - { - Page page = await Store.Empty(flavor, parentId); - - if (page == null) - { - return NotFound(); - } - - if (!await Store.IsAllowedAsChild(page, parentId)) - { - return BadRequest(Result.Fail("@errors.childnotallowed")); - } - - return page; - } - - - [HttpGet("{id}/flavors")] - [ZeroAuthorize(PagePermissions.Read)] - public async Task>> GetAllowedFlavors(string id) => Ok(await PageTypeService.GetAllowedTypes(NormalizeParentId(id))); - - - [HttpGet("{id}")] - [ZeroAuthorize(PagePermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("{id}/children")] - [ZeroAuthorize(PagePermissions.Read)] - public virtual async Task> GetChildren(string id, [FromQuery] ListQuery query) - { - query.SearchFor(x => x.Name); - query.OrderQuery = q => q.OrderByDescending(x => x.Sort).ThenByDescending(x => x.CreatedDate); - Paged result = await Store.LoadChildren(id, query.Page, query.PageSize, q => q.Filter(query)); - - return result; - } - - [HttpGet("")] - [ZeroAuthorize(PagePermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) - { - query.SearchFor(x => x.Name); - query.OrderQuery = q => q.OrderByDescending(x => x.Sort).ThenByDescending(x => x.CreatedDate); - return GetModelsByIndex(query); - } - - [HttpGet("{id}/url")] - [ZeroAuthorize(PagePermissions.Read)] - public async Task> GetUrl(string id) - { - string url = await Routes.GetUrl(id); - return new UrlResult(ZeroContext.Application.Domains.FirstOrDefault(), url); - } - - [HttpPost("")] - [ZeroAuthorize(PagePermissions.Create)] - public virtual Task> Create(Page saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(PagePermissions.Update)] - public virtual Task> Update(string id, Page updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(PagePermissions.Delete)] - public virtual Task>> Delete(string id) => DeleteModelWithDescendants(id); - - - [HttpPut("{id}/move/{destinationId}")] - [ZeroAuthorize(PagePermissions.Update)] - public virtual Task> Move(string id, string destinationId) => MoveModel(id, NormalizeParentId(destinationId)); - - - [HttpPut("{id}/copy/{destinationId}")] - [ZeroAuthorize(PagePermissions.Update)] - public virtual Task> Copy(string id, string destinationId, [FromQuery] bool includeDescendants = false) - { - destinationId = NormalizeParentId(destinationId); - - return includeDescendants ? - CopyModelWithDescendants(id, destinationId) - : CopyModel(id, destinationId); - } - - - [HttpPut("sort")] - [ZeroAuthorize(PagePermissions.Update)] - public virtual Task> Sort([FromBody] string[] ids) => SortModels(ids); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Pages/_PagesController.cs b/zero.Api/Endpoints/Pages/_PagesController.cs deleted file mode 100644 index 3583d652..00000000 --- a/zero.Api/Endpoints/Pages/_PagesController.cs +++ /dev/null @@ -1,104 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using Raven.Client.Documents; -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; -//using zero.Core.Api; -//using zero.Core.Collections; -//using zero.Core.Entities; -//using zero.Core.Extensions; -//using zero.Core.Routing; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// public class PagesController : BackofficeCollectionController -// { -// IRoutes Routes; - -// public PagesController(IPageService collection, IRoutes routes) : base(collection) -// { -// Routes = routes; -// } - - -// public override async Task> GetById([FromQuery] string id, [FromQuery] string changeVector = null) -// { -// Page entity = changeVector.IsNullOrEmpty() ? await Collection.GetById(id) : await Collection.GetRevision(changeVector); - -// return entity == null ? null : Edit>(new PageEditModel() -// { -// Entity = entity, -// PageType = Collection.GetPageType(entity.PageTypeAlias), -// Urls = new List() { await Routes.GetUrl(entity) } -// }); -// } - - -// public override async Task> GetPreviews([FromQuery] List ids) -// { -// IReadOnlyCollection pageTypes = Options.Pages.GetAllItems(); -// Dictionary pages = await Collection.GetByIds(ids.ToArray()); -// Dictionary routes = await Routes.GetRoutes(pages.Where(x => x.Value != null).Select(x => x.Value).ToArray()); - -// return Previews(pages, item => -// { -// routes.TryGetValue(item, out Route route); - -// PickerPreviewModel model = new() -// { -// Id = item.Id, -// Icon = pageTypes.FirstOrDefault(x => x.Alias == item.PageTypeAlias)?.Icon ?? "fth-folder", -// Name = item.Name, -// Text = route?.Url.Or("No URL found") -// }; - -// PreviewTransform?.Invoke(item, model); -// return model; -// }); - -// } - - -// public async Task> GetChildren([FromQuery] string parent = null, [FromQuery] string active = null, [FromQuery] string search = null) -// { -// return await Collection.GetChildren(parent, active, search); -// } - - -// public PageType GetPageType([FromQuery] string alias) => Collection.GetPageType(alias); - - -// public async Task> GetUrls([FromQuery] string pageId) -// { -// string url = await Routes.GetUrl(pageId); -// return url.HasValue() ? new List() { url } : new List(); -// } - - -// public async Task> GetAllowedPageTypes([FromQuery] string parent = null) => await Collection.GetAllowedPageTypes(parent); - - -// public async Task> GetEmptyByType([FromQuery] string type, [FromQuery] string parent = null) => Edit(await Collection.GetEmpty(type, parent)); - - -// [HttpPost] -// public async Task>> SaveSorting([FromBody] string[] ids) => await Collection.SaveSorting(ids); - - -// [HttpPost] -// public async Task> Move([FromBody] ActionCopyModel model) => await Collection.Move(model.Id, model.DestinationId); - - -// [HttpPost] -// public async Task> Copy([FromBody] ActionCopyModel model) => await Collection.Copy(model.Id, model.DestinationId, model.IncludeDescendants); - - -// [HttpPost] -// public async Task> Restore([FromBody] ActionCopyModel model) => await Collection.Restore(model.Id, model.IncludeDescendants); - - -// [HttpDelete] -// public async Task> DeleteRecursive([FromQuery] string id) => await Collection.Delete(id, recursive: true, moveToRecycleBin: true); -// } -//} diff --git a/zero.Api/Endpoints/RecycleBin/RecycleBinController.cs b/zero.Api/Endpoints/RecycleBin/RecycleBinController.cs deleted file mode 100644 index 8f6e88e3..00000000 --- a/zero.Api/Endpoints/RecycleBin/RecycleBinController.cs +++ /dev/null @@ -1,36 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using System.Threading.Tasks; -//using zero.Core.Api; -//using zero.Core.Entities; - -//namespace zero.Web.Controllers -//{ -// public class RecycleBinController : BackofficeController -// { -// IRecycleBinApi Api; - -// public RecycleBinController(IRecycleBinApi api) -// { -// Api = api; -// } - - -// public async Task> GetByQuery([FromQuery] RecycleBinListQuery query) -// { -// query.IncludeInactive = true; -// return await Api.GetByQuery(query); -// } - - -// public async Task GetCountByOperation([FromQuery] string operationId) => await Api.GetCountByOperation(operationId); - - -// [HttpDelete] -// public async Task> Delete([FromQuery] string id) => await Api.Delete(id); - - -// [HttpDelete] -// public async Task> DeleteByGroup([FromQuery] string group) => await Api.DeleteByGroup(group); - -// } -//} diff --git a/zero.Api/Endpoints/Search/SearchController.cs b/zero.Api/Endpoints/Search/SearchController.cs deleted file mode 100644 index 525d7666..00000000 --- a/zero.Api/Endpoints/Search/SearchController.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using zero.Search; - -namespace zero.Api.Endpoints.Search; - -public class SearchController : ZeroApiController -{ - protected ISearchService Service { get; set; } - - public SearchController(ISearchService service) - { - Service = service; - } - - - [HttpGet("")] - public async Task> Query([FromQuery] ListQuery query) - { - if (!query.Search.HasValue()) - { - return new Paged(new List(), 0, query.Page, query.PageSize); - } - return await Service.Query(query.Search, query.Page, query.PageSize); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Search/SearchModule.cs b/zero.Api/Endpoints/Search/SearchModule.cs deleted file mode 100644 index 1a42e399..00000000 --- a/zero.Api/Endpoints/Search/SearchModule.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Search; - -public class SearchModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Search/SearchPermissions.cs b/zero.Api/Endpoints/Search/SearchPermissions.cs deleted file mode 100644 index 7808aeab..00000000 --- a/zero.Api/Endpoints/Search/SearchPermissions.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace zero.Api.Endpoints.Search; - -public class SearchPermissions : PermissionProvider -{ - public const string Group = "zero.search"; - - public const string Search = "zero.search.use"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@search.permissions.search_group"); - group.Permissions.Add(new Permission(Search, "@search.permissions.search")); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Spaces/Indexes/zero_Api_Spaces_Listing.cs b/zero.Api/Endpoints/Spaces/Indexes/zero_Api_Spaces_Listing.cs deleted file mode 100644 index fc1b945b..00000000 --- a/zero.Api/Endpoints/Spaces/Indexes/zero_Api_Spaces_Listing.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Spaces; - -public class zero_Api_Spaces_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - IsActive = item.IsActive, - Flavor = item.Flavor, - CreatedDate = item.CreatedDate - }); - - Index(x => x.Name, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Spaces/SpaceModule.cs b/zero.Api/Endpoints/Spaces/SpaceModule.cs deleted file mode 100644 index d94da71d..00000000 --- a/zero.Api/Endpoints/Spaces/SpaceModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Spaces; - -public class SpaceModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - //services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Spaces/SpacePermissions.cs b/zero.Api/Endpoints/Spaces/SpacePermissions.cs deleted file mode 100644 index 5df46f86..00000000 --- a/zero.Api/Endpoints/Spaces/SpacePermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace zero.Api.Endpoints.Spaces; - -public class SpacePermissions : PermissionProvider -{ - public const string Group = "zero.space"; - - public const string Create = "zero.space.create"; - public const string Read = "zero.space.read"; - public const string Update = "zero.space.update"; - public const string Delete = "zero.space.delete"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@space.list"); - group.Permissions.Add(new Permission("zero.space.defaults", "Default permissions") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Spaces/SpacesController.cs b/zero.Api/Endpoints/Spaces/SpacesController.cs deleted file mode 100644 index 115efba2..00000000 --- a/zero.Api/Endpoints/Spaces/SpacesController.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System.Collections; - -namespace zero.Api.Endpoints.Spaces; - -public class SpacesController : ZeroApiEntityStoreController -{ - ISpaceTypeService SpaceTypes; - - public SpacesController(ISpaceStore store, ISpaceTypeService spaceTypes) : base(store) - { - SpaceTypes = spaceTypes; - } - - - [HttpGet("types")] - [ZeroAuthorize(SpacePermissions.Read)] - public virtual ActionResult GetTypes() => Ok(SpaceTypes.GetAll()); - - [HttpGet("types/{alias}")] - [ZeroAuthorize(SpacePermissions.Read)] - public virtual ActionResult GetType(string alias) => Ok(SpaceTypes.GetByAlias(alias)); - - [HttpGet("{alias}")] - [ZeroAuthorize(SpacePermissions.Read)] - public virtual async Task> Get(string alias, [FromQuery] ListQuery query = null) - { - SpaceType space = SpaceTypes.GetByAlias(alias); - - if (space == null) - { - return NotFound(); - } - - if (space.View != SpaceView.Editor) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Store.Load(query.Page, query.PageSize, q => q.Where(x => x.Flavor == alias).Filter(query)); - return result; - } - - var stream = Store.Stream(q => q.Where(x => x.Flavor == alias)); - Space item = (await stream.FirstOrDefaultAsync()) ?? (await Store.Empty(alias)); - return item; - } - - - [HttpGet("{alias}/empty")] - [ZeroAuthorize(SpacePermissions.Create)] - public virtual Task> Empty(string alias) => EmptyModel(alias); - - - [HttpGet("{alias}/{id}")] - [ZeroAuthorize(SpacePermissions.Read)] - public virtual Task> Get(string alias, string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpPost("")] - [ZeroAuthorize(SpacePermissions.Create)] - public virtual Task> Create([FromBody] Space saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(SpacePermissions.Update)] - public virtual Task> Update(string id, [FromBody] Space updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(SpacePermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/Indexes/zero_Api_Translations_Listing.cs b/zero.Api/Endpoints/Translations/Indexes/zero_Api_Translations_Listing.cs deleted file mode 100644 index bc57fc6f..00000000 --- a/zero.Api/Endpoints/Translations/Indexes/zero_Api_Translations_Listing.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Translations; - -public class zero_Api_Translations_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - Value = item.Value, - Key = item.Key, - CreatedDate = item.CreatedDate - }); - - Index(x => x.Name, FieldIndexing.Search); - Index(x => x.Key, FieldIndexing.Search); - Index(x => x.Value, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/Maps/TranslationBasic.cs b/zero.Api/Endpoints/Translations/Maps/TranslationBasic.cs deleted file mode 100644 index b00a937c..00000000 --- a/zero.Api/Endpoints/Translations/Maps/TranslationBasic.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace zero.Api.Endpoints.Translations; - -public class TranslationBasic : ZeroIdEntity -{ - public string Key { get; set; } - - public DateTimeOffset CreatedDate { get; set; } - - public string Flavor { get; set; } - - public string Value { get; set; } - - public TranslationDisplay Display { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/Maps/TranslationEdit.cs b/zero.Api/Endpoints/Translations/Maps/TranslationEdit.cs deleted file mode 100644 index 2d542cdc..00000000 --- a/zero.Api/Endpoints/Translations/Maps/TranslationEdit.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Translations; - -public class TranslationEdit : DisplayModel -{ - public string Value { get; set; } - - public TranslationDisplay Display { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/Maps/TranslationMapperProfile.cs b/zero.Api/Endpoints/Translations/Maps/TranslationMapperProfile.cs deleted file mode 100644 index 1804cb26..00000000 --- a/zero.Api/Endpoints/Translations/Maps/TranslationMapperProfile.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace zero.Api.Endpoints.Translations; - -public class TranslationMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(Translation source, TranslationBasic target, IZeroMapperContext ctx) - { - target.Id = source.Id; - target.Key = source.Key; - target.Flavor = source.Flavor; - target.CreatedDate = source.CreatedDate; - target.Value = source.Value; - target.Display = source.Display; - } - - protected virtual void Map(Translation source, TranslationEdit target, IZeroMapperContext ctx) - { - this.MapDisplayData(source, target); - target.Value = source.Value; - target.Display = source.Display; - } - - protected virtual void Map(TranslationSave source, Translation target, IZeroMapperContext ctx) - { - this.MapSaveData(source, target); - target.Value = source.Value; - target.Display = source.Display; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/Maps/TranslationSave.cs b/zero.Api/Endpoints/Translations/Maps/TranslationSave.cs deleted file mode 100644 index f12409c0..00000000 --- a/zero.Api/Endpoints/Translations/Maps/TranslationSave.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Endpoints.Translations; - -public class TranslationSave : SaveModel -{ - public string Value { get; set; } - - public TranslationDisplay Display { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/TranslationModule.cs b/zero.Api/Endpoints/Translations/TranslationModule.cs deleted file mode 100644 index 8f1eca80..00000000 --- a/zero.Api/Endpoints/Translations/TranslationModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Translations; - -public class TranslationModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/TranslationPermissions.cs b/zero.Api/Endpoints/Translations/TranslationPermissions.cs deleted file mode 100644 index b69f763a..00000000 --- a/zero.Api/Endpoints/Translations/TranslationPermissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace zero.Api.Endpoints.Translations; - -public class TranslationPermissions : PermissionProvider -{ - public const string Create = "zero.settings.translation.create"; - public const string Read = "zero.settings.translation.read"; - public const string Update = "zero.settings.translation.update"; - public const string Delete = "zero.settings.translation.delete"; - - - public override Task Configure(IPermissionContext context) - { - if (!context.TryGetGroup(Constants.Permissions.Groups.Settings, out PermissionGroup group)) - { - group.Permissions.Add(new Permission("zero.settings.translation", "@settings.application.translations.name") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Translations/TranslationsController.cs b/zero.Api/Endpoints/Translations/TranslationsController.cs deleted file mode 100644 index d3d5f031..00000000 --- a/zero.Api/Endpoints/Translations/TranslationsController.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Translations; - -public class TranslationsController : ZeroApiEntityStoreController -{ - public TranslationsController(ITranslationStore store) : base(store) - { - - } - - - [HttpGet("empty")] - [ZeroAuthorize(TranslationPermissions.Create)] - public virtual Task> Empty(string flavor = null) => EmptyModel(flavor); - - - [HttpGet("{id}")] - [ZeroAuthorize(TranslationPermissions.Read)] - public virtual Task> Get(string id, string changeVector = null) => GetModel(id, changeVector); - - - [HttpGet("")] - [ZeroAuthorize(TranslationPermissions.Read)] - public virtual Task> Get([FromQuery] ListQuery query) - { - query.SearchFor(x => x.Key, x => x.Value); - return GetModelsByIndex(query); - } - - - [HttpPost("")] - [ZeroAuthorize(TranslationPermissions.Create)] - public virtual Task> Create(Translation saveModel) => CreateModel(saveModel); - - - [HttpPut("{id}")] - [ZeroAuthorize(TranslationPermissions.Update)] - public virtual Task> Update(string id, Translation updateModel, [FromQuery] string changeToken = null) => UpdateModel(id, updateModel, changeToken); - - - [HttpDelete("{id}")] - [ZeroAuthorize(TranslationPermissions.Delete)] - public virtual Task> Delete(string id) => DeleteModel(id); -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/Indexes/zero_Api_Users_Listing.cs b/zero.Api/Endpoints/Users/Indexes/zero_Api_Users_Listing.cs deleted file mode 100644 index c62900dc..00000000 --- a/zero.Api/Endpoints/Users/Indexes/zero_Api_Users_Listing.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Raven.Client.Documents.Indexes; - -namespace zero.Api.Endpoints.Users; - -public class zero_Api_Users_Listing : ZeroIndex -{ - protected override void Create() - { - Map = items => items.Select(item => new - { - Name = item.Name, - CreatedDate = item.CreatedDate - }); - - Index(x => x.Name, FieldIndexing.Search); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/Maps/UserBasic.cs b/zero.Api/Endpoints/Users/Maps/UserBasic.cs deleted file mode 100644 index 7d8b330a..00000000 --- a/zero.Api/Endpoints/Users/Maps/UserBasic.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace zero.Api.Endpoints.Users; - -public class UserBasic : ZeroIdEntity -{ - public string Name { get; set; } - - public bool IsActive { get; set; } - - public string Email { get; set; } - - public string AvatarId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/Maps/UserMapperProfile.cs b/zero.Api/Endpoints/Users/Maps/UserMapperProfile.cs deleted file mode 100644 index 74550423..00000000 --- a/zero.Api/Endpoints/Users/Maps/UserMapperProfile.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace zero.Api.Endpoints.Users; - -public class UserMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(ZeroUser source, UserBasic target, IZeroMapperContext ctx) - { - target.Id = source.Id; - target.Name = source.Name; - target.Email = source.Email; - target.IsActive = source.IsActive; - target.AvatarId = source.AvatarId; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/UserModule.cs b/zero.Api/Endpoints/Users/UserModule.cs deleted file mode 100644 index b0e546d6..00000000 --- a/zero.Api/Endpoints/Users/UserModule.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Api.Endpoints.Users; - -public class UserModule : ZeroModule -{ - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddSingleton(); - - services.Configure(opts => - { - opts.Indexes.Add(); - }); - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/UserPermissions.cs b/zero.Api/Endpoints/Users/UserPermissions.cs deleted file mode 100644 index adf94058..00000000 --- a/zero.Api/Endpoints/Users/UserPermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace zero.Api.Endpoints.Users; - -public class UserPermissions : PermissionProvider -{ - public const string Group = "zero.user"; - - public const string Create = "zero.user.create"; - public const string Read = "zero.user.read"; - public const string Update = "zero.user.update"; - public const string Delete = "zero.user.delete"; - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new(Group, "@user.list"); - group.Permissions.Add(new Permission("zero.user.defaults", "Default permissions") - { - Children = new() - { - new(Create, "@permission.states.create"), - new(Read, "@permission.states.read"), - new(Update, "@permission.states.update"), - new(Delete, "@permission.states.delete") - } - }); - - context.AddGroup(group); - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Api/Endpoints/Users/Users/UserEditModel.cs b/zero.Api/Endpoints/Users/Users/UserEditModel.cs deleted file mode 100644 index 3205224a..00000000 --- a/zero.Api/Endpoints/Users/Users/UserEditModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using zero.Core.Entities; - -//namespace zero.Web.Models -//{ -// public class UserEditModel : ObsoleteEditModel -// { -// public string Name { get; set; } - -// public bool IsSuper { get; set; } - -// public string Email { get; set; } - -// public bool IsEmailConfirmed { get; set; } - -// public string AvatarId { get; set; } - -// public string LanguageId { get; set; } - -// public List Roles { get; set; } = new List(); - -// public List Claims { get; set; } = new List(); - -// public DateTimeOffset? LockoutEnd { get; set; } - -// public bool IsLockedOut { get; set; } - -// public IList SupportedCultures { get; set; } = new List(); -// } -//} diff --git a/zero.Api/Endpoints/Users/Users/UserPasswordEditModel.cs b/zero.Api/Endpoints/Users/Users/UserPasswordEditModel.cs deleted file mode 100644 index 5f7ca531..00000000 --- a/zero.Api/Endpoints/Users/Users/UserPasswordEditModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -//namespace zero.Web.Models -//{ -// public class UserPasswordEditModel -// { -// public string UserId { get; set; } - -// public string CurrentPassword { get; set; } - -// public string NewPassword { get; set; } - -// public string ConfirmNewPassword { get; set; } -// } -//} diff --git a/zero.Api/Endpoints/Users/Users/UserRoleEditModel.cs b/zero.Api/Endpoints/Users/Users/UserRoleEditModel.cs deleted file mode 100644 index f4da5032..00000000 --- a/zero.Api/Endpoints/Users/Users/UserRoleEditModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -//using System; -//using System.Collections.Generic; -//using zero.Core.Entities; - -//namespace zero.Web.Models -//{ -// public class UserRoleEditModel : ObsoleteEditModel -// { -// public string Name { get; set; } - -// public string Description { get; set; } - -// public string Icon { get; set; } - -// // TODO use UserClaim and resolve to default type -// // see here: http://www.dotnet-programming.com/post/2017/05/08/Aspnet-core-Deserializing-Json-with-Dependency-Injection.aspx -// public List Claims { get; set; } -// } -//} diff --git a/zero.Api/Endpoints/Users/Users/UserRoleListModel.cs b/zero.Api/Endpoints/Users/Users/UserRoleListModel.cs deleted file mode 100644 index ac6b8edd..00000000 --- a/zero.Api/Endpoints/Users/Users/UserRoleListModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -//namespace zero.Web.Models -//{ -// public class UserRoleListModel : ListModel -// { -// public string Name { get; set; } - -// public int CountClaims { get; set; } - -// public string Icon { get; set; } - -// public string Alias { get; set; } -// } -//} diff --git a/zero.Api/Endpoints/Users/Users/UserRolesController.cs b/zero.Api/Endpoints/Users/Users/UserRolesController.cs deleted file mode 100644 index 5f8015d1..00000000 --- a/zero.Api/Endpoints/Users/Users/UserRolesController.cs +++ /dev/null @@ -1,41 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using System.Collections.Generic; -//using System.Threading.Tasks; -//using zero.Core.Api; -//using zero.Core.Entities; -//using zero.Core.Identity; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Read)] -// public class UserRolesController : BackofficeController -// { -// IUserRolesService Api; -// IPermissionsService PermissionsApi; - - -// public UserRolesController(IUserRolesService api, IPermissionsService permissionsApi) -// { -// Api = api; -// PermissionsApi = permissionsApi; -// } - - -// public async Task> GetById([FromQuery] string id) => Edit(await Api.GetById(id)); - - -// public async Task> GetAll() => await Api.GetAll(); - - -// public IList GetAllPermissions() => PermissionsApi.GetAll(); - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Save([FromBody] ZeroUserRole model) => await Api.Save(model); - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Delete([FromQuery] string id) => await Api.Delete(id); -// } -//} diff --git a/zero.Api/Endpoints/Users/Users/UsersController.cs b/zero.Api/Endpoints/Users/Users/UsersController.cs deleted file mode 100644 index c077fb47..00000000 --- a/zero.Api/Endpoints/Users/Users/UsersController.cs +++ /dev/null @@ -1,117 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using System.Collections.Generic; -//using System.Linq; -//using System.Threading.Tasks; -//using zero.Core.Api; -//using zero.Core.Entities; -//using zero.Core.Identity; -//using zero.Web.Models; - -//namespace zero.Web.Controllers -//{ -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Read)] -// public class UsersController : BackofficeController -// { -// IUserService Api; -// IAuthenticationService AuthenticationApi; -// IPermissionsService PermissionsApi; - - -// public UsersController(IUserService api, IAuthenticationService authenticationApi, IPermissionsService permissionsApi) -// { -// Api = api; -// AuthenticationApi = authenticationApi; -// PermissionsApi = permissionsApi; -// IsCoreDatabase = true; -// } - - -// public async Task> GetById([FromQuery] string id) => Edit(await Api.GetUserById(id)); - - -// public async Task> GetAll([FromQuery] ListQuery query) => await Api.GetByQuery(query); - - -// public IList GetAllPermissions() => PermissionsApi.GetAll(); - - -// public async Task> GetForPicker() => (await Api.GetAll()).Select(x => new PickerModel() -// { -// Id = x.Id, -// Name = x.Name, -// IsActive = x.IsActive -// }); - - -// public async Task> GetPreviews([FromQuery] List ids) -// { -// return Previews(await Api.GetByIds(ids.ToArray()), item => new PickerPreviewModel() -// { -// Id = item.Id, -// Icon = item.AvatarId, -// Name = item.Name -// }); -// } - - -// [ZeroAuthorize] -// public async Task> UpdatePassword([FromBody] UserPasswordEditModel model) -// { -// Result result; - -// if (model.NewPassword != model.ConfirmNewPassword) -// { -// result = Result.Fail(nameof(model.NewPassword), "@errors.changepassword.newpasswordsnotmatching"); -// } -// else -// { -// ZeroUser user = await AuthenticationApi.GetUser(); -// result = await Api.UpdatePassword(user as ZeroUser, model.CurrentPassword, model.NewPassword); - -// if (result.IsSuccess) -// { -// await AuthenticationApi.Logout(); -// } -// } - -// return result; -// } - - -// [ZeroAuthorize] -// public async Task> HashPassword([FromBody] UserPasswordEditModel model) -// { -// ZeroUser user = await Api.GetUserById(model.UserId); -// return await Api.HashPassword(user, model.CurrentPassword, model.NewPassword, model.ConfirmNewPassword); -// } - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Disable([FromBody] ZeroUser model) -// { -// ZeroUser entity = await Api.GetUserById(model.Id); -// return await Api.Disable(entity); -// } - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Enable([FromBody] ZeroUser model) -// { -// ZeroUser entity = await Api.GetUserById(model.Id); -// return await Api.Enable(entity); -// } - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Save([FromBody] ZeroUser model) => await Api.Save(model); - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// // TODO do not need settings.users authorization for editing current user profiles -// public async Task> SaveCurrent([FromBody] ZeroUser model) => await Api.Save(model); - - -// [ZeroAuthorize(Permissions.Settings.Users, PermissionsValue.Update)] -// public async Task> Delete([FromQuery] string id) => await Api.Delete(id); -// } -//} diff --git a/zero.Api/Endpoints/Users/UsersController.cs b/zero.Api/Endpoints/Users/UsersController.cs deleted file mode 100644 index 7d27d3e3..00000000 --- a/zero.Api/Endpoints/Users/UsersController.cs +++ /dev/null @@ -1,109 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Api.Endpoints.Users; - -public class UsersController : ZeroApiController -{ - readonly IUserService Users; - - public UsersController(IUserService users) - { - Users = users; - } - - - [HttpGet("empty")] - [ZeroAuthorize(UserPermissions.Create)] - public virtual ActionResult Empty(string flavor = null) - { - return new ZeroUser(); - } - - - [HttpGet("{id}")] - [ZeroAuthorize(UserPermissions.Read)] - public virtual async Task> Get(string id) - { - ZeroUser model = await Users.GetUserById(id); - - if (model == null) - { - return NotFound(); - } - - model.PasswordHash = null; - model.SecurityStamp = null; - - //HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model); - - return model; - } - - - [HttpGet("")] - [ZeroAuthorize(UserPermissions.Read)] - public virtual async Task> Get([FromQuery] ListQuery query) - { - query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); - query.SearchSelector ??= x => x.Name; - Paged result = await Users.GetAll(query.Page, query.PageSize); - return Mapper.Map(result); - } - - - [HttpPost("")] - [ZeroAuthorize(UserPermissions.Create)] - public virtual async Task> Create(ZeroUser saveModel) - { - Result result = await Users.Save(saveModel); - - bool minimalResponse = Hints.ResponsePreference == ApiResponsePreference.Minimal; - - if (result.IsSuccess) - { - return Created("/", minimalResponse ? null : saveModel); - } - - return result.WithoutModel(); - } - - - [HttpPut("{id}")] - [ZeroAuthorize(UserPermissions.Update)] - public virtual async Task> Update(string id, ZeroUser updateModel, [FromQuery] string changeToken = null) - { - if (id != updateModel.Id) - { - return BadRequest(Result.Fail(nameof(id), "@errors.onupdate.noidmatch")); - } - - Result result = await Users.Save(updateModel); - - if (Hints.ResponsePreference == ApiResponsePreference.Minimal) - { - return result.WithoutModel(); - } - - return result; - } - - - [HttpDelete("{id}")] - [ZeroAuthorize(UserPermissions.Delete)] - public virtual async Task> Delete(string id) - { - Result result = await Users.Delete(id); - return result.WithoutModel(); - } - - - [HttpGet("password/random/{length?}")] - [ZeroAuthorize(UserPermissions.Read)] - public virtual ActionResult Password(int length = -1) - { - return new - { - Password = PasswordGenerator.Random(length) - }; - } -} \ No newline at end of file diff --git a/zero.Api/Extensions/IMapperProfileExtensions.cs b/zero.Api/Extensions/IMapperProfileExtensions.cs deleted file mode 100644 index a20c1eac..00000000 --- a/zero.Api/Extensions/IMapperProfileExtensions.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace zero.Api.Extensions; - -public static class IMapperProfileExtensions -{ - /// - /// Map data for a zero entity BasicModel - /// - public static void MapBasicData(this IMapperProfile profile, TSource source, TDestination target) - where TSource : ZeroEntity - where TDestination : BasicModel - { - target.Id = source.Id; - target.Name = source.Name; - target.Alias = source.Alias; - target.Key = source.Key; - target.IsActive = source.IsActive; - target.CreatedDate = source.CreatedDate; - target.Flavor = source.Flavor; - } - - - /// - /// Map data for a zero entity DiplayModel - /// - public static void MapDisplayData(this IMapperProfile profile, TSource source, TDestination target) - where TSource : ZeroEntity - where TDestination : DisplayModel - { - target.Id = source.Id; - target.Name = source.Name; - target.Alias = source.Alias; - target.Key = source.Key; - target.IsActive = source.IsActive; - target.CreatedDate = source.CreatedDate; - target.Flavor = source.Flavor; - - target.Sort = source.Sort; - target.Hash = source.Hash; - target.LastModifiedById = source.LastModifiedById; - target.LastModifiedDate = source.LastModifiedDate; - target.CreatedById = source.CreatedById; - target.LanguageId = source.LanguageId; - } - - - /// - /// Map data for a zero entity SaveModel - /// - public static void MapSaveData(this IMapperProfile profile, TSource source, TDestination target) - where TSource : SaveModel - where TDestination : ZeroEntity - { - target.Name = source.Name; - target.Alias = source.Alias; - target.Key = source.Key; - target.Sort = source.Sort; - target.IsActive = source.IsActive; - target.Flavor = source.Flavor; - } -} diff --git a/zero.Api/Filters/ApiExceptionFilter.cs b/zero.Api/Filters/ApiExceptionFilter.cs deleted file mode 100644 index 0c0e96f5..00000000 --- a/zero.Api/Filters/ApiExceptionFilter.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace zero.Api.Filters; - -public class ApiExceptionFilter : IExceptionFilter -{ - readonly IHostEnvironment _hostEnvironment; - readonly ILogger _logger; - - public ApiExceptionFilter(IHostEnvironment hostEnvironment, ILogger logger) - { - _hostEnvironment = hostEnvironment; - _logger = logger; - } - - public void OnException(ExceptionContext context) - { - _logger.LogError(context.Exception, "API Exception thrown at '{path}'", context.HttpContext.Request.GetEncodedPathAndQuery()); - - JsonResult result = new(new ErrorApiResponse() - { - Success = false, - Status = StatusCodes.Status500InternalServerError, - Metadata = GetMetadata(context), - Errors = new() - { - new ErrorApiResponseError() - { - Code = ApiErrorCodes.Server.Exception, - Category = ApiErrorCodes.Categories.Server, - Message = context.Exception.Message - } - } - //Content = context.Exception.ToString() - }); - - result.StatusCode = StatusCodes.Status500InternalServerError; - context.HttpContext.Response.Headers["X-Variant"] = "api-response"; - - context.Result = result; - } - - - ApiResponseMetadata GetMetadata(ExceptionContext context) - { - DateTimeOffset started = (DateTimeOffset)context.HttpContext.Items["zero.action.started"]; - TimeSpan duration = DateTimeOffset.Now - started; - - return new() - { - Duration = duration, - RequestDate = started - }; - } -} \ No newline at end of file diff --git a/zero.Api/Filters/ApiMetadataFilter.cs b/zero.Api/Filters/ApiMetadataFilter.cs deleted file mode 100644 index ad3981ac..00000000 --- a/zero.Api/Filters/ApiMetadataFilter.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.AspNetCore.Mvc.Filters; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace zero.Api.Filters; - -public class ApiMetadataFilterAttribute : ActionFilterAttribute -{ - public override void OnActionExecuting(ActionExecutingContext context) - { - context.HttpContext.Items["zero.action.started"] = DateTimeOffset.Now; - } -} \ No newline at end of file diff --git a/zero.Api/Filters/ApiResponseFilter.cs b/zero.Api/Filters/ApiResponseFilter.cs deleted file mode 100644 index 7a790ac0..00000000 --- a/zero.Api/Filters/ApiResponseFilter.cs +++ /dev/null @@ -1,190 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; - -namespace zero.Api.Filters; - -public class ApiResponseFilterAttribute : ResultFilterAttribute -{ - public override void OnResultExecuting(ResultExecutingContext context) - { - if (context.Result is ObjectResult result) - { - // format paged results - if (result.Value is Paged paged) - { - result.Value = new PagedDataApiResponse() - { - Success = true, - Status = result.StatusCode.Value, - Paging = new() - { - Page = paged.Page, - PageSize = paged.PageSize, - TotalPages = paged.TotalPages, - TotalItems = paged.TotalItems - }, - Properties = paged.Properties, - Data = paged.GetItems() - }; - } - - // format patch results - else if (result.Value is Result model) - { - ApiResponse response = new DataApiResponse(); - - if (!model.IsSuccess) - { - response = new ErrorApiResponse() - { - Errors = model.Errors.Select(x => new ErrorApiResponseError() - { - Category = ApiErrorCodes.Categories.Validation, - Code = "// TODO", - Property = x.Property, - Message = x.Message - }).ToList() - }; - } - else if (context.HttpContext.Items.TryGetValue(ApiConstants.ChangeToken, out object tokenObj) && tokenObj is string token) - { - response = new TokenizedDataApiResponse() - { - Data = model.GetModel(), - ChangeToken = token - }; - } - else - { - response = new DataApiResponse() - { - Data = model.GetModel() - }; - } - - response.Success = model.IsSuccess; - response.Status = !model.IsSuccess ? StatusCodes.Status400BadRequest : result.StatusCode.Value; - - result.StatusCode = response.Status; - result.Value = response; - } - - // format bulk patch results - else if (result.Value is IEnumerable> list) - { - int countSucceeded = list.Count(x => x.IsSuccess); - int countFailed = list.Count() - countSucceeded; - - BulkOperationApiResponse response = countFailed > 0 ? new BulkOperationWithErrorsApiResponse() : new BulkOperationApiResponse(); - - response.CountSucceeded = countSucceeded; - response.CountFailed = countFailed; - - if (countFailed > 0 && response is BulkOperationWithErrorsApiResponse errorResponse) - { - errorResponse.Errors = list.Where(x => !x.IsSuccess).SelectMany(x => x.Errors.Select(e => new BulkOperationErrorApiResponseError() - { - AffectedId = x.Model, - Category = ApiErrorCodes.Categories.Validation, - Code = "// TODO", - Property = e.Property, - Message = e.Message - })).ToList(); - } - - response.Success = countSucceeded > 0; - response.Status = countSucceeded < 1 ? StatusCodes.Status400BadRequest : result.StatusCode.Value; - result.StatusCode = response.Status; - result.Value = response; - } - - // format model results - else - { - DataApiResponse response = new(); - - if (context.HttpContext.Items.TryGetValue(ApiConstants.ChangeToken, out object tokenObj) && tokenObj is string token) - { - response = new TokenizedDataApiResponse() { ChangeToken = token }; - } - - response.Success = result.StatusCode.Value >= 200 && result.StatusCode.Value <= 299; - response.Status = result.StatusCode.Value; - response.Data = result.Value; - result.Value = response; - } - - // append metadata - if (result.Value is ApiResponse apiResponse) - { - apiResponse.Metadata = GetMetadata(context); - context.HttpContext.Response.Headers["X-Variant"] = "api-response"; - } - } - } - - - ApiResponseMetadata GetMetadata(ResultExecutingContext context) - { - if (!context.HttpContext.Items.ContainsKey("zero.action.started")) - { - return new(); - } - - DateTimeOffset started = (DateTimeOffset)context.HttpContext.Items["zero.action.started"]; - TimeSpan duration = DateTimeOffset.Now - started; - - return new() - { - Duration = duration, - RequestDate = started - }; - } - - - //if (context.Result is ObjectResult result && result.StatusCode.HasValue) - //{ - // if (typeof(ZeroIdEntity).IsAssignableFrom(result.DeclaredType)) - // { - // result.Value = new ModelApiResponse() - // { - // Model = result.Value, - // Success = true, - // Status = result.StatusCode.Value, - // ChangeToken = context.HttpContext.Items[ApiConstants.ChangeToken] as string, - // Metadata = new ModelApiResponseMetadata() - // { - // RequestDate = started, - // Duration = duration, - // Token = IdGenerator.Create(32) - // } - // }; - // } - // else if (typeof(Paged).IsAssignableFrom(result.DeclaredType)) - // { - // Paged paged = result.Value as Paged; - // result.Value = new PagedApiResponse() - // { - // Items = paged.GetItems(), - // Paging = new() - // { - // Page = paged.Page, - // PageSize = paged.PageSize, - // TotalItems = paged.TotalItems, - // TotalPages = paged.TotalPages, - // HasMore = paged.HasMore - // }, - // Success = true, - // Status = result.StatusCode.Value, - // Metadata = new ModelApiResponseMetadata() - // { - // RequestDate = started, - // Duration = duration, - // Token = IdGenerator.Create(32) - // } - // }; - // } - //} -} \ No newline at end of file diff --git a/zero.Api/Filters/ApiUnhandledExceptionMiddleware.cs b/zero.Api/Filters/ApiUnhandledExceptionMiddleware.cs deleted file mode 100644 index 55b3c051..00000000 --- a/zero.Api/Filters/ApiUnhandledExceptionMiddleware.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.Extensions.Logging; - -namespace zero.Api.Filters; - -public class ApiUnhandledExceptionMiddleware : IMiddleware -{ - private readonly ILogger _logger; - - public ApiUnhandledExceptionMiddleware(ILogger logger) - { - _logger = logger; - } - - public async Task InvokeAsync(HttpContext context, RequestDelegate next) - { - try - { - await next(context); - } - catch (Exception e) - { - _logger.LogError(e, "API Exception thrown at '{path}'", context.Request.GetEncodedPathAndQuery()); - throw; - } - } -} \ No newline at end of file diff --git a/zero.Api/Filters/ApiUnhandledExceptionMiddlewareFilter.cs b/zero.Api/Filters/ApiUnhandledExceptionMiddlewareFilter.cs deleted file mode 100644 index fbb7fd85..00000000 --- a/zero.Api/Filters/ApiUnhandledExceptionMiddlewareFilter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Builder; - -namespace zero.Api.Filters; - -public class ApiUnhandledExceptionMiddlewareFilter -{ - public void Configure(IApplicationBuilder applicationBuilder) - { - applicationBuilder.UseMiddleware(); - } -} \ No newline at end of file diff --git a/zero.Api/Filters/DisableBrowserCacheFilter.cs b/zero.Api/Filters/DisableBrowserCacheFilter.cs deleted file mode 100644 index 59d640f8..00000000 --- a/zero.Api/Filters/DisableBrowserCacheFilter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Net.Http.Headers; - -namespace zero.Api.Controllers; - -/// -/// Ensures that the request is not cached by the browser -/// -public class DisableBrowserCacheFilterAttribute : ActionFilterAttribute -{ - public override void OnResultExecuting(ResultExecutingContext context) - { - base.OnResultExecuting(context); - - var httpResponse = context.HttpContext.Response; - - if (httpResponse.StatusCode != 200) return; - - httpResponse.GetTypedHeaders().CacheControl = - new CacheControlHeaderValue() - { - NoCache = true, - MaxAge = TimeSpan.Zero, - MustRevalidate = true, - NoStore = true - }; - - httpResponse.Headers[HeaderNames.LastModified] = DateTime.Now.ToString("R"); // Format RFC1123 - httpResponse.Headers[HeaderNames.Pragma] = "no-cache"; - httpResponse.Headers[HeaderNames.Expires] = new DateTime(1990, 1, 1, 0, 0, 0).ToString("R"); - } -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListQuery.cs b/zero.Api/Models/ListQuery/ListQuery.cs deleted file mode 100644 index d2d0fd5a..00000000 --- a/zero.Api/Models/ListQuery/ListQuery.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq.Expressions; - -namespace zero.Api.Models; - -public class ListQuery -{ - public ListQueryDisplayType DisplayType { get; set; } - - public string[] Ids { get; set; } = Array.Empty(); - - public string Search { get; set; } = null; - - public Expression> SearchSelector { get; set; } = null; - - public Expression>[] SearchSelectors { get; private set; } = new Expression>[0] { }; - - public Expression, IQueryable>> AdditionalQuery { get; set; } = null; - - public string OrderBy { get; set; } = "createdDate"; - - public ListQueryOrderType OrderType { get; set; } = ListQueryOrderType.String; - - public bool OrderIsDescending { get; set; } = true; - - public Func, IQueryable> OrderQuery = null; - - public int Page { get; set; } = 1; - - public int PageSize { get; set; } = 30; - - //public bool IncludeInactive { get; set; } = true; - - public void SearchFor(params Expression>[] selectors) - { - SearchSelectors = selectors; - } -} - - -public class ListQuery : ListQuery where TFilter : IListSpecificQuery -{ - public TFilter Filter { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListQueryDisplayType.cs b/zero.Api/Models/ListQuery/ListQueryDisplayType.cs deleted file mode 100644 index 349cf722..00000000 --- a/zero.Api/Models/ListQuery/ListQueryDisplayType.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace zero.Api.Models; - -public enum ListQueryDisplayType -{ - /// - /// Default output for listings - /// - Default = 0, - /// - /// Previews for collection pickers - /// - Preview = 1, - /// - /// Selection within a picker - /// - Picker = 2 -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListQueryExtensions.cs b/zero.Api/Models/ListQuery/ListQueryExtensions.cs deleted file mode 100644 index 985de8a1..00000000 --- a/zero.Api/Models/ListQuery/ListQueryExtensions.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Newtonsoft.Json; -using Raven.Client.Documents.Linq; -using Raven.Client.Documents.Session; - -namespace zero.Api.Models; - -public static class ListQueryExtensions -{ - public static ListQuery AsList(this string options) where TFilter : IListSpecificQuery - { - return JsonConvert.DeserializeObject>(options); - } - - public static ListQuery AsList(this string options) where T : IListSpecificQuery - { - return JsonConvert.DeserializeObject>(options); - } - - public static IQueryable Filter(this IQueryable source, ListQuery listQuery) where T : ZeroIdEntity - { - if (listQuery == null) - { - return source; - } - - Type collectionType = typeof(T); - Type zeroType = typeof(ZeroEntity); - bool isZeroType = zeroType.IsAssignableFrom(collectionType); - - IQueryable queryable = source; - - if (listQuery.AdditionalQuery != null) - { - queryable = listQuery.AdditionalQuery.Compile()(queryable); - } - - if (listQuery.Ids.Length > 0) - { - queryable = queryable.Where(x => x.Id.In(listQuery.Ids)); - } - - if (!listQuery.Search.IsNullOrEmpty() && listQuery.SearchSelectors.Length > 0) - { - foreach (var selector in listQuery.SearchSelectors) - { - queryable = queryable.SearchIf(selector, listQuery.Search, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And); - } - } - else if (!listQuery.Search.IsNullOrEmpty() && listQuery.SearchSelector != null) - { - queryable = queryable.SearchIf(listQuery.SearchSelector, listQuery.Search, "*", "*", Raven.Client.Documents.Queries.SearchOperator.And); - } - - if (listQuery.OrderQuery != null) - { - queryable = listQuery.OrderQuery(queryable); - } - else if (!listQuery.OrderBy.IsNullOrEmpty()) - { - queryable = queryable.OrderBy(listQuery.OrderBy, listQuery.OrderIsDescending, listQuery.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double); - } - else if (isZeroType) - { - queryable = queryable.OrderByDescending(x => (x as ZeroEntity).CreatedDate); - } - - return queryable; - } -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListQueryOrderType.cs b/zero.Api/Models/ListQuery/ListQueryOrderType.cs deleted file mode 100644 index b130ca1f..00000000 --- a/zero.Api/Models/ListQuery/ListQueryOrderType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace zero.Api.Models; - -public enum ListQueryOrderType -{ - String, - Number -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListQueryRange.cs b/zero.Api/Models/ListQuery/ListQueryRange.cs deleted file mode 100644 index d7d77125..00000000 --- a/zero.Api/Models/ListQuery/ListQueryRange.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace zero.Api.Models; - -public class ListQueryDateRange -{ - public DateTimeOffset? From { get; set; } - - public DateTimeOffset? To { get; set; } -} - -public class ListQueryRange -{ - public decimal? From { get; set; } - - public decimal? To { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/ListQuery/ListSpecificQuery.cs b/zero.Api/Models/ListQuery/ListSpecificQuery.cs deleted file mode 100644 index 935e28b6..00000000 --- a/zero.Api/Models/ListQuery/ListSpecificQuery.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace zero.Api.Models; - -public interface IListSpecificQuery { } - -public class EmptyListSpecificQuery : IListSpecificQuery { } \ No newline at end of file diff --git a/zero.Api/Models/ModelApiResponseMetadata.cs b/zero.Api/Models/ModelApiResponseMetadata.cs deleted file mode 100644 index d575dc4e..00000000 --- a/zero.Api/Models/ModelApiResponseMetadata.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace zero.Api.Models; - -public class ModelApiResponseMetadata : ApiResponseMetadata -{ - /// - /// Wehther this entity is application aware - /// - public bool IsAppAware { get; set; } - - /// - /// Whether this entity can be shared across applications (only for IsAppAware=true) - /// - public bool CanBeShared { get; set; } - - public bool IsShared { get; set; } - - /// - /// The change token maps to a database entity which holds ID and collection of the model to edit - /// If these values do not match the entity on save it is rejected - /// // TODO expiration expiry session.Advanced.GetMetadataFor(user)[Raven.Client.Constants.Documents.Metadata.Expires] = DateTime.UtcNow.AddMinutes(60); - /// - public string Token { get; set; } - - - /// - /// Whether an entity of this type can be created - /// - public bool CanCreate { get; set; } - - /// - /// Whether an entity of this type can be created in the shared app space - /// - public bool CanCreateShared { get; set; } - - /// - /// Whether this entity can be edited or only viewed - /// - public bool CanEdit { get; set; } - - /// - /// Whether this entity can be deleted - /// - public bool CanDelete { get; set; } -} diff --git a/zero.Api/Models/Responses/ApiResponse.cs b/zero.Api/Models/Responses/ApiResponse.cs deleted file mode 100644 index fb8a23c3..00000000 --- a/zero.Api/Models/Responses/ApiResponse.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace zero.Api.Models -{ - public class ApiResponse - { - [JsonPropertyOrder(-2)] - public bool Success { get; set; } - - [JsonPropertyOrder(-1)] - public int Status { get; set; } - - public ApiResponseMetadata Metadata { get; set; } = new(); - } -} diff --git a/zero.Api/Models/Responses/ApiResponseMetadata.cs b/zero.Api/Models/Responses/ApiResponseMetadata.cs deleted file mode 100644 index 492f79a8..00000000 --- a/zero.Api/Models/Responses/ApiResponseMetadata.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace zero.Api.Models; - -public class ApiResponseMetadata -{ - public DateTimeOffset RequestDate { get; set; } - - public TimeSpan Duration { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/Responses/BulkOperationApiResponse.cs b/zero.Api/Models/Responses/BulkOperationApiResponse.cs deleted file mode 100644 index 6cdb43f0..00000000 --- a/zero.Api/Models/Responses/BulkOperationApiResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace zero.Api.Models; - - -public class BulkOperationApiResponse : ApiResponse -{ - public int CountSucceeded { get; set; } - - public int CountFailed { get; set; } -} - -public class BulkOperationWithErrorsApiResponse : BulkOperationApiResponse -{ - public List Errors { get; set; } = new(); -} - -public class BulkOperationErrorApiResponseError : ErrorApiResponseError -{ - public string AffectedId { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/Responses/DataApiResponse.cs b/zero.Api/Models/Responses/DataApiResponse.cs deleted file mode 100644 index 37cfee6b..00000000 --- a/zero.Api/Models/Responses/DataApiResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Models; - -public class DataApiResponse : ApiResponse -{ - public object Data { get; set; } -} diff --git a/zero.Api/Models/Responses/ErrorApiResponse.cs b/zero.Api/Models/Responses/ErrorApiResponse.cs deleted file mode 100644 index 2bb36648..00000000 --- a/zero.Api/Models/Responses/ErrorApiResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace zero.Api.Models; - -public class ErrorApiResponse : ApiResponse -{ - public List Errors { get; set; } = new(); -} - -public class ErrorApiResponseError -{ - public string Code { get; set; } - - public string Category { get; set; } - - public string Message { get; set; } - - public string Property { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/Responses/PagedDataApiResponse.cs b/zero.Api/Models/Responses/PagedDataApiResponse.cs deleted file mode 100644 index dce68c15..00000000 --- a/zero.Api/Models/Responses/PagedDataApiResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace zero.Api.Models; - -public class PagedDataApiResponse : DataApiResponse -{ - public PagedDataApiResponsePaging Paging { get; set; } - - public Dictionary Properties { get; set; } = new(); -} - - -public class PagedDataApiResponsePaging -{ - public long Page { get; set; } - - public long PageSize { get; set; } - - public long TotalPages { get; set; } - - public long TotalItems { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/Responses/TokenizedDataApiResponse.cs b/zero.Api/Models/Responses/TokenizedDataApiResponse.cs deleted file mode 100644 index 749a4a7c..00000000 --- a/zero.Api/Models/Responses/TokenizedDataApiResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Api.Models; - -public class TokenizedDataApiResponse : DataApiResponse -{ - public string ChangeToken { get; set; } -} diff --git a/zero.Api/Models/Trees/TreeItem.cs b/zero.Api/Models/Trees/TreeItem.cs deleted file mode 100644 index 0cd3ae65..00000000 --- a/zero.Api/Models/Trees/TreeItem.cs +++ /dev/null @@ -1,77 +0,0 @@ -namespace zero.Api.Models; - -/// -/// Represents an item in a tree -/// -public class TreeItem -{ - /// - /// Id of the item - /// - public string Id { get; set; } - - /// - /// Parent id of the item - /// - public string ParentId { get; set; } - - /// - /// Sort order - /// - public uint Sort { get; set; } - - /// - /// Name of the item - /// - public string Name { get; set; } - - /// - /// Displays a description on hover - /// - public string Description { get; set; } - - /// - /// Icon to display alongside the name - /// - public string Icon { get; set; } - - /// - /// Whether this item is open in case it contains children - /// - public bool IsOpen { get; set; } - - /// - /// Displays a small icon (with hover text) next to the main item icon - /// - public TreeItemModifier? Modifier { get; set; } - - /// - /// Whether this item has children - /// - public bool HasChildren { get; set; } - - /// - /// Count of children - /// - public int ChildCount { get; set; } - - /// - /// Whether this item is published or not - /// - public bool IsInactive { get; set; } - - /// - /// Whether to display the item icon with a dashed line - /// - public bool IsDashed { get; set; } - - /// - /// Whether to show actions menu. This will only work when the onActionsRequested cb is implemented in the component - /// - public bool HasActions { get; set; } - - /// - /// Output an additional count value. - /// - public int? CountOutput { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/Trees/TreeItemModifier.cs b/zero.Api/Models/Trees/TreeItemModifier.cs deleted file mode 100644 index 6a142fdd..00000000 --- a/zero.Api/Models/Trees/TreeItemModifier.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace zero.Api.Models; - -/// -/// The modifier displays a small icon (with hover text) next to the main item icon -/// -public struct TreeItemModifier -{ - /// - /// Name of the modifier - /// - public string Name { get; set; } - - /// - /// Icon to display - /// - public string Icon { get; set; } - - public TreeItemModifier(string name, string icon) - { - Name = name; - Icon = icon; - } -} diff --git a/zero.Api/Models/_legacy/ActionCopyModel.cs b/zero.Api/Models/_legacy/ActionCopyModel.cs deleted file mode 100644 index 3fc60ffb..00000000 --- a/zero.Api/Models/_legacy/ActionCopyModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace zero.Web.Models -{ - public class ActionCopyModel - { - public string Id { get; set; } - - public string DestinationId { get; set; } - - public bool IncludeDescendants { get; set; } - } -} diff --git a/zero.Api/Models/_legacy/ListItemModel.cs b/zero.Api/Models/_legacy/ListItemModel.cs deleted file mode 100644 index b42a8ef7..00000000 --- a/zero.Api/Models/_legacy/ListItemModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -//using System; - -//namespace zero.Web.Models -//{ -// public class ListItemModel : ListModel -// { -// public string Name { get; set; } - -// public bool IsActive { get; set; } -// } -//} diff --git a/zero.Api/Models/_legacy/ListModel.cs b/zero.Api/Models/_legacy/ListModel.cs deleted file mode 100644 index 1c17e271..00000000 --- a/zero.Api/Models/_legacy/ListModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Web.Models -{ - public abstract class ListModel where T : ZeroIdEntity - { - /// - /// Id of the entity - /// - public string Id { get; set; } - } -} diff --git a/zero.Api/Models/_legacy/ObsoleteEditModel.cs b/zero.Api/Models/_legacy/ObsoleteEditModel.cs deleted file mode 100644 index eeac4280..00000000 --- a/zero.Api/Models/_legacy/ObsoleteEditModel.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; - -namespace zero.Web.Models -{ - public class EditModel : EditModel { } - - public class EditModel - { - /// - /// Model - /// - public T Entity { get; set; } - - /// - /// Meta data - /// - public EditMetaModel Meta { get; set; } = new EditMetaModel(); - } - - - public class EditMetaModel - { - /// - /// Whether an entity of this type can be created - /// - public bool CanCreate { get; set; } - - /// - /// Whether an entity of this type can be created in the shared app space - /// - public bool CanCreateShared { get; set; } - - /// - /// Whether this entity can be edited or only viewed - /// - public bool CanEdit { get; set; } - - /// - /// Whether this entity can be deleted - /// - public bool CanDelete { get; set; } - - /// - /// Wehther this entity is application aware - /// - public bool IsAppAware { get; set; } - - /// - /// Whether this entity can be shared across applications (only for IsAppAware=true) - /// - public bool CanBeShared { get; set; } - - public bool IsShared { get; set; } - - /// - /// The change token maps to a database entity which holds ID and collection of the model to edit - /// If these values do not match the entity on save it is rejected - /// // TODO expiration expiry session.Advanced.GetMetadataFor(user)[Raven.Client.Constants.Documents.Metadata.Expires] = DateTime.UtcNow.AddMinutes(60); - /// - public string Token { get; set; } - } - - - public abstract class ObsoleteEditModel - { - /// - /// Id of the entity - /// - public string Id { get; set; } - - /// - /// Whether this entity is active - /// - public bool IsActive { get; set; } - - /// - /// Whether this entity can be edited or only viewed - /// - public bool CanEdit { get; set; } - - /// - /// Date of creation - /// - public DateTimeOffset CreatedDate { get; set; } - - /// - /// Meta data for the entity - /// - public EditModelMeta Meta { get; set; } = new EditModelMeta(); - } - - - public class EditModelMeta - { - /// - /// The change token maps to a database entity which holds ID and collection of the model to edit - /// If these values do not match the entity on save it is rejected - /// // TODO expiration expiry session.Advanced.GetMetadataFor(user)[Raven.Client.Constants.Documents.Metadata.Expires] = DateTime.UtcNow.AddMinutes(60); - /// - public string Token { get; set; } - } -} diff --git a/zero.Api/Models/_legacy/PageEditModel.cs b/zero.Api/Models/_legacy/PageEditModel.cs deleted file mode 100644 index 0e52057e..00000000 --- a/zero.Api/Models/_legacy/PageEditModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -//using System.Collections.Generic; -//using zero.Core.Entities; - -//namespace zero.Web.Models -//{ -// public class PageEditModel : EditModel where T : Page -// { -// public PageType PageType { get; set; } - -// public Paged Revisions { get; set; } - -// public List Urls { get; set; } = new(); -// } -//} diff --git a/zero.Api/Models/_new/BasicModel.cs b/zero.Api/Models/_new/BasicModel.cs deleted file mode 100644 index 3e1742b2..00000000 --- a/zero.Api/Models/_new/BasicModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace zero.Api.Models; - -public abstract class BasicModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity -{ - /// - /// Full name of the entity - /// - public string Name { get; set; } - - /// - /// Alias (non-unique) which can be used in the frontend and URLs - /// - public string Alias { get; set; } - - /// - /// A key which can be used to query this entity in code - /// - public string Key { get; set; } - - /// - /// Whether the entity is visible in the frontend - /// - public bool IsActive { get; set; } - - /// - /// Date of creation - /// - public DateTimeOffset CreatedDate { get; set; } - - /// - /// Configured flavor of this entity - /// - public string Flavor { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/_new/DisplayModel.cs b/zero.Api/Models/_new/DisplayModel.cs deleted file mode 100644 index 57f8daae..00000000 --- a/zero.Api/Models/_new/DisplayModel.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace zero.Api.Models; - - -public abstract class DisplayModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity -{ - /// - /// Full name of the entity - /// - public string Name { get; set; } - - /// - /// Alias (non-unique) which can be used in the frontend and URLs - /// - public string Alias { get; set; } - - /// - /// A key which can be used to query this entity in code - /// - public string Key { get; set; } - - /// - /// Sort order - /// - public uint Sort { get; set; } - - /// - /// Whether the entity is visible in the frontend - /// - public bool IsActive { get; set; } - - /// - /// Unique hash for this entity (primarily used for routing) - /// - public string Hash { get; set; } - - /// - /// Backoffice user who last modified this content - /// - public string LastModifiedById { get; set; } - - /// - /// Date of last modification - /// - public DateTimeOffset LastModifiedDate { get; set; } - - /// - /// Backoffice user who created this content - /// - public string CreatedById { get; set; } - - /// - /// Date of creation - /// - public DateTimeOffset CreatedDate { get; set; } - - /// - /// Language of the entity - /// - public string LanguageId { get; set; } - - /// - /// Configured flavor of this entity - /// - public string Flavor { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/_new/PickerModel.cs b/zero.Api/Models/_new/PickerModel.cs deleted file mode 100644 index 85bb6611..00000000 --- a/zero.Api/Models/_new/PickerModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace zero.Api.Models; - -public class PickerModel -{ - public string Id { get; set; } - - public string Name { get; set; } - - public bool IsActive { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Models/_new/PickerPreviewModel.cs b/zero.Api/Models/_new/PickerPreviewModel.cs deleted file mode 100644 index 2ab20829..00000000 --- a/zero.Api/Models/_new/PickerPreviewModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace zero.Api.Models; - -public class PickerPreviewModel -{ - public string Id { get; set; } - - public string Icon { get; set; } - - public string Text { get; set; } - - public string Name { get; set; } - - //public static PickerPreviewModel NotFound(string id) => new() - //{ - // HasError = true, - // Icon = "fth-alert-circle color-red", - // Id = id, - // Name = "@errors.preview.notfound", - // Text = "@errors.preview.notfound_text" - //}; -} \ No newline at end of file diff --git a/zero.Api/Models/_new/SaveModel.cs b/zero.Api/Models/_new/SaveModel.cs deleted file mode 100644 index f0d27729..00000000 --- a/zero.Api/Models/_new/SaveModel.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace zero.Api.Models; - -public abstract class SaveModel : ZeroIdEntity, ISupportsFlavors where T : ZeroEntity -{ - /// - /// Full name of the entity - /// - public string Name { get; set; } - - /// - /// Alias (non-unique) which can be used in the frontend and URLs - /// - public string Alias { get; set; } - - /// - /// A key which can be used to query this entity in code - /// - public string Key { get; set; } - - /// - /// Sort order - /// - public uint Sort { get; set; } - - /// - /// Whether the entity is visible in the frontend - /// - public bool IsActive { get; set; } - - /// - /// Configured flavor of this entity - /// - public string Flavor { get; set; } -} \ No newline at end of file diff --git a/zero.Api/Plugin.cs b/zero.Api/Plugin.cs deleted file mode 100644 index 887343d1..00000000 --- a/zero.Api/Plugin.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace zero.Api; - -public class ZeroApiPlugin : ZeroPlugin -{ - internal Action PostConfigureServices = null; - - public ZeroApiPlugin() - { - Options.Name = "zero.Api"; - } - - - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.TryAddEnumerable(ServiceDescriptor.Transient, ZeroApiMvcOptions>()); - services.AddTransient(); - services.AddTransient(); - - services.ConfigureOptions(); - - ZeroModuleCollection modules = new(); - - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - modules.Add(); - - modules.ConfigureServices(services, configuration); - - PostConfigureServices?.Invoke(services, configuration); - } - - - public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) - { - string path = "/zero/api"; - - app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path), appScoped => - { - appScoped.UseEndpoints(endpoints => - { - //IZeroOptions options = app.ApplicationServices.GetService(); // TODO oO - // see https://our.umbraco.com/documentation/reference/routing/custom-routes#where-to-put-your-routing-logic - //string path = options.BackofficePath.EnsureStartsWith('/').TrimEnd('/'); - //endpoints.MapFallbackToController(path + "/{**path}", "Index", "ZeroIndex"); - - //endpoints.MapControllers(); - }); - }); - } - - - protected void ConfigureOptions(IWebHostEnvironment env) - { - //Map().Display((x, res, opts) => - //{ - // PageType pageType = opts.Pages.GetByAlias(x.PageTypeAlias); - // if (pageType != null) - // { - // res.Icon = pageType.Icon; - // } - // res.Url = "/pages/edit/" + x.Id; - //}); - //Map("fth-image"); - } -} \ No newline at end of file diff --git a/zero.Api/Usings.cs b/zero.Api/Usings.cs deleted file mode 100644 index 24620c38..00000000 --- a/zero.Api/Usings.cs +++ /dev/null @@ -1,35 +0,0 @@ - -global using System; -global using System.Collections.Generic; -global using System.Linq; -global using System.Threading; -global using System.Threading.Tasks; -global using System.Text.Json.Serialization; - -global using zero.Applications; -global using zero.Architecture; -global using zero.Stores; -global using zero.Configuration; -global using zero.Context; -global using zero.Extensions; -global using zero.FileStorage; -global using zero.Identity; -global using zero.Localization; -global using zero.Mapper; -global using zero.Mails; -global using zero.Media; -global using zero.Models; -global using zero.Pages; -global using zero.Persistence; -global using zero.Routing; -global using zero.Spaces; -global using zero.Utils; - -global using zero.Api.Configuration; -global using zero.Api.Controllers; -global using zero.Api.Models; -global using zero.Api.Endpoints; -global using zero.Api.Abstractions; -global using zero.Api.Attributes; -global using zero.Api.Extensions; -global using zero.Api.Filters; \ No newline at end of file diff --git a/zero.Api/ZeroApiControllerModelConvention.cs b/zero.Api/ZeroApiControllerModelConvention.cs deleted file mode 100644 index 5b3d053f..00000000 --- a/zero.Api/ZeroApiControllerModelConvention.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using System.Reflection; -using System.Text; - -namespace zero.Api.Controllers; - -public class ZeroApiControllerModelConvention : IControllerModelConvention -{ - protected Type BaseClassType { get; set; } = typeof(ZeroApiController); - - readonly AttributeRouteModel AppAwareRouteModel; - - readonly AttributeRouteModel AppUnawareRouteModel; - - readonly Type SystemApiType = typeof(ZeroSystemApiAttribute); - - readonly ApiParameterTransformer Transformer = new(); - - readonly bool RuntimeIsAppAware = false; - - - public ZeroApiControllerModelConvention(string path, bool isAppAware = false) - { - RuntimeIsAppAware = isAppAware; - AppAwareRouteModel = BuildRouteModel(path, true); - AppUnawareRouteModel = BuildRouteModel(path, false); - } - - - /// - /// Configure routing model for all backoffice controllers - /// - public virtual void Apply(ControllerModel controller) - { - bool hasAttributeRouteModels = controller.Selectors.Any(selector => selector.AttributeRouteModel != null); - - if (controller.ControllerType.IsSubclassOf(BaseClassType)) - { - bool isAppAware = RuntimeIsAppAware && controller.ControllerType.GetCustomAttribute(SystemApiType) == null; - - controller.Selectors[0].AttributeRouteModel = isAppAware ? AppAwareRouteModel : AppUnawareRouteModel; - controller.Filters.Add(new DisableBrowserCacheFilterAttribute()); - - foreach (var action in controller.Actions) - { - action.RouteParameterTransformer = Transformer; - } - } - } - - - protected virtual AttributeRouteModel BuildRouteModel(string pathSegment, bool appAware = false) - { - StringBuilder path = new(); - path.Append(pathSegment.EnsureSurroundedWith('/')); - - path.Append("{zero_app_key}/"); - // TODO add route constraint which only allows registered app-ids - // see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/ - - path.Append("[controller]"); - - return new AttributeRouteModel(new RouteAttribute(path.ToString())); - } -} \ No newline at end of file diff --git a/zero.Api/ZeroApiMvcOptions.cs b/zero.Api/ZeroApiMvcOptions.cs deleted file mode 100644 index 6bc1c811..00000000 --- a/zero.Api/ZeroApiMvcOptions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; - -namespace zero.Api; - -internal class ZeroApiMvcOptions : IConfigureOptions -{ - IZeroOptions Options { get; set; } - - public ZeroApiMvcOptions(IZeroOptions options) - { - Options = options; - } - - public void Configure(MvcOptions options) - { - options.Conventions.Add(new ZeroApiControllerModelConvention(Options.ZeroPath + "/api", isAppAware: Options.Applications.Count > 1)); - } -} \ No newline at end of file diff --git a/zero.Api/ZeroBuilderExtensions.cs b/zero.Api/ZeroBuilderExtensions.cs deleted file mode 100644 index ab078eb6..00000000 --- a/zero.Api/ZeroBuilderExtensions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace zero.Api; - -public static class ZeroBuilderExtensions -{ - public static ZeroBuilder AddApi(this ZeroBuilder builder) - { - return builder.AddPlugin(); - } -} \ No newline at end of file diff --git a/zero.Api/ZeroEnpointRouteBuilderExtensions.cs b/zero.Api/ZeroEnpointRouteBuilderExtensions.cs deleted file mode 100644 index cd2942bc..00000000 --- a/zero.Api/ZeroEnpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.AspNetCore.Builder; - -namespace zero.Backoffice; - -public static class ZeroEndpointRouteBuilderExtensions -{ - public static void MapZeroApi(this IZeroEndpointRouteBuilder endpoints, string path = "/zero/api") - { - endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "{**path}", "Index", "NotFoundZeroApi"); - //app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path + "/api"), app1 => - //{ - // app1.UseEndpoints(endpoints => - // { - // //IZeroOptions options = app.ApplicationServices.GetService(); // TODO oO - // // see https://our.umbraco.com/documentation/reference/routing/custom-routes#where-to-put-your-routing-logic - // //string path = options.BackofficePath.EnsureStartsWith('/').TrimEnd('/'); - // //endpoints.MapFallbackToController(path + "/{**path}", "Index", "ZeroIndex"); - - // //endpoints.MapControllers(); - // }); - //}); - } -} diff --git a/zero.Api/zero.Api.csproj b/zero.Api/zero.Api.csproj deleted file mode 100644 index 32be1e04..00000000 --- a/zero.Api/zero.Api.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - zero.Api - 0.1.0 - preview - net6.0 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/zero.Backoffice/Abstractions/ZeroBackofficeController.cs b/zero.Backoffice/Abstractions/ZeroBackofficeController.cs deleted file mode 100644 index eba76309..00000000 --- a/zero.Backoffice/Abstractions/ZeroBackofficeController.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using zero.Api.Filters; - -namespace zero.Backoffice.Abstractions; - -[ApiController] -[ZeroAuthorize] -[ApiMetadataFilter] -[ApiResponseFilter] -//[ServiceFilter(typeof(ModelStateValidationFilterAttribute))] -//[ServiceFilter(typeof(BackofficeFilterAttribute))] -public abstract class ZeroBackofficeController : ControllerBase -{ - IZeroMapper _mapper; - protected IZeroMapper Mapper => _mapper ?? (_mapper = HttpContext?.RequestServices?.GetService()); -} diff --git a/zero.Backoffice/BackofficeAssetFileSystem.cs b/zero.Backoffice/BackofficeAssetFileSystem.cs deleted file mode 100644 index c95279f4..00000000 --- a/zero.Backoffice/BackofficeAssetFileSystem.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace zero.Backoffice; - -public class BackofficeAssetFileSystem : PhysicalFileSystem, IBackofficeAssetFileSystem -{ - public BackofficeAssetFileSystem(string root) : base(root) { } -} - - -public interface IBackofficeAssetFileSystem : IFileSystem -{ -} \ No newline at end of file diff --git a/zero.Backoffice/BackofficeResourceFileSystem.cs b/zero.Backoffice/BackofficeResourceFileSystem.cs deleted file mode 100644 index 784a98d0..00000000 --- a/zero.Backoffice/BackofficeResourceFileSystem.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace zero.Backoffice; - -public class BackofficeResourceFileSystem : PhysicalFileSystem, IBackofficeResourceFileSystem -{ - public BackofficeResourceFileSystem(string root) : base(root) { } -} - - -public interface IBackofficeResourceFileSystem : IFileSystem -{ -} \ No newline at end of file diff --git a/zero.Backoffice/Configuration/BackofficeConstants.cs b/zero.Backoffice/Configuration/BackofficeConstants.cs deleted file mode 100644 index 06398391..00000000 --- a/zero.Backoffice/Configuration/BackofficeConstants.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace zero.Backoffice.Configuration; - -public static class BackofficeConstants -{ - public static class HttpErrors - { - public const string NoIdMatchOnUpdate = "The Id as part of the URL does not match the Id of the model"; - - public const string IdNotFound = "Could not find persisted model for the given Id"; - } -} \ No newline at end of file diff --git a/zero.Backoffice/Configuration/BackofficeIconSet.cs b/zero.Backoffice/Configuration/BackofficeIconSet.cs deleted file mode 100644 index 247491b2..00000000 --- a/zero.Backoffice/Configuration/BackofficeIconSet.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace zero.Backoffice.Configuration; - -/// -/// Define a backoffice icon set -/// -public class BackofficeIconSet -{ - /// - /// The alias for reference - /// - public string Alias { get; set; } - - /// - /// Name of the icon set - /// - public string Name { get; set; } - - /// - /// Optional symbol identifier prefix (by default the alias is used) - /// - public string Prefix { get; set; } - - /// - /// Path to the SVG sprite containing addressable symbols - /// - public string SpritePath { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Configuration/BackofficeOptions.cs b/zero.Backoffice/Configuration/BackofficeOptions.cs deleted file mode 100644 index 5eafc93c..00000000 --- a/zero.Backoffice/Configuration/BackofficeOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace zero.Backoffice.Configuration; - -public class BackofficeOptions -{ - /// - /// Public path to zero assets - /// - public string AssetPath { get; set; } - - /// - /// Paths in the backoffice which are not handled by zero - /// - public List ExcludedPaths { get; private set; } = new(); - - /// - /// Define icon sets which can be used in icon pickers (and also in backoffice rendering) - /// - public List IconSets { get; set; } = new(); - - /// - /// Authentication configuration for external services - /// - public ExternalServicesOptions ExternalServices { get; set; } = new(); - - /// - /// Options for configuring the vite development server - /// - public ZeroDevOptions DevServer { get; set; } = new(); - - /// - /// Default language ISO code - /// - public string DefaultLanguage { get; set; } - - /// - /// Language ISO codes which are supported by the zero backoffice - /// - public string[] SupportedLanguages { get; internal set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Configuration/ExternalServicesOptions.cs b/zero.Backoffice/Configuration/ExternalServicesOptions.cs deleted file mode 100644 index da5fc2d8..00000000 --- a/zero.Backoffice/Configuration/ExternalServicesOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace zero.Backoffice.Configuration; - -public class ExternalServicesOptions -{ - /// - /// Define a YouTube API Key so the zero videopicker can display previews - /// - public string YouTubeApiKey { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Controllers/ZeroIndexController.cs b/zero.Backoffice/Controllers/ZeroIndexController.cs deleted file mode 100644 index 3f20309f..00000000 --- a/zero.Backoffice/Controllers/ZeroIndexController.cs +++ /dev/null @@ -1,107 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Hosting; -using System.IO; -using System.Reflection; -using System.Text.Json; -using zero.Api.Controllers; -using zero.Backoffice.Services; - -namespace zero.Backoffice.Controllers; - -[ZeroAuthorize(false)] -[DisableBrowserCacheFilter] -public class ZeroIndexController : Controller -{ - IZeroOptions Options { get; set; } - IIconService IconRepository { get; set; } - IWebHostEnvironment Env { get; set; } - IBackofficeAssetFileSystem AssetFileSystem { get; set; } - - static string MetaInfoJson { get; set; } - - public ZeroIndexController(IZeroOptions options, IIconService iconRepository, IWebHostEnvironment env, IBackofficeAssetFileSystem assetFileSystem) - { - Options = options; - IconRepository = iconRepository; - Env = env; - AssetFileSystem = assetFileSystem; - } - - - public async Task Index() - { - if (Options.Version.IsNullOrEmpty()) - { - return RedirectToAction("ZeroBackoffice", "Setup"); - } - - - - //return View("~/Views/Zero/Index.cshtml", new ZeroBackofficeModel() - //{ - // Meta = GetMetaInfo() - //}); - - BackofficeOptions options = Options.For(); - - int port = options.DevServer.Port; - string domain = "http://localhost:" + port; - - MetaInfoJson ??= JsonSerializer.Serialize(GetMetaInfo()); - - Dictionary model = new() - { - { "top", String.Empty }, - { "bottom", String.Join(String.Empty, GetJsModules(domain, new[] { "/vite/client", "/app/app.ts" })) }, - { "svg", await IconRepository.GetCompiledSvg() }, - { "meta", MetaInfoJson } - }; - - if (!Env.IsDevelopment()) - { - string html = TokenReplacement.Apply(System.IO.File.ReadAllText(Path.Combine(Env.WebRootPath, "zero/index.html")), model); - return Content(html, "text/html"); - //string assetHash = options.AssetHash; - //string suffix = assetHash.HasValue() ? "?v=" + assetHash : String.Empty; - - //model["bottom"] = String.Empty; - //model["top"] = @$" - // - // - // - //"; - } - - string content = TokenReplacement.Apply(await LoadTemplate("zero.Backoffice.Resources.backoffice.tpl.html"), model); - return Content(content, "text/html"); - } - - - ZeroBackofficeMetaInfo GetMetaInfo() - { - Assembly assembly = Assembly.GetEntryAssembly(); - FileInfo assemblyFileInfo = new(assembly.Location); - - return new() - { - AppVersion = assembly.GetCustomAttribute().InformationalVersion, - ZeroVersion = Options.Version, - AppLastModifiedDate = assemblyFileInfo.LastWriteTime - }; - } - - - IEnumerable GetJsModules(string domain, string[] modules) - { - return modules.Select(path => $""); - } - - - async Task LoadTemplate(string resourceName) - { - using Stream stream = GetType().Assembly.GetManifestResourceStream(resourceName); - using StreamReader reader = new(stream); - return await reader.ReadToEndAsync(); - } -} \ No newline at end of file diff --git a/zero.Backoffice/Controllers/ZeroSetupController.cs b/zero.Backoffice/Controllers/ZeroSetupController.cs deleted file mode 100644 index e94f4dd2..00000000 --- a/zero.Backoffice/Controllers/ZeroSetupController.cs +++ /dev/null @@ -1,49 +0,0 @@ -//using Microsoft.AspNetCore.Hosting; -//using Microsoft.AspNetCore.Mvc; -//using zero.Setup; - -//namespace zero.Backoffice.Endpoints; - -//[ZeroAuthorize(false)] -//public class ZeroSetupController : Controller -//{ -// ISetupApi Api; -// IWebHostEnvironment Env; -// IZeroOptions Options; - - -// public ZeroSetupController(ISetupApi api, IWebHostEnvironment env, IZeroOptions options) -// { -// Api = api; -// Env = env; -// Options = options; -// } - - -// public IActionResult Index() -// { -// //if (!Options.ZeroVersion.IsNullOrEmpty()) -// //{ -// // return Redirect(Options.BackofficePath); -// //} - -// return View("/Views/Zero/Setup.cshtml"); -// } - - -// [HttpPost] -// public async Task Install([FromBody] SetupModel model) -// { -// model.ContentRootPath = Env.ContentRootPath; - -// Result result = await Api.Install(model); - -// if (result.IsSuccess) -// { -// return Json(result); -// } - -// object value = String.Join("\n\n", result.Errors.Select(error => error.Message + "\n(property: " + error.Property + ")")); -// return StatusCode(500, value); -// } -//} \ No newline at end of file diff --git a/zero.Backoffice/DevServer/EventedStreamReader.cs b/zero.Backoffice/DevServer/EventedStreamReader.cs deleted file mode 100644 index 55bdd8a5..00000000 --- a/zero.Backoffice/DevServer/EventedStreamReader.cs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) .NET Foundation Contributors. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -// Original Source: https://github.com/aspnet/JavaScriptServices - -using System.IO; -using System.Text; -using System.Text.RegularExpressions; - -namespace zero.Backoffice.DevServer; - -/// -/// Wraps a to expose an evented API, issuing notifications -/// when the stream emits partial lines, completed lines, or finally closes. -/// -internal class EventedStreamReader -{ - public delegate void OnReceivedChunkHandler(ArraySegment chunk); - public delegate void OnReceivedLineHandler(string line); - public delegate void OnStreamClosedHandler(); - - public event OnReceivedChunkHandler OnReceivedChunk; - public event OnReceivedLineHandler OnReceivedLine; - public event OnStreamClosedHandler OnStreamClosed; - - private readonly StreamReader _streamReader; - private readonly StringBuilder _linesBuffer; - - public EventedStreamReader(StreamReader streamReader) - { - _streamReader = streamReader ?? throw new ArgumentNullException(nameof(streamReader)); - _linesBuffer = new StringBuilder(); - Task.Factory.StartNew(Run); - } - - public Task WaitForMatch(Regex regex) - { - var tcs = new TaskCompletionSource(); - var completionLock = new object(); - - OnReceivedLineHandler onReceivedLineHandler = null; - OnStreamClosedHandler onStreamClosedHandler = null; - - void ResolveIfStillPending(Action applyResolution) - { - lock (completionLock) - { - if (!tcs.Task.IsCompleted) - { - OnReceivedLine -= onReceivedLineHandler; - OnStreamClosed -= onStreamClosedHandler; - applyResolution(); - } - } - } - - onReceivedLineHandler = line => - { - var match = regex.Match(line); - if (match.Success) - { - ResolveIfStillPending(() => tcs.SetResult(match)); - } - }; - - onStreamClosedHandler = () => - { - ResolveIfStillPending(() => tcs.SetException(new EndOfStreamException())); - }; - - OnReceivedLine += onReceivedLineHandler; - OnStreamClosed += onStreamClosedHandler; - - return tcs.Task; - } - - - public Task WaitForFinish() - { - var tcs = new TaskCompletionSource(); - var completionLock = new object(); - - OnStreamClosedHandler onStreamClosedHandler = null; - - void ResolveIfStillPending(Action applyResolution) - { - lock (completionLock) - { - if (!tcs.Task.IsCompleted) - { - OnStreamClosed -= onStreamClosedHandler; - applyResolution(); - } - } - } - - onStreamClosedHandler = () => - { - ResolveIfStillPending(() => tcs.SetResult()); - }; - - OnStreamClosed += onStreamClosedHandler; - - return tcs.Task; - } - - - private async Task Run() - { - var buf = new char[8 * 1024]; - while (true) - { - var chunkLength = await _streamReader.ReadAsync(buf, 0, buf.Length); - if (chunkLength == 0) - { - OnClosed(); - break; - } - - OnChunk(new ArraySegment(buf, 0, chunkLength)); - - int lineBreakPos = -1; - int startPos = 0; - - // get all the newlines - while ((lineBreakPos = Array.IndexOf(buf, '\n', startPos, chunkLength - startPos)) >= 0 && startPos < chunkLength) - { - var length = lineBreakPos - startPos; - _linesBuffer.Append(buf, startPos, length); - OnCompleteLine(_linesBuffer.ToString()); - _linesBuffer.Clear(); - startPos = lineBreakPos + 1; - } - - // get the rest - if (lineBreakPos < 0 && startPos < chunkLength) - { - _linesBuffer.Append(buf, startPos, chunkLength - startPos); - } - } - } - - private void OnChunk(ArraySegment chunk) - { - var dlg = OnReceivedChunk; - dlg?.Invoke(chunk); - } - - private void OnCompleteLine(string line) - { - var dlg = OnReceivedLine; - dlg?.Invoke(line); - } - - private void OnClosed() - { - var dlg = OnStreamClosed; - dlg?.Invoke(); - } -} - -/// -/// Captures the completed-line notifications from a , -/// combining the data into a single . -/// -internal class EventedStreamStringReader : IDisposable -{ - private EventedStreamReader _eventedStreamReader; - private bool _isDisposed; - private StringBuilder _stringBuilder = new StringBuilder(); - - public EventedStreamStringReader(EventedStreamReader eventedStreamReader) - { - _eventedStreamReader = eventedStreamReader - ?? throw new ArgumentNullException(nameof(eventedStreamReader)); - _eventedStreamReader.OnReceivedLine += OnReceivedLine; - } - - public string ReadAsString() => _stringBuilder.ToString(); - - private void OnReceivedLine(string line) => _stringBuilder.AppendLine(line); - - public void Dispose() - { - if (!_isDisposed) - { - _eventedStreamReader.OnReceivedLine -= OnReceivedLine; - _isDisposed = true; - } - } -} diff --git a/zero.Backoffice/DevServer/PidUtils.cs b/zero.Backoffice/DevServer/PidUtils.cs deleted file mode 100644 index 63db6caa..00000000 --- a/zero.Backoffice/DevServer/PidUtils.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; - -namespace zero.Backoffice.DevServer; - -public static class PidUtils -{ - const string ssPidRegex = @"(?:^|"",|"",pid=)(\d+)"; - const string portRegex = @"[^]*[.:](\\d+)$"; - - public static int GetPortPid(ushort port) - { - int pidOut = -1; - - int portColumn = 1; // windows - int pidColumn = 4; // windows - string pidRegex = null; - - List results = null; - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - results = RunProcessReturnOutputSplit("netstat", "-anv -p tcp"); - results.AddRange(RunProcessReturnOutputSplit("netstat", "-anv -p udp")); - portColumn = 3; - pidColumn = 8; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - results = RunProcessReturnOutputSplit("ss", "-tunlp"); - portColumn = 4; - pidColumn = 6; - pidRegex = ssPidRegex; - } - else - { - results = RunProcessReturnOutputSplit("netstat", "-ano"); - } - - - foreach (var line in results) - { - if (line.Length <= portColumn || line.Length <= pidColumn) continue; - try - { - // split lines to words - var portMatch = Regex.Match(line[portColumn], $"[.:]({port})"); - if (portMatch.Success) - { - int portValue = int.Parse(portMatch.Groups[1].Value); - - if (pidRegex == null) - { - pidOut = int.Parse(line[pidColumn]); - return pidOut; - } - else - { - var pidMatch = Regex.Match(line[pidColumn], pidRegex); - if (pidMatch.Success) - { - pidOut = int.Parse(pidMatch.Groups[1].Value); - } - } - } - } - catch (Exception) - { - // ignore line error - } - } - - return pidOut; - } - - private static List RunProcessReturnOutputSplit(string fileName, string arguments) - { - string result = RunProcessReturnOutput(fileName, arguments); - if (result == null) return new List(); - - string[] lines = result.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - var lineWords = new List(); - foreach (var line in lines) - { - lineWords.Add(line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); - } - return lineWords; - } - - private static string RunProcessReturnOutput(string fileName, string arguments) - { - Process process = null; - try - { - var si = new ProcessStartInfo(fileName, arguments) - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true - }; - - process = Process.Start(si); - var stdOutT = process.StandardOutput.ReadToEndAsync(); - var stdErrorT = process.StandardError.ReadToEndAsync(); - if (!process.WaitForExit(10000)) - { - try { process?.Kill(); } catch { } - } - - if (Task.WaitAll(new Task[] { stdOutT, stdErrorT }, 10000)) - { - // if success, return data - return (stdOutT.Result + Environment.NewLine + stdErrorT.Result).Trim(); - } - return null; - } - catch (Exception) - { - return null; - } - finally - { - process?.Close(); - } - } - - public static bool Kill(string process, bool ignoreCase = true, bool force = false, bool tree = true) - { - var args = new List(); - try - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - if (force) { args.Add("-9"); } - if (ignoreCase) { args.Add("-i"); } - args.Add(process); - RunProcessReturnOutput("pkill", string.Join(" ", args)); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - if (force) { args.Add("-9"); } - if (ignoreCase) { args.Add("-I"); } - args.Add(process); - RunProcessReturnOutput("killall", string.Join(" ", args)); - } - else - { - if (force) { args.Add("/f"); } - if (tree) { args.Add("/T"); } - args.Add("/im"); - args.Add(process); - return RunProcessReturnOutput("taskkill", string.Join(" ", args))?.StartsWith("SUCCESS") ?? false; - } - return true; - } - catch (Exception) - { - - } - return false; - } - - public static bool Kill(int pid, bool force = false, bool tree = true) - { - if (pid == -1) { return false; } - - var args = new List(); - try - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - if (force) { args.Add("-9"); } - args.Add(pid.ToString()); - RunProcessReturnOutput("kill", string.Join(" ", args)); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - if (force) { args.Add("-9"); } - args.Add(pid.ToString()); - RunProcessReturnOutput("kill", string.Join(" ", args)); - } - else - { - if (force) { args.Add("/f"); } - if (tree) { args.Add("/T"); } - args.Add("/PID"); - args.Add(pid.ToString()); - return RunProcessReturnOutput("taskkill", string.Join(" ", args))?.StartsWith("SUCCESS") ?? false; - } - return true; - } - catch (Exception) - { - } - return false; - } - - public static bool KillPort(ushort port, bool force = false, bool tree = true) => Kill(GetPortPid(port), force: force, tree: tree); - -} diff --git a/zero.Backoffice/DevServer/ProcessProxy.cs b/zero.Backoffice/DevServer/ProcessProxy.cs deleted file mode 100644 index 83b2d63b..00000000 --- a/zero.Backoffice/DevServer/ProcessProxy.cs +++ /dev/null @@ -1,248 +0,0 @@ -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; - -namespace zero.Backoffice.DevServer; - -public class ProcessProxy -{ - string workingDirectory = null; - string script = null; - Action onProcessConfigure = null; - Action captureLog = null; - bool isWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - Dictionary envVars = new(); - HashSet arguments = new(); - bool forwardLog = false; - - Process process = null; - EventedStreamReader stdOut = null; - EventedStreamReader stdErr = null; - - - - - public ProcessProxy(string workingDirectory, string script, bool forwardLog = false) - { - this.workingDirectory = workingDirectory; - this.script = script; - this.forwardLog = forwardLog; - } - - - /// - /// Adds an environment variable - /// - public ProcessProxy EnvVar(string key, string value) - { - envVars.Add(key, value); - return this; - } - - - /// - /// Adds an argument - /// - public ProcessProxy Argument(string argument) - { - arguments.Add(argument); - return this; - } - - - /// - /// Configures the process start info - /// - public ProcessProxy Configure(Action onProcessConfigure) - { - this.onProcessConfigure = onProcessConfigure; - return this; - } - - - /// - /// Capture the log instead of outputting it to the console - /// - public ProcessProxy Capture(Action action) - { - this.captureLog = action; - return this; - } - - - /// - /// Run the script and wait for completion. - /// This is only recommended for scripts which finish automatically and have no user interaction. - /// - public async Task ExecuteAsync(TimeSpan timeout = default) - { - StartProcess(); - - using var stdErrReader = new EventedStreamStringReader(stdErr); - try - { - // TODO implement timeout - // https://stackoverflow.com/questions/18760252/timeout-an-async-method-implemented-with-taskcompletionsource - await stdOut.WaitForFinish(); - } - catch (EndOfStreamException ex) - { - throw new InvalidOperationException($"The script '{script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex); - } - } - - - /// - /// Run the script and return as soon as a condition is met. - /// The script will not cancel and will continue to run as a sub-process as long as it does not auto-close. - /// - public async Task RunAsync(string startupCondition, TimeSpan startupTimeout = default) - { - StartProcess(); - - using var stdErrReader = new EventedStreamStringReader(stdErr); - try - { - await stdOut.WaitForMatch(new Regex(startupCondition, RegexOptions.IgnoreCase, startupTimeout == default ? TimeSpan.FromMinutes(5) : startupTimeout)); - } - catch (EndOfStreamException ex) - { - throw new InvalidOperationException($"The script '{script}' exited without indicating that the server was listening for requests.\nThe error output was: " + $"{stdErrReader.ReadAsString()}", ex); - } - } - - - public void Exit() - { - try { process?.Kill(); } catch { } - try { process?.WaitForExit(); } catch { } - - AppDomain.CurrentDomain.DomainUnload -= UnloadHandler; - AppDomain.CurrentDomain.ProcessExit -= UnloadHandler; - AppDomain.CurrentDomain.UnhandledException -= UnloadHandler; - } - - - /// - /// Run - /// - Process StartProcess() - { - string executable = script; - - StringBuilder command = new(); - command.Append(script); - command.Append(' '); - foreach (string arg in arguments) - { - command.Append(arg); - } - string argumentList = command.ToString(); - - if (isWindows) - { - argumentList = $"/c {argumentList}"; - executable = "cmd"; - } - - ProcessStartInfo startInfo = new(executable) - { - Arguments = argumentList, - UseShellExecute = false, - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - WorkingDirectory = workingDirectory - }; - - foreach (var envVar in envVars) - { - startInfo.Environment[envVar.Key] = envVar.Value; - } - - onProcessConfigure?.Invoke(startInfo); - - try - { - process = Process.Start(startInfo); - process.EnableRaisingEvents = true; - } - catch (Exception ex) - { - var message = $"Failed to start '{startInfo.FileName}'. To resolve this:.\n\n" - + $"[1] Ensure that '{startInfo.FileName}' is installed and can be found in one of the PATH directories.\n" - + $" Current PATH enviroment variable is: { Environment.GetEnvironmentVariable("PATH") }\n" - + " Make sure the executable is in one of those directories, or update your PATH.\n\n" - + "[2] See the InnerException for further details of the cause."; - throw new InvalidOperationException(message, ex); - } - - AttachLogger(); - - AppDomain.CurrentDomain.DomainUnload += UnloadHandler; - AppDomain.CurrentDomain.ProcessExit += UnloadHandler; - AppDomain.CurrentDomain.UnhandledException += UnloadHandler; - - return process; - } - - - void UnloadHandler(object sender, EventArgs e) - { - Exit(); - } - - - void AttachLogger(bool isStream = false) - { - stdOut = new EventedStreamReader(process.StandardOutput); - stdErr = new EventedStreamReader(process.StandardError); - - stdOut.OnReceivedLine += line => WriteToLog(line); - stdOut.OnReceivedChunk += chunk => WriteToLog(chunk); - stdErr.OnReceivedLine += line => WriteToLog(line, true); - stdErr.OnReceivedChunk += chunk => WriteToLog(chunk, true); - } - - - void WriteToLog(string line, bool isError = false) - { - if (String.IsNullOrWhiteSpace(line)) - { - return; - } - - line = line.StartsWith("") ? line.Substring(3) : line; - - if (captureLog != null) - { - captureLog(line, isError); - } - if (forwardLog) - { - (isError ? Console.Error : Console.Out).WriteLine(line); - } - } - - - void WriteToLog(ArraySegment chunk, bool isError = false) - { - bool containsNewline = Array.IndexOf(chunk.Array, '\n', chunk.Offset, chunk.Count) >= 0; - - if (containsNewline) - { - return; - } - - if (captureLog != null) - { - captureLog(new String(chunk.Array, chunk.Offset, chunk.Count), isError); - } - if (forwardLog) - { - (isError ? Console.Error : Console.Out).Write(chunk.Array, chunk.Offset, chunk.Count); - } - } -} diff --git a/zero.Backoffice/DevServer/ZeroDevOptions.cs b/zero.Backoffice/DevServer/ZeroDevOptions.cs deleted file mode 100644 index 79a55436..00000000 --- a/zero.Backoffice/DevServer/ZeroDevOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace zero.Backoffice.DevServer; - -public class ZeroDevOptions -{ - public int Port { get; set; } = 3399; - - public bool ForwardLog { get; set; } = false; - - public string WorkingDirectory { get; set; } - - public bool Enabled { get; set; } = true; -} diff --git a/zero.Backoffice/DevServer/ZeroDevService.cs b/zero.Backoffice/DevServer/ZeroDevService.cs deleted file mode 100644 index 45d4cf50..00000000 --- a/zero.Backoffice/DevServer/ZeroDevService.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; - -namespace zero.Backoffice.DevServer; - -public class ZeroDevService : IHostedService -{ - IWebHostEnvironment env; - IOptions options; - ProcessProxy viteProcess; - ILogger logger; - IEnumerable plugins; - string workingDirectory; - bool isRunning = false; - - - public ZeroDevService(IWebHostEnvironment env, IOptions options, ILogger logger, IEnumerable plugins) - { - //foreach (IZeroPlugin plugin in plugins) - //{ - // string location = Assembly.GetAssembly(plugin.GetType()). ; - //} - this.plugins = plugins; - this.env = env; - this.options = options; - this.workingDirectory = options.Value.WorkingDirectory; - this.logger = logger; - } - - - public async Task StartAsync(CancellationToken cancellationToken) - { - // this is a development-time service, - // therefore no way to enable it in production - if (!env.IsDevelopment() || !options.Value.Enabled) - { - return; - } - - // locate npm version and throw if it is not installed - Version npmVersion = await FindNpmVersion(); - - if (npmVersion == null) - { - throw new Exception("Please install node+npm to use the zero dev service (https://www.npmjs.com/)"); - } - - // start vite server - viteProcess = await StartDevServer(options.Value.Port); - logger.LogInformation("vite listening on: http://localhost:{port}", options.Value.Port); - } - - public Task StopAsync(CancellationToken cancellationToken) - { - return Task.CompletedTask; - } - - - /// - /// Get the node version from the system - /// - async Task FindNpmVersion() - { - Version version = null; - - ProcessProxy process = new ProcessProxy(workingDirectory, "npm").Argument("-v").Capture((value, err) => - { - if (version == null && !value.Contains("not recognized") && Version.TryParse(value, out Version _version)) - { - version = _version; - } - }); - - await process.ExecuteAsync(); - - return version; - } - - - /// - /// Starts the vite dev server which also support HMR - /// - async Task StartDevServer(int port) - { - // if the port we want to use is occupied, terminate the process utilizing that port. - // this occurs when "stop" is used from the debugger and the middleware does not have the opportunity to kill the process - PidUtils.KillPort((ushort)port, true); - - // get all plugins which need to be passed to vite - List plugins = new(); - - foreach (var plugin in this.plugins) - { - if (!String.IsNullOrEmpty(plugin.Options.PluginPath)) - { - plugins.Add(plugin.Options.PluginPath); - } - } - - // create and run the vite script - ProcessProxy process = new ProcessProxy(workingDirectory, "npm", options.Value.ForwardLog) - .Argument("run dev") - .EnvVar("PORT", port.ToString()) - .EnvVar("ZERO_PLUGINS", JsonConvert.SerializeObject(plugins)) - .Capture(CaptureLog); - - await process.RunAsync("localhost:", TimeSpan.FromMinutes(1)); - - isRunning = true; - - return process; - } - - - void CaptureLog(string line, bool isError) - { - if (!isRunning) - { - return; - } - - if (isError) - { - logger.LogWarning(line); - } - else - { - logger.LogInformation(line); - } - } -} diff --git a/zero.Backoffice/Endpoints/Account/AccountController.cs b/zero.Backoffice/Endpoints/Account/AccountController.cs deleted file mode 100644 index 5d4b08f0..00000000 --- a/zero.Backoffice/Endpoints/Account/AccountController.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using zero.Api.Filters; -using zero.Identity.Models; - -namespace zero.Backoffice.Endpoints.Account; - -[ZeroSystemApi] -public class AccountController : ZeroBackofficeController -{ - readonly IAuthenticationService AuthService; - - public AccountController(IAuthenticationService authService) - { - AuthService = authService; - } - - - [HttpGet("user")] - public async Task> GetUser() - { - ZeroUser user = await AuthService.GetUser(); - - if (user == null) - { - return Unauthorized(); - } - - return Mapper.Map(user); - } - - - [HttpGet("loggedin")] - [ZeroAuthorize(false)] - public ActionResult LoggedIn() => new LoggedInResponseModel() { LoggedIn = AuthService.IsLoggedIn() }; - - - [HttpPost("login")] - [ZeroAuthorize(false)] - //[ValidateAntiForgeryToken] - public async Task> Login(LoginModel model) - { - LoginResult result = await AuthService.Login(model.Email, model.Password, model.IsPersistent); - - if (result != LoginResult.Success) - { - return Result.Fail(result.ToString()); - } - - ZeroUser user = await AuthService.GetUser(); - - return Result.Success(new() - { - User = Mapper.Map(user), - ApiKey = "myapikey" - }); - } - - - [HttpPost("logout")] - public async Task Logout() - { - await AuthService.Logout(); - return Ok(); - } - - - //[HttpPost, ZeroAuthorize] - //public async Task SwitchApp(string appId) - //{ - // return Result.Maybe(await Api.TrySwitchApp(appId)); - //} -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Account/AccountMapperProfile.cs b/zero.Backoffice/Endpoints/Account/AccountMapperProfile.cs deleted file mode 100644 index dd3801fc..00000000 --- a/zero.Backoffice/Endpoints/Account/AccountMapperProfile.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace zero.Backoffice.Endpoints.Account; - -public class AccountMapperProfile : ZeroMapperProfile -{ - public override void Configure(IZeroMapper mapper) - { - mapper.Define((source, ctx) => new(), Map); - } - - - protected virtual void Map(ZeroUser source, UserModel target, IZeroMapperContext ctx) - { - target.Id = source.Id; - target.CurrentAppId = source.CurrentAppId; - target.IsSuper = source.IsSuper; - target.IsActive = source.IsActive; - target.AvatarId = source.AvatarId; - target.Name = source.Name; - target.Email = source.Email; - target.CreatedDate = source.CreatedDate; - target.Flavor = source.Flavor; - target.Culture = source.LanguageId; - } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Account/Models/LoggedInResponseModel.cs b/zero.Backoffice/Endpoints/Account/Models/LoggedInResponseModel.cs deleted file mode 100644 index 1134e38b..00000000 --- a/zero.Backoffice/Endpoints/Account/Models/LoggedInResponseModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace zero.Backoffice.Endpoints.Account; - -public class LoggedInResponseModel -{ - public bool LoggedIn { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Account/Models/LoginModel.cs b/zero.Backoffice/Endpoints/Account/Models/LoginModel.cs deleted file mode 100644 index 567612b4..00000000 --- a/zero.Backoffice/Endpoints/Account/Models/LoginModel.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace zero.Backoffice.Endpoints.Account; - -public class LoginModel -{ - [Required, EmailAddress] - public string Email { get; set; } - - [Required] - public string Password { get; set; } - - public bool IsPersistent { get; set; } = true; -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Account/Models/LoginSuccessModel.cs b/zero.Backoffice/Endpoints/Account/Models/LoginSuccessModel.cs deleted file mode 100644 index 1cf945fa..00000000 --- a/zero.Backoffice/Endpoints/Account/Models/LoginSuccessModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace zero.Backoffice.Endpoints.Account; - -public class LoginSuccessModel : LoginSuccessMinimalModel -{ - public UserModel User { get; set; } -} - -public class LoginSuccessMinimalModel -{ - public string ApiKey { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Account/Models/UserModel.cs b/zero.Backoffice/Endpoints/Account/Models/UserModel.cs deleted file mode 100644 index 449c4d75..00000000 --- a/zero.Backoffice/Endpoints/Account/Models/UserModel.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace zero.Backoffice.Endpoints.Account; - -public class UserModel : ZeroIdEntity -{ - public string CurrentAppId { get; set; } - - public bool IsSuper { get; set; } - - public string AvatarId { get; set; } - - public string Email { get; set; } - - public string Name { get; set; } - - public bool IsActive { get; set; } - - public DateTimeOffset CreatedDate { get; set; } - - public string Flavor { get; set; } - - public string Culture { get; set; } -} diff --git a/zero.Backoffice/Endpoints/Links/LinksController.cs b/zero.Backoffice/Endpoints/Links/LinksController.cs deleted file mode 100644 index afccfa76..00000000 --- a/zero.Backoffice/Endpoints/Links/LinksController.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.Backoffice.Endpoints.Links; - -public class LinksController : ZeroBackofficeController -{ - readonly IZeroStore Store; - readonly ILinks Links; - - public LinksController(IZeroStore store, ILinks links) - { - Store = store; - Links = links; - } - - [HttpPost("convert")] - //[ZeroAuthorize(CountryPermissions.Create)] - public async Task>> ConvertToLinks([FromBody] List links) - { - IZeroDocumentSession session = Store.Session(); - List previews = new(); - - foreach (Link link in links) - { - ILinkProvider provider = Links.GetProvider(link); - LinkPreview model = null; - - if (provider != null) - { - model = await provider.Preview(session, link); - } - - string id = link.Values.GetValueOrDefault("id"); - - previews.Add(model ?? new LinkPreview() - { - HasError = true, - Icon = "fth-alert-circle color-red", - Id = id.Or("tmp_" + IdGenerator.Create()), - Name = "@errors.preview.notfound", - Text = "@errors.preview.notfound_text" - }); - } - - return previews; - } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Media/MediaController.cs b/zero.Backoffice/Endpoints/Media/MediaController.cs deleted file mode 100644 index 93df5733..00000000 --- a/zero.Backoffice/Endpoints/Media/MediaController.cs +++ /dev/null @@ -1,85 +0,0 @@ -//using Microsoft.AspNetCore.Mvc; -//using Raven.Client.Documents; -//using zero.Api.Models; - -//namespace zero.Backoffice.Endpoints.Media; - -//public class MediaController : ZeroBackofficeController -//{ -// readonly IPagesStore Store; -// readonly IMediaTreeService PageTreeService; -// readonly IPageTypeService PageTypeService; -// readonly IRoutes Routes; - - -// public PagesController(IPagesStore store, IMediaTreeService pageTreeService, IPageTypeService pageTypeService, IRoutes routes) -// { -// Store = store; -// PageTreeService = pageTreeService; -// PageTypeService = pageTypeService; -// Routes = routes; -// } - - -// [HttpGet("{parentId}/children")] -// public async Task>> GetChildren(string parentId = null, string activeId = null, string search = null) -// { -// return await PageTreeService.GetChildren(parentId, activeId, search); -// } - - -// [HttpGet("{parentId}/dependencies")] -// //[ZeroAuthorize(MediaPermissions.Update)] -// public virtual async Task> GetDependencies(string parentId) -// { -// int descendantCount = await Store.Session.Query() -// .ProjectInto() -// .CountAsync(x => x.PathIds.Contains(parentId)); - -// return new -// { -// pages = descendantCount + 1 -// }; -// } - - -// [HttpGet("previews")] -// public async Task>> GetPreviews([FromQuery] List ids) -// { -// IEnumerable pageTypes = PageTypeService.GetAll(); -// Dictionary pages = await Store.Load(ids.ToArray()); -// Dictionary routes = await Routes.GetRoutes(pages.Where(x => x.Value != null).Select(x => x.Value).ToArray()); - -// List previews = new(); - -// foreach ((string id, Page page) in pages) -// { -// if (page != null) -// { -// routes.TryGetValue(page, out Route route); -// FlavorConfig pageType = PageTypeService.GetByAlias(page.Flavor); - -// previews.Add(new() -// { -// Name = page.Name, -// Text = route?.Url.Or("@page.picker.urlnotfound"), -// Id = page.Id, -// Icon = pageType?.Icon.Or("fth-folder") -// }); -// } -// else -// { -// previews.Add(new() -// { -// HasError = true, -// Icon = "fth-alert-circle color-red", -// Id = "tmp_" + IdGenerator.Create(), -// Name = "@errors.preview.notfound", -// Text = "@errors.preview.notfound_text" -// }); -// } -// } - -// return previews; -// } -//} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Media/MediaTreeService.cs b/zero.Backoffice/Endpoints/Media/MediaTreeService.cs deleted file mode 100644 index f6ae4a5d..00000000 --- a/zero.Backoffice/Endpoints/Media/MediaTreeService.cs +++ /dev/null @@ -1,155 +0,0 @@ -//using Raven.Client.Documents; -//using Raven.Client.Documents.Linq; -//using Raven.Client.Documents.Session; -//using zero.Api.Models; - -//namespace zero.Backoffice.Endpoints.Media; - -//public class MediaTreeService : IMediaTreeService -//{ -// protected IMediaStore Media { get; private set; } - -// protected IRoutes Routes { get; set; } - -// protected IPageTypeService PageTypes { get; set; } - - -// public MediaTreeService(IMediaStore pages, IPageTypeService pageTypes, IRoutes routes) -// { -// Media = pages; -// Routes = routes; -// PageTypes = pageTypes; -// } - - -// /// -// public async Task> GetChildren(string parentId = null, string activeId = null, string search = null) -// { -// if (parentId == "root") -// { -// parentId = null; -// } - -// List items = new(); -// string[] openIds = Array.Empty(); -// Paged pages = null; -// IList children = null; -// bool isSearch = !search.IsNullOrWhiteSpace(); - -// if (isSearch) -// { -// pages = await Media.Load(1, Int32.MaxValue, q => q.SearchIf(x => x.Name, search, "*").OrderBy(x => x.Sort, OrderingType.Long)); - -// var urls = await Routes.GetUrls(pages.Items.ToArray()); - -// foreach (Page page in pages.Items) -// { -// if (urls.TryGetValue(page, out string url)) -// { -// page.Url = url; -// } -// } -// } -// else -// { -// pages = await Media.Load(1, Int32.MaxValue, q => q -// .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) -// .OrderBy(x => x.Sort, OrderingType.Long)); - - -// // get hierarchy so we know if we should set the page to open -// if (!activeId.IsNullOrEmpty()) -// { -// zero_Pages_ByHierarchy.Result result = await Media.Session.Query() -// .ProjectInto() -// .Include(x => x.Path.Select(p => p.Id)) -// .FirstOrDefaultAsync(x => x.Id == activeId); - -// if (result != null) -// { -// openIds = result.Path.Select(x => x.Id).ToArray(); // .Union(new string[1] { activeId }) -// } -// } - - -// // get children for all pages -// string[] pageIds = pages.Items.Select(x => x.Id).ToArray(); - -// children = await Media.Session.Query() -// .ProjectInto() -// .Where(x => x.Id.In(pageIds)) -// .ToListAsync(); -// } - - -// // function to get modifier icon -// TreeItemModifier? GetModifier(Page page) -// { -// if (page.PublishDate > DateTimeOffset.Now || page.UnpublishDate > DateTimeOffset.Now) -// { -// return new TreeItemModifier("@page.schedule.scheduled", "fth-clock"); -// } -// if (!page.IsActive) -// { -// return new TreeItemModifier("@ui.inactive", "fth-minus-circle color-red"); -// } -// return null; -// } - - -// // build tree -// foreach (Page page in pages.Items) -// { -// FlavorConfig pageType = PageTypes.GetByAlias(page.Flavor); - -// if (pageType == null) -// { -// //continue; -// // TODO the page type does not exist anymore -// } - -// int childCount = isSearch ? 0 : children.Count(x => x.Id == page.Id); - -// items.Add(new TreeItem() -// { -// Id = page.Id, -// Name = page.Name, -// HasChildren = childCount > 0, -// ChildCount = childCount, -// ParentId = page.ParentId, -// Sort = page.Sort, -// Icon = pageType?.Icon ?? "fth-box", -// IsOpen = openIds.Contains(page.Id), -// IsInactive = !page.IsActive, -// HasActions = true, -// Modifier = GetModifier(page), -// Description = isSearch ? page.Url : null -// }); -// } - -// if (parentId.IsNullOrEmpty()) -// { -// items.Add(new TreeItem() -// { -// Id = "recyclebin", -// ParentId = null, -// Sort = 99999, -// Name = "@recyclebin.name", -// Icon = "fth-trash", -// HasChildren = false, -// HasActions = true -// }); -// } - -// return items; -// } -//} - - -//public interface IMediaTreeService -//{ -// /// -// /// Get page children as tree items -// /// -// Task> GetChildren(string parentId = null, string activeId = null, string search = null); -//} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Pages/PageTreeService.cs b/zero.Backoffice/Endpoints/Pages/PageTreeService.cs deleted file mode 100644 index 71d27644..00000000 --- a/zero.Backoffice/Endpoints/Pages/PageTreeService.cs +++ /dev/null @@ -1,155 +0,0 @@ -using Raven.Client.Documents; -using Raven.Client.Documents.Linq; -using Raven.Client.Documents.Session; -using zero.Api.Models; - -namespace zero.Backoffice.Endpoints.Pages; - -public class PageTreeService : IPageTreeService -{ - protected IPagesStore Pages { get; private set; } - - protected IRoutes Routes { get; set; } - - protected IPageTypeService PageTypes { get; set; } - - - public PageTreeService(IPagesStore pages, IPageTypeService pageTypes, IRoutes routes) - { - Pages = pages; - Routes = routes; - PageTypes = pageTypes; - } - - - /// - public async Task> GetChildren(string parentId = null, string activeId = null, string search = null) - { - if (parentId == "root") - { - parentId = null; - } - - List items = new(); - string[] openIds = Array.Empty(); - Paged pages = null; - IList children = null; - bool isSearch = !search.IsNullOrWhiteSpace(); - - if (isSearch) - { - pages = await Pages.Load(1, Int32.MaxValue, q => q.SearchIf(x => x.Name, search, "*").OrderBy(x => x.Sort, OrderingType.Long)); - - var urls = await Routes.GetUrls(pages.Items.ToArray()); - - foreach (Page page in pages.Items) - { - if (urls.TryGetValue(page, out string url)) - { - page.Url = url; - } - } - } - else - { - pages = await Pages.Load(1, Int32.MaxValue, q => q - .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) - .OrderBy(x => x.Sort, OrderingType.Long)); - - - // get hierarchy so we know if we should set the page to open - if (!activeId.IsNullOrEmpty()) - { - zero_Pages_ByHierarchy.Result result = await Pages.Session.Query() - .ProjectInto() - .Include(x => x.Path.Select(p => p.Id)) - .FirstOrDefaultAsync(x => x.Id == activeId); - - if (result != null) - { - openIds = result.Path.Select(x => x.Id).ToArray(); // .Union(new string[1] { activeId }) - } - } - - - // get children for all pages - string[] pageIds = pages.Items.Select(x => x.Id).ToArray(); - - children = await Pages.Session.Query() - .ProjectInto() - .Where(x => x.Id.In(pageIds)) - .ToListAsync(); - } - - - // function to get modifier icon - TreeItemModifier? GetModifier(Page page) - { - if (page.PublishDate > DateTimeOffset.Now || page.UnpublishDate > DateTimeOffset.Now) - { - return new TreeItemModifier("@page.schedule.scheduled", "fth-clock"); - } - if (!page.IsActive) - { - return new TreeItemModifier("@ui.inactive", "fth-minus-circle color-red"); - } - return null; - } - - - // build tree - foreach (Page page in pages.Items) - { - FlavorConfig pageType = PageTypes.GetByAlias(page.Flavor); - - if (pageType == null) - { - //continue; - // TODO the page type does not exist anymore - } - - int childCount = isSearch ? 0 : children.Count(x => x.Id == page.Id); - - items.Add(new TreeItem() - { - Id = page.Id, - Name = page.Name, - HasChildren = childCount > 0, - ChildCount = childCount, - ParentId = page.ParentId, - Sort = page.Sort, - Icon = pageType?.Icon ?? "fth-box", - IsOpen = openIds.Contains(page.Id), - IsInactive = !page.IsActive, - HasActions = true, - Modifier = GetModifier(page), - Description = isSearch ? page.Url : null - }); - } - - if (parentId.IsNullOrEmpty()) - { - items.Add(new TreeItem() - { - Id = "recyclebin", - ParentId = null, - Sort = 99999, - Name = "@recyclebin.name", - Icon = "fth-trash", - HasChildren = false, - HasActions = true - }); - } - - return items; - } -} - - -public interface IPageTreeService -{ - /// - /// Get page children as tree items - /// - Task> GetChildren(string parentId = null, string activeId = null, string search = null); -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Pages/PagesController.cs b/zero.Backoffice/Endpoints/Pages/PagesController.cs deleted file mode 100644 index 36bef3d0..00000000 --- a/zero.Backoffice/Endpoints/Pages/PagesController.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Raven.Client.Documents; -using zero.Api.Models; - -namespace zero.Backoffice.Endpoints.Pages; - -public class PagesController : ZeroBackofficeController -{ - readonly IPagesStore Store; - readonly IPageTreeService PageTreeService; - readonly IPageTypeService PageTypeService; - readonly IRoutes Routes; - - - public PagesController(IPagesStore store, IPageTreeService pageTreeService, IPageTypeService pageTypeService, IRoutes routes) - { - Store = store; - PageTreeService = pageTreeService; - PageTypeService = pageTypeService; - Routes = routes; - } - - - [HttpGet("{parentId}/children")] - public async Task>> GetChildren(string parentId = null, string activeId = null, string search = null) - { - return await PageTreeService.GetChildren(parentId, activeId, search); - } - - - [HttpGet("{parentId}/dependencies")] - //[ZeroAuthorize(MediaPermissions.Update)] - public virtual async Task> GetDependencies(string parentId) - { - int descendantCount = await Store.Session.Query() - .ProjectInto() - .CountAsync(x => x.PathIds.Contains(parentId)); - - return new - { - pages = descendantCount + 1 - }; - } - - - [HttpGet("previews")] - public async Task>> GetPreviews([FromQuery] List ids) - { - IEnumerable pageTypes = PageTypeService.GetAll(); - Dictionary pages = await Store.Load(ids.ToArray()); - Dictionary routes = await Routes.GetRoutes(pages.Where(x => x.Value != null).Select(x => x.Value).ToArray()); - - List previews = new(); - - foreach ((string id, Page page) in pages) - { - if (page != null) - { - routes.TryGetValue(page, out Route route); - FlavorConfig pageType = PageTypeService.GetByAlias(page.Flavor); - - previews.Add(new() - { - Name = page.Name, - Text = route?.Url.Or("@page.picker.urlnotfound"), - Id = page.Id, - Icon = pageType?.Icon.Or("fth-folder") - }); - } - else - { - previews.Add(new() - { - HasError = true, - Icon = "fth-alert-circle color-red", - Id = "tmp_" + IdGenerator.Create(), - Name = "@errors.preview.notfound", - Text = "@errors.preview.notfound_text" - }); - } - } - - return previews; - } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/Previews/PreviewController.cs b/zero.Backoffice/Endpoints/Previews/PreviewController.cs deleted file mode 100644 index 1811c983..00000000 --- a/zero.Backoffice/Endpoints/Previews/PreviewController.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System.Threading.Tasks; -using zero.Core.Api; -using zero.Core.Entities; -using zero.Web.Models; - -namespace zero.Web.Controllers -{ - public class PreviewController : BackofficeController - { - IPreviewApi Api; - - public PreviewController(IPreviewApi api) - { - Api = api; - } - - - public async Task> GetById([FromQuery] string id) => Edit(await Api.GetById(id)); - - - public async Task> Add([FromBody] ZeroEntity model) - { - Result preview = await Api.Add(model); - return Result.From(preview, preview.Model?.Id); - } - - - public async Task> Update([FromQuery] string id, [FromBody] ZeroEntity model) - { - Result preview = await Api.Update(id, model); - return Result.From(preview, id); - } - } -} diff --git a/zero.Backoffice/Endpoints/UI/PreviewRequestTokenModel.cs b/zero.Backoffice/Endpoints/UI/PreviewRequestTokenModel.cs deleted file mode 100644 index 9c585507..00000000 --- a/zero.Backoffice/Endpoints/UI/PreviewRequestTokenModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace zero.Backoffice.Endpoints.UI; - -public class PreviewRequestTokenModel -{ - public string Key { get; set; } - - public class Response - { - public string Token { get; set; } - - public string QueryParameter { get; set; } - } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/UI/UIController.cs b/zero.Backoffice/Endpoints/UI/UIController.cs deleted file mode 100644 index da4e4231..00000000 --- a/zero.Backoffice/Endpoints/UI/UIController.cs +++ /dev/null @@ -1,157 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Net.Http.Headers; -using System.Collections; -using System.IO; -using System.Net.Http; -using System.Reflection; -using zero.Backoffice.Services; -using zero.Preview; - -namespace zero.Backoffice.Endpoints.UI; - -public class UIController : ZeroBackofficeController -{ - readonly IIconService IconService; - readonly IResourceService ResourceService; - readonly ISectionService SectionService; - readonly IZeroOptions Options; - readonly IMediaManagement Media; - readonly ICultureService CultureService; - readonly IUserService UserService; - readonly IRequestUrlResolver RequestUrlResolver; - readonly IPreviewService PreviewService; - readonly IZeroContext ZeroContext; - readonly HttpClient HttpClient; - - public UIController(IUserService userService, IIconService iconService, IResourceService resourceService, ISectionService sectionService, IZeroOptions options, IMediaManagement media, - ICultureService cultureService, IRequestUrlResolver requestUrlResolver, IPreviewService previewService, IZeroContext zeroContext) - { - UserService = userService; - IconService = iconService; - ResourceService = resourceService; - SectionService = sectionService; - CultureService = cultureService; - Options = options; - Media = media; - RequestUrlResolver = requestUrlResolver; - PreviewService = previewService; - ZeroContext = zeroContext; - HttpClient = new HttpClient(); - } - - [HttpGet("sections")] - //[ZeroAuthorize(CountryPermissions.Create)] - public async Task> GetSections() => Ok(await SectionService.GetSections()); - - - [HttpGet("settingareas")] - public async Task> GetSettingGroups() => Ok(await SectionService.GetSettingsAreas()); - - - [HttpGet("iconsets")] - public async Task> GetIconSets() - { - return Ok(await IconService.GetSets()); - } - - - [HttpGet("translations")] - [ZeroAuthorize(false)] - public async Task>> GetTranslations() - { - ZeroUser user = await UserService.GetCurrentUser(); - string cultureCode = user?.LanguageId.Or("en-us"); - return Ok(await ResourceService.GetTranslations(cultureCode)); - } - - - [HttpGet("cultures")] - public ActionResult> GetCultures() - { - return Ok(CultureService.GetAllCultures(Options.For().SupportedLanguages)); - } - - - [HttpGet("flavors")] - public ActionResult> GetFlavors() - { - Dictionary result = new(); - - foreach ((Type type, FlavorProvider provider) in Options.For().Providers) - { - string key = type.GetCustomAttribute(true)?.Name ?? type.Name; - result[Safenames.Alias(key)] = provider; - } - - return result; - } - - - [HttpGet("blueprints")] - public ActionResult> GetBlueprints() - { - HashSet result = new(); - - foreach (Blueprint blueprint in Options.For()) - { - string key = blueprint.ContentType.GetCustomAttribute(true)?.Name ?? blueprint.Alias; - result.Add(Safenames.Alias(key)); - } - - return result; - } - - - [HttpPost("previews/token")] - public async Task> GetPreviewToken(PreviewRequestTokenModel model) - { - string token = await PreviewService.CreateAccessToken(model.Key, ZeroContext.BackofficeUser); - return new PreviewRequestTokenModel.Response() - { - Token = token, - QueryParameter = Options.For().QueryParameter - }; - } - - - [HttpGet("thumbnail/{id}-{size}.tmp")] - public async Task GetThumbnail(string id, string size) - { - Stream stream = null; - zero.Media.Media media = await Media.GetFile(id); - - if (media == null) - { - return NotFound(); - } - - try - { - stream = await Media.GetFileStream(media, size); - } - catch { } - - if (stream == null) - { - string fullPath = Media.GetPublicFilePath(media, size); - - if (RequestUrlResolver.IsAbsolute(fullPath)) - { - byte[] bytes = await HttpClient.GetByteArrayAsync(fullPath); - return File(bytes, "image/webp"); // TODO this is shit and should not be here in zero (only for CDN link) - } - - return Ok(); - } - - try - { - return File(stream, "image/jpeg", DateTimeOffset.Now, EntityTagHeaderValue.Any); // TODO we do not query for the content-type - } - catch (FileSystemException) - { - return Ok(); - } - } -} \ No newline at end of file diff --git a/zero.Backoffice/Endpoints/UI/UIViewModel.cs b/zero.Backoffice/Endpoints/UI/UIViewModel.cs deleted file mode 100644 index bf3d0023..00000000 --- a/zero.Backoffice/Endpoints/UI/UIViewModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -//using zero.Backoffice.Endpoints.Applications; - -//namespace zero.Backoffice.Endpoints.UI; - -//public class UIViewModel -//{ -// public List Groups { get; set; } - -// public List Applications { get; set; } -//} diff --git a/zero.Backoffice/Endpoints/_todo_CulturesController.cs b/zero.Backoffice/Endpoints/_todo_CulturesController.cs deleted file mode 100644 index 1587ab85..00000000 --- a/zero.Backoffice/Endpoints/_todo_CulturesController.cs +++ /dev/null @@ -1,34 +0,0 @@ -// TODO this is only for the backoffice -// not required for API - -//using Microsoft.AspNetCore.Mvc; - -//namespace zero.Api.Endpoints.Languages; - -//public class CulturesController : ZeroApiController -//{ -// protected ICultureService Service { get; set; } - -// protected IZeroOptions Options { get; set; } - - -// public CulturesController(ICultureService service, IZeroOptions options) -// { -// Service = service; -// Options = options; -// } - - -// [HttpGet("empty")] -// [ZeroAuthorize(LanguagePermissions.Create)] -// public List GetAllCultures() -// { -// return Service.GetAllCultures(); -// } - - -// public List GetSupportedCultures() -// { -// return Service.GetAllCultures(Options.For.SupportedLanguages); -// } -//} \ No newline at end of file diff --git a/zero.Backoffice/Extensions/ZeroBackofficeControllerExtensions.cs b/zero.Backoffice/Extensions/ZeroBackofficeControllerExtensions.cs deleted file mode 100644 index c6bdb686..00000000 --- a/zero.Backoffice/Extensions/ZeroBackofficeControllerExtensions.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.StaticFiles; -using System.IO; -using zero.Api.Abstractions; - -namespace zero.Backoffice.Extensions; - -public static class ZeroBackofficeControllerExtensions -{ - /// - /// Provides a file stream for download in the browser - /// - public static IActionResult DownloadFile(this ZeroApiController controller, Stream stream, string filename) - { - if (stream == null) - { - // TODO add success property + return error response - } - - if (filename.Contains("{date}")) - { - filename = filename.Replace("{date}", DateTimeOffset.Now.ToString("yyyy-MM-dd")); - } - - var provider = new FileExtensionContentTypeProvider(); - if (filename == null || !provider.TryGetContentType(Path.GetFileName(filename), out string contentType)) - { - contentType = "application/octet-stream"; - } - - controller.Response.Headers.Add("zero-filename", filename); - - return controller.File(stream, contentType, filename, true); - } - - - /// - /// Provides a file stream to the browser - /// - public static IActionResult File(this ZeroApiController controller, FileStorage.FileResult file) - { - if (file == null) - { - return controller.NotFound(); - } - - FileStream stream = System.IO.File.OpenRead(file.Path); - return controller.File(stream, file.ContentType, file.Filename); - } -} diff --git a/zero.Backoffice/Indexes/zero_RecycledEntities.cs b/zero.Backoffice/Indexes/zero_RecycledEntities.cs deleted file mode 100644 index 650a87f7..00000000 --- a/zero.Backoffice/Indexes/zero_RecycledEntities.cs +++ /dev/null @@ -1,18 +0,0 @@ -//using System.Linq; -//using zero.Core.Entities; - -//namespace zero.Core.Database.Indexes -//{ -// public class zero_RecycledEntities : ZeroIndex -// { -// protected override void Create() -// { -// Map = items => items.Select(item => new -// { -// Group = item.Group, -// OperationId = item.OperationId, -// CreatedDate = item.CreatedDate -// }); -// } -// } -//} diff --git a/zero.Backoffice/Plugin.cs b/zero.Backoffice/Plugin.cs deleted file mode 100644 index 14fe6b55..00000000 --- a/zero.Backoffice/Plugin.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; -using System.IO; -using zero.Backoffice.Endpoints.Account; -using zero.Backoffice.Endpoints.Pages; -using zero.Backoffice.Services; - -namespace zero.Backoffice; - -public class ZeroBackofficePlugin : ZeroPlugin -{ - internal Action PostConfigureServices = null; - - - public ZeroBackofficePlugin() - { - Options.Name = "zero.Backoffice"; - Options.LocalizationPaths.Add("Resources/Localization/zero.{lang}.json"); - } - - - public override void ConfigureServices(IServiceCollection services, IConfiguration configuration) - { - services.AddOptions().Bind(configuration.GetSection("Zero:Backoffice")).Configure(ConfigureOptions); - services.TryAddEnumerable(ServiceDescriptor.Transient, ZeroBackofficeMvcOptions>()); - services.AddHostedService(); - services.AddSingleton(); - services.AddScoped(); - - services.AddSingleton(); - services.AddSingleton(); - services.AddScoped(); - - services.AddSingleton(svc => - { - IOptions options = svc.GetRequiredService>(); - IWebHostEnvironment env = svc.GetRequiredService(); - return new(Path.Combine(env.WebRootPath, options.Value.AssetPath)); - }); - - services.AddSingleton(svc => - { - IOptions options = svc.GetRequiredService>(); - IWebHostEnvironment env = svc.GetRequiredService(); - return new(env.ContentRootPath); - }); - - services.AddZeroBackofficeUIComposition(); - - //services.AddTransient(); - //services.AddTransient(); - - //services.AddScoped(); - - - PostConfigureServices?.Invoke(services, configuration); - } - - - protected void ConfigureOptions(BackofficeOptions options, IWebHostEnvironment env) - { - options.ExcludedPaths.Add("resources"); - options.AssetPath = "zero/resources"; - - options.DevServer.WorkingDirectory = Path.Combine(env.ContentRootPath, "..", "Zero.Web.UI", "App"); - - options.IconSets.Add(new BackofficeIconSet() - { - Alias = "feather", - Name = "Feather", - SpritePath = "icons/feather.svg", - Prefix = "fth" - }); - - options.SupportedLanguages = new string[2] { "en-US", "de-DE" }; - options.DefaultLanguage = options.SupportedLanguages[0]; - } -} \ No newline at end of file diff --git a/zero.Backoffice/Resources/Countries/countries.de-de.json b/zero.Backoffice/Resources/Countries/countries.de-de.json deleted file mode 100644 index 78384674..00000000 --- a/zero.Backoffice/Resources/Countries/countries.de-de.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "AF": "Afghanistan", - "EG": "\u00c4gypten", - "AX": "\u00c5landinseln", - "AL": "Albanien", - "DZ": "Algerien", - "AS": "Amerikanisch-Samoa", - "VI": "Amerikanische Jungferninseln", - "UM": "Amerikanische \u00dcberseeinseln", - "AD": "Andorra", - "AO": "Angola", - "AI": "Anguilla", - "AQ": "Antarktis", - "AG": "Antigua und Barbuda", - "GQ": "\u00c4quatorialguinea", - "AR": "Argentinien", - "AM": "Armenien", - "AW": "Aruba", - "AC": "Ascension", - "AZ": "Aserbaidschan", - "ET": "\u00c4thiopien", - "AU": "Australien", - "BS": "Bahamas", - "BH": "Bahrain", - "BD": "Bangladesch", - "BB": "Barbados", - "BY": "Belarus", - "BE": "Belgien", - "BZ": "Belize", - "BJ": "Benin", - "BM": "Bermuda", - "BT": "Bhutan", - "BO": "Bolivien", - "BQ": "Bonaire, Sint Eustatius und Saba", - "BA": "Bosnien und Herzegowina", - "BW": "Botsuana", - "BR": "Brasilien", - "VG": "Britische Jungferninseln", - "IO": "Britisches Territorium im Indischen Ozean", - "BN": "Brunei Darussalam", - "BG": "Bulgarien", - "BF": "Burkina Faso", - "BI": "Burundi", - "CV": "Cabo Verde", - "EA": "Ceuta und Melilla", - "CL": "Chile", - "CN": "China", - "CK": "Cookinseln", - "CR": "Costa Rica", - "CI": "C\u00f4te d\u2019Ivoire", - "CW": "Cura\u00e7ao", - "DK": "D\u00e4nemark", - "DE": "Deutschland", - "DG": "Diego Garcia", - "DM": "Dominica", - "DO": "Dominikanische Republik", - "DJ": "Dschibuti", - "EC": "Ecuador", - "SV": "El Salvador", - "ER": "Eritrea", - "EE": "Estland", - "FK": "Falklandinseln", - "FO": "F\u00e4r\u00f6er", - "FJ": "Fidschi", - "FI": "Finnland", - "FR": "Frankreich", - "GF": "Franz\u00f6sisch-Guayana", - "PF": "Franz\u00f6sisch-Polynesien", - "TF": "Franz\u00f6sische S\u00fcd- und Antarktisgebiete", - "GA": "Gabun", - "GM": "Gambia", - "GE": "Georgien", - "GH": "Ghana", - "GI": "Gibraltar", - "GD": "Grenada", - "GR": "Griechenland", - "GL": "Gr\u00f6nland", - "GP": "Guadeloupe", - "GU": "Guam", - "GT": "Guatemala", - "GG": "Guernsey", - "GN": "Guinea", - "GW": "Guinea-Bissau", - "GY": "Guyana", - "HT": "Haiti", - "HN": "Honduras", - "IN": "Indien", - "ID": "Indonesien", - "IQ": "Irak", - "IR": "Iran", - "IE": "Irland", - "IS": "Island", - "IM": "Isle of Man", - "IL": "Israel", - "IT": "Italien", - "JM": "Jamaika", - "JP": "Japan", - "YE": "Jemen", - "JE": "Jersey", - "JO": "Jordanien", - "KY": "Kaimaninseln", - "KH": "Kambodscha", - "CM": "Kamerun", - "CA": "Kanada", - "IC": "Kanarische Inseln", - "KZ": "Kasachstan", - "QA": "Katar", - "KE": "Kenia", - "KG": "Kirgisistan", - "KI": "Kiribati", - "CC": "Kokosinseln", - "CO": "Kolumbien", - "KM": "Komoren", - "CG": "Kongo-Brazzaville", - "CD": "Kongo-Kinshasa", - "XK": "Kosovo", - "HR": "Kroatien", - "CU": "Kuba", - "KW": "Kuwait", - "LA": "Laos", - "LS": "Lesotho", - "LV": "Lettland", - "LB": "Libanon", - "LR": "Liberia", - "LY": "Libyen", - "LI": "Liechtenstein", - "LT": "Litauen", - "LU": "Luxemburg", - "MG": "Madagaskar", - "MW": "Malawi", - "MY": "Malaysia", - "MV": "Malediven", - "ML": "Mali", - "MT": "Malta", - "MA": "Marokko", - "MH": "Marshallinseln", - "MQ": "Martinique", - "MR": "Mauretanien", - "MU": "Mauritius", - "YT": "Mayotte", - "MX": "Mexiko", - "FM": "Mikronesien", - "MC": "Monaco", - "MN": "Mongolei", - "ME": "Montenegro", - "MS": "Montserrat", - "MZ": "Mosambik", - "MM": "Myanmar", - "NA": "Namibia", - "NR": "Nauru", - "NP": "Nepal", - "NC": "Neukaledonien", - "NZ": "Neuseeland", - "NI": "Nicaragua", - "NL": "Niederlande", - "NE": "Niger", - "NG": "Nigeria", - "NU": "Niue", - "KP": "Nordkorea", - "MP": "N\u00f6rdliche Marianen", - "MK": "Nordmazedonien", - "NF": "Norfolkinsel", - "NO": "Norwegen", - "OM": "Oman", - "AT": "\u00d6sterreich", - "PK": "Pakistan", - "PS": "Pal\u00e4stinensische Autonomiegebiete", - "PW": "Palau", - "PA": "Panama", - "PG": "Papua-Neuguinea", - "PY": "Paraguay", - "PE": "Peru", - "PH": "Philippinen", - "PN": "Pitcairninseln", - "PL": "Polen", - "PT": "Portugal", - "XA": "Pseudo-Accents", - "XB": "Pseudo-Bidi", - "PR": "Puerto Rico", - "MD": "Republik Moldau", - "RE": "R\u00e9union", - "RW": "Ruanda", - "RO": "Rum\u00e4nien", - "RU": "Russland", - "SB": "Salomonen", - "ZM": "Sambia", - "WS": "Samoa", - "SM": "San Marino", - "ST": "S\u00e3o Tom\u00e9 und Pr\u00edncipe", - "SA": "Saudi-Arabien", - "SE": "Schweden", - "CH": "Schweiz", - "SN": "Senegal", - "RS": "Serbien", - "SC": "Seychellen", - "SL": "Sierra Leone", - "ZW": "Simbabwe", - "SG": "Singapur", - "SX": "Sint Maarten", - "SK": "Slowakei", - "SI": "Slowenien", - "SO": "Somalia", - "HK": "Sonderverwaltungsregion Hongkong", - "MO": "Sonderverwaltungsregion Macau", - "ES": "Spanien", - "SJ": "Spitzbergen und Jan Mayen", - "LK": "Sri Lanka", - "BL": "St. Barth\u00e9lemy", - "SH": "St. Helena", - "KN": "St. Kitts und Nevis", - "LC": "St. Lucia", - "MF": "St. Martin", - "PM": "St. Pierre und Miquelon", - "VC": "St. Vincent und die Grenadinen", - "ZA": "S\u00fcdafrika", - "SD": "Sudan", - "GS": "S\u00fcdgeorgien und die S\u00fcdlichen Sandwichinseln", - "KR": "S\u00fcdkorea", - "SS": "S\u00fcdsudan", - "SR": "Suriname", - "SZ": "Swasiland", - "SY": "Syrien", - "TJ": "Tadschikistan", - "TW": "Taiwan", - "TZ": "Tansania", - "TH": "Thailand", - "TL": "Timor-Leste", - "TG": "Togo", - "TK": "Tokelau", - "TO": "Tonga", - "TT": "Trinidad und Tobago", - "TA": "Tristan da Cunha", - "TD": "Tschad", - "CZ": "Tschechien", - "TN": "Tunesien", - "TR": "T\u00fcrkei", - "TM": "Turkmenistan", - "TC": "Turks- und Caicosinseln", - "TV": "Tuvalu", - "UG": "Uganda", - "UA": "Ukraine", - "HU": "Ungarn", - "UY": "Uruguay", - "UZ": "Usbekistan", - "VU": "Vanuatu", - "VA": "Vatikanstadt", - "VE": "Venezuela", - "AE": "Vereinigte Arabische Emirate", - "US": "Vereinigte Staaten", - "GB": "Vereinigtes K\u00f6nigreich", - "VN": "Vietnam", - "WF": "Wallis und Futuna", - "CX": "Weihnachtsinsel", - "EH": "Westsahara", - "CF": "Zentralafrikanische Republik", - "CY": "Zypern" -} \ No newline at end of file diff --git a/zero.Backoffice/Resources/Countries/countries.en-us.json b/zero.Backoffice/Resources/Countries/countries.en-us.json deleted file mode 100644 index 81dd1733..00000000 --- a/zero.Backoffice/Resources/Countries/countries.en-us.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "AF": "Afghanistan", - "AX": "\u00c5land Islands", - "AL": "Albania", - "DZ": "Algeria", - "AS": "American Samoa", - "AD": "Andorra", - "AO": "Angola", - "AI": "Anguilla", - "AQ": "Antarctica", - "AG": "Antigua & Barbuda", - "AR": "Argentina", - "AM": "Armenia", - "AW": "Aruba", - "AC": "Ascension Island", - "AU": "Australia", - "AT": "Austria", - "AZ": "Azerbaijan", - "BS": "Bahamas", - "BH": "Bahrain", - "BD": "Bangladesh", - "BB": "Barbados", - "BY": "Belarus", - "BE": "Belgium", - "BZ": "Belize", - "BJ": "Benin", - "BM": "Bermuda", - "BT": "Bhutan", - "BO": "Bolivia", - "BA": "Bosnia & Herzegovina", - "BW": "Botswana", - "BR": "Brazil", - "IO": "British Indian Ocean Territory", - "VG": "British Virgin Islands", - "BN": "Brunei", - "BG": "Bulgaria", - "BF": "Burkina Faso", - "BI": "Burundi", - "KH": "Cambodia", - "CM": "Cameroon", - "CA": "Canada", - "IC": "Canary Islands", - "CV": "Cape Verde", - "BQ": "Caribbean Netherlands", - "KY": "Cayman Islands", - "CF": "Central African Republic", - "EA": "Ceuta & Melilla", - "TD": "Chad", - "CL": "Chile", - "CN": "China", - "CX": "Christmas Island", - "CC": "Cocos (Keeling) Islands", - "CO": "Colombia", - "KM": "Comoros", - "CG": "Congo - Brazzaville", - "CD": "Congo - Kinshasa", - "CK": "Cook Islands", - "CR": "Costa Rica", - "CI": "C\u00f4te d\u2019Ivoire", - "HR": "Croatia", - "CU": "Cuba", - "CW": "Cura\u00e7ao", - "CY": "Cyprus", - "CZ": "Czechia", - "DK": "Denmark", - "DG": "Diego Garcia", - "DJ": "Djibouti", - "DM": "Dominica", - "DO": "Dominican Republic", - "EC": "Ecuador", - "EG": "Egypt", - "SV": "El Salvador", - "GQ": "Equatorial Guinea", - "ER": "Eritrea", - "EE": "Estonia", - "SZ": "Eswatini", - "ET": "Ethiopia", - "FK": "Falkland Islands", - "FO": "Faroe Islands", - "FJ": "Fiji", - "FI": "Finland", - "FR": "France", - "GF": "French Guiana", - "PF": "French Polynesia", - "TF": "French Southern Territories", - "GA": "Gabon", - "GM": "Gambia", - "GE": "Georgia", - "DE": "Germany", - "GH": "Ghana", - "GI": "Gibraltar", - "GR": "Greece", - "GL": "Greenland", - "GD": "Grenada", - "GP": "Guadeloupe", - "GU": "Guam", - "GT": "Guatemala", - "GG": "Guernsey", - "GN": "Guinea", - "GW": "Guinea-Bissau", - "GY": "Guyana", - "HT": "Haiti", - "HN": "Honduras", - "HK": "Hong Kong SAR China", - "HU": "Hungary", - "IS": "Iceland", - "IN": "India", - "ID": "Indonesia", - "IR": "Iran", - "IQ": "Iraq", - "IE": "Ireland", - "IM": "Isle of Man", - "IL": "Israel", - "IT": "Italy", - "JM": "Jamaica", - "JP": "Japan", - "JE": "Jersey", - "JO": "Jordan", - "KZ": "Kazakhstan", - "KE": "Kenya", - "KI": "Kiribati", - "XK": "Kosovo", - "KW": "Kuwait", - "KG": "Kyrgyzstan", - "LA": "Laos", - "LV": "Latvia", - "LB": "Lebanon", - "LS": "Lesotho", - "LR": "Liberia", - "LY": "Libya", - "LI": "Liechtenstein", - "LT": "Lithuania", - "LU": "Luxembourg", - "MO": "Macao SAR China", - "MG": "Madagascar", - "MW": "Malawi", - "MY": "Malaysia", - "MV": "Maldives", - "ML": "Mali", - "MT": "Malta", - "MH": "Marshall Islands", - "MQ": "Martinique", - "MR": "Mauritania", - "MU": "Mauritius", - "YT": "Mayotte", - "MX": "Mexico", - "FM": "Micronesia", - "MD": "Moldova", - "MC": "Monaco", - "MN": "Mongolia", - "ME": "Montenegro", - "MS": "Montserrat", - "MA": "Morocco", - "MZ": "Mozambique", - "MM": "Myanmar (Burma)", - "NA": "Namibia", - "NR": "Nauru", - "NP": "Nepal", - "NL": "Netherlands", - "NC": "New Caledonia", - "NZ": "New Zealand", - "NI": "Nicaragua", - "NE": "Niger", - "NG": "Nigeria", - "NU": "Niue", - "NF": "Norfolk Island", - "KP": "North Korea", - "MK": "North Macedonia", - "MP": "Northern Mariana Islands", - "NO": "Norway", - "OM": "Oman", - "PK": "Pakistan", - "PW": "Palau", - "PS": "Palestinian Territories", - "PA": "Panama", - "PG": "Papua New Guinea", - "PY": "Paraguay", - "PE": "Peru", - "PH": "Philippines", - "PN": "Pitcairn Islands", - "PL": "Poland", - "PT": "Portugal", - "XA": "Pseudo-Accents", - "XB": "Pseudo-Bidi", - "PR": "Puerto Rico", - "QA": "Qatar", - "RE": "R\u00e9union", - "RO": "Romania", - "RU": "Russia", - "RW": "Rwanda", - "WS": "Samoa", - "SM": "San Marino", - "ST": "S\u00e3o Tom\u00e9 & Pr\u00edncipe", - "SA": "Saudi Arabia", - "SN": "Senegal", - "RS": "Serbia", - "SC": "Seychelles", - "SL": "Sierra Leone", - "SG": "Singapore", - "SX": "Sint Maarten", - "SK": "Slovakia", - "SI": "Slovenia", - "SB": "Solomon Islands", - "SO": "Somalia", - "ZA": "South Africa", - "GS": "South Georgia & South Sandwich Islands", - "KR": "South Korea", - "SS": "South Sudan", - "ES": "Spain", - "LK": "Sri Lanka", - "BL": "St. Barth\u00e9lemy", - "SH": "St. Helena", - "KN": "St. Kitts & Nevis", - "LC": "St. Lucia", - "MF": "St. Martin", - "PM": "St. Pierre & Miquelon", - "VC": "St. Vincent & Grenadines", - "SD": "Sudan", - "SR": "Suriname", - "SJ": "Svalbard & Jan Mayen", - "SE": "Sweden", - "CH": "Switzerland", - "SY": "Syria", - "TW": "Taiwan", - "TJ": "Tajikistan", - "TZ": "Tanzania", - "TH": "Thailand", - "TL": "Timor-Leste", - "TG": "Togo", - "TK": "Tokelau", - "TO": "Tonga", - "TT": "Trinidad & Tobago", - "TA": "Tristan da Cunha", - "TN": "Tunisia", - "TR": "Turkey", - "TM": "Turkmenistan", - "TC": "Turks & Caicos Islands", - "TV": "Tuvalu", - "UM": "U.S. Outlying Islands", - "VI": "U.S. Virgin Islands", - "UG": "Uganda", - "UA": "Ukraine", - "AE": "United Arab Emirates", - "GB": "United Kingdom", - "US": "United States", - "UY": "Uruguay", - "UZ": "Uzbekistan", - "VU": "Vanuatu", - "VA": "Vatican City", - "VE": "Venezuela", - "VN": "Vietnam", - "WF": "Wallis & Futuna", - "EH": "Western Sahara", - "YE": "Yemen", - "ZM": "Zambia", - "ZW": "Zimbabwe" -} \ No newline at end of file diff --git a/zero.Backoffice/Resources/Localization/zero.de-de.json b/zero.Backoffice/Resources/Localization/zero.de-de.json deleted file mode 100644 index a4b68219..00000000 --- a/zero.Backoffice/Resources/Localization/zero.de-de.json +++ /dev/null @@ -1,834 +0,0 @@ -{ - "zero": { - "name": "zero", - "config": { - "linkareas": { - "pages": "Seiten", - "media": "Medien", - "url": "Url" - } - } - }, - "nav": { - "apps": { - "manage": "Apps verwalten" - }, - "account": { - "edit": "Profil ändern", - "changepassword": "Passwort ändern", - "logout": "Abmelden" - }, - "theme": { - "dark": "Dunkles Theme", - "light": "Helles Theme" - } - }, - "ui": { - "yes": "Ja", - "no": "Nein", - "required": "Erforderlich", - "more": "Mehr", - "add": "Hinzufügen", - "actions": "Aktionen", - "back": "Zurück", - "close": "Schließen", - "cancel": "Abbrechen", - "ok": "OK", - "confirm": "Bestätigen", - "save": "Speichern", - "create": "Erstellen", - "update": "Aktualisieren", - "createddate": "Erstellt am", - "modifieddate": "Zuletzt bearbeitet am", - "id": "ID", - "disabled": "Deaktiviert", - "enabled": "Aktiviert", - "disable": "Deaktivieren", - "enable": "Aktivieren", - "active": "Aktiv", - "inactive": "Inaktiv", - "delete": "Löschen", - "deleteq": "Löschen?", - "default": "Standard", - "remove": "Entfernen", - "alias": "Alias", - "link": "Link", - "links": "Links", - "item": "Element", - "url": "URL", - "urls": "URLs", - "emptylist": "Keine Ergebnisse gefunden", - "pagination": { - "xofy": "Seite {x} von {y}", - "next": "Nächste Seite", - "previous": "Vorherige Seite" - }, - "search": { - "placeholder": "Suchen ...", - "button": "Suchen" - }, - "name": "Name", - "select": "Auswählen", - "selection": { - "select": "Auswählen", - "deselect": "Abwählen" - }, - "icon": "Symbol", - "icon_select": "Wähle ein Symbol", - "tab_general": "Generell", - "tab_content": "Inhalte", - "tab_options": "Optionen", - "tab_infos": "Infos", - "pick": { - "title": "Wähle eines aus", - "title_multiple": "Auswählen", - "title_autocomplete": "Wert eingeben", - "max": "max. {count}" - }, - "date": { - "set": "Datum setzen", - "select": "Datum wählen...", - "xtoy": "{x} bis {y}", - "x": "ab {x}", - "y": "bis {y}", - "range_header": "Datumsbereich wählen", - "range_from": "Datum von", - "range_to": "Datum bis" - }, - "time": { - "set": "Zeit setzen", - "select": "Zeit wählen..." - }, - "price": { - "free": "Gratis", - "xtoy": "von {x} bis {y}", - "x": "ab {x}", - "y": "bis {y}", - "range_from": "Preis von", - "range_to": "Preis bis" - }, - "sort": { - "title": "Sortieren", - "text": "Verschiebe die Elemente hoch oder runter, bis du sie korrekt geordnet hast." - }, - "move": { - "title": "Verschieben", - "action": "Verschieben", - "text": "Wähle in der Baumstruktur ein neues Überelement für {name}." - }, - "copy": { - "title": "Kopieren", - "action": "Kopieren", - "text": "Kopiere {name} in der Baumstruktur an ein neues Ziel.", - "includedescendants": "Unterelemente inkludieren" - }, - "open": { - "title": "Öffnen" - }, - "rename": { - "title": "Umbennenen" - }, - "edit": { - "title": "Bearbeiten" - }, - "export": { - "action": "Exportieren" - }, - "parsedinput": { - "placeholder": "Wert eingeben", - "placeholder_output": "ID" - }, - "entityfields": { - "key": "Schlüssel", - "alias": "Alias", - "sort": "Sortierung", - "hash": "Hash", - "name": "Name", - "isactive": "Aktiv" - } - }, - "gender": { - "undisclosed": "Ungenannt", - "male": "Männlich", - "female": "Weiblich", - "nonbinary": "Nicht-binär", - "unknown": "Unbekannt" - }, - "revisions": { - "label": "Revisionen", - "actions": { - "updated": "Aktualisiert", - "created": "Erstellt", - "deleted": "Gelöscht" - }, - "view": "Ansehen" - }, - "rte": { - "undo": "Rückgängig machen", - "redo": "Nochmals machen", - "bold": "Fett", - "italic": "Kursiv", - "underline": "Unterstrichen", - "strikethrough": "Durchgestrichen", - "heading": "Überschrift", - "heading1": "Überschrift 1", - "heading2": "Überschrift 2", - "heading3": "Überschrift 3", - "heading4": "Überschrift 4", - "heading5": "Überschrift 5", - "heading6": "Überschrift 6", - "paragraph": "Absatz", - "quote": "Zitat", - "list": "Liste", - "olist": "Geordnete Liste", - "ulist": "Ungeordnete Liste", - "code": "Code", - "line": "Linie", - "link": "Link", - "image": "Bild", - "video": "Video", - "accept": "OK", - "cancel": "Abbrechen", - "raw": "HTML bearbeiten" - }, - "links": { - "overlay": { - "title": "Link auswählen" - }, - "providers": { - "page": "Seiten", - "media": "Medien" - }, - "target": { - "default": "Standard", - "self": "Self (gleicher Tab)", - "blank": "Blank (neuer Tab)" - }, - "fields": { - "target": "Ziel", - "title": "Titel", - "title_text": "Wird angezeigt, wenn man über den Link fährt", - "url": { - "url": "URL" - } - } - }, - "flavors": { - "default": { - "name": "Standard", - "text": "Standard-Element erstellen" - } - }, - "errors": { - "idnotfound": "Element konnte nicht gefunden werden", - "childnotallowed": "Nicht erlaubt als Kind dieses Elements", - "onsave": { - "notallowed": "Keine Berechtigung, um dieses Element zu bearbeiten", - "empty": "Es wurden keine Daten übermittelt", - "noidmatch": "Beim Erstellen von Elementen darf keine ID übermittelt werden", - "flavornotfound": "Variante des Elements konnte nicht gefunden werden" - }, - "ondelete": { - "idnotfound": "Element konnte nicht gefunden werden" - }, - "onupdate": { - "noidmatch": "Die ID in der URL stimmt nicht mit jener in den Daten überein", - "changetokenmismatch": "Der Änderungs-Token ist nicht mehr gültig" - }, - "onmove": { - "title": "Element konnte nicht verschoben werden" - }, - "oncopy": { - "title": "Element konnte nicht kopiert werden" - }, - "onsort": { - "title": "Elemente konnten nicht sortiert werden" - }, - "http": { - "403": "Unautorisiert", - "403_text": "Dieses Element kann nicht betrachtet werden", - "404": "Nicht gefunden", - "404_text": "Das angefragte Element konnte nicht gefunden werden
({path})", - "409": "Konflikt", - "409_text": "Die Operation konnte nicht abgeschlossen werden, da sie nicht mehr gültig ist. Bitte Seite neu laden.", - "4xx": "Anwenderfehler", - "4xx_text": "Interner Anwenderfehler (Code: {code})", - "504": "Zeitüberschreitung", - "504_text": "Der Server konnte nicht rechtzeitig auf eine Anfragen antworten", - "5xx": "Serverfehler", - "5xx_text": "Interner Serverfehler (Code: {code})" - }, - "role": { - "emptyclaim": "Eine Berechtigung benötigt einen Schlüssel und einen Wert", - "nosection": "Es muss zumindest ein Bereich ausgewählt werden, zu dem der Benutzer Zugang hat" - }, - "changepassword": { - "emptyfields": "Es müssen alle Felder ausgefüllt werden", - "nouser": "Benutzer ist ungültig", - "newpasswordsnotmatching": "Das neue Passwort stimmt nicht mit deren Bestätigung überein", - "passwordincorrect": "Das aktuelle Passwort des Benutzers ist falsch" - }, - "preview": { - "notfound": "Nicht gefunden", - "notfound_text": "Element mit der ID '{id}' konnte nicht gefunden werden" - }, - "page": { - "parentnotallowed": "Die Seite ist als Kind der ausgewählten Überseite nicht erlaubt", - "sortingmultipleparents": "Seiten können nur auf derselben Hierarchieebene sortiert werden" - }, - "treeentity": { - "parentnotallowed": "Das Element ist als Kind des ausgewählten Überelements nicht erlaubt", - "sortingmultipleparents": "Elemente können nur auf derselben Hierarchieebene sortiert werden" - }, - "forms": { - "email_invalid": "Die E-Mail Adresse ist ungültig", - "emails_invalid": "Die E-Mail Adresse(n) ist/sind ungültig", - "hex_format": "Die Eingabe ist nicht im gültigen HEX #aabbcc Format", - "url_format": "Die Eingabe ist keine gütlige URL", - "not_unique": "Der Wert muss einmalig in dieser Kollektion sein", - "not_unique_alone": "Es muss zumindest ein Element in dieser Kollektion geben, das diese Bedingung erfüllt", - "culture": "Culture konnte für diesen ISO Code nicht gefunden werden", - "reference_notfound": "Die Referenz konnte nicht gefunden werden" - } - }, - "unsavedchanges": { - "title": "Ungespeicherte Änderungen vorhanden", - "text": "Bist du sicher, dass du diese Seite verlassen möchtest ohne die Änderungen zu speichern?", - "close": "Änderungen verwerfen", - "confirm": "Auf der Seite bleiben" - }, - "deleteoverlay": { - "close": "Abbrechen", - "confirm": "Löschen", - "title": "Element löschen", - "text": "Bist du sicher, dass du dieses Element löschen möchtest?", - "success": "Gelöscht", - "success_text": "Du hast das Element erfolgreich gelöscht", - "page_text": "Mit dieser Aktion löscht du die Seite inklusive aller Unterseiten. Bist du sicher?", - "page_success_text": "Die Seite wurde erfolgreich gelöscht" - }, - "changepasswordoverlay": { - "title": "Passwort ändern", - "confirm": "Passwort ändern", - "regenerate": "Neu generieren", - "regenerate_help": "Kopiere das neue Passwort, bevor du den Benutzer speicherst", - "fields": { - "currentpassword": "Aktuelles Passwort", - "newpassword": "Neues Passwort", - "confirmnewpassword": "Neues Passwort bestätigen" - } - }, - "addoverlay": { - "title": "Element erstellen", - "gotoeditor": "Weiter" - }, - "sections": { - "item": { - "dashboard": "Dashboard", - "spaces": "Räume", - "media": "Medien", - "pages": "Seiten", - "settings": "Optionen" - } - }, - "settings": { - "groups": { - "system": "System", - "application": "Applikation", - "integrations": "Integrationen" - }, - "system": { - "updates": { - "name": "Updates", - "text": "Version {zero_version}", - "text_default": "Die zero Version aktualisieren" - }, - "applications": { - "name": "Applikationen", - "text": "Verwalten der App-Instanzen" - }, - "users": { - "name": "Benutzer", - "text": "Administration der Backoffice-Benutzer" - }, - "logs": { - "name": "Logs", - "text": "Logs ansehen und debuggen" - }, - "plugins": { - "name": "Plugins", - "text": "{plugin_count} installierte Plugin(s)", - "text_default": "Verwalten und Installieren von Plugins" - }, - "create": { - "name": "Plugin erstellen", - "text": "Von bestehendem Code erstellen" - } - }, - "application": { - "languages": { - "name": "Sprachen", - "text": "Für das Frontend" - }, - "translations": { - "name": "Übersetzungen", - "text": "Frontend-Texte und Übersetzungen" - }, - "countries": { - "name": "Länder", - "text": "Liste an Ländern verwalten" - }, - "mails": { - "name": "Mails", - "text": "Bearbeiten von Mail-Vorlagen" - }, - "integrations": { - "name": "Integrationen", - "text": "Verfügbare Integration verwalten" - } - } - }, - "user": { - "name": "Benutzer", - "users": "Benutzer", - "add_user": "Benutzer hinzufügen", - "add_role": "Benutzerrolle hinzufügen", - "title": "Benutzer & Berechtigungen", - "count_permissions": "{count} Berechtigungen", - "one_permission": "1 Berechtigung", - "tab_permissions": "Berechtigungen", - "changepassword": "Passwort ändern", - "fields": { - "name_placeholder": "Gib deinen echten Name oder einen Benutzernamen ein", - "email": "Email", - "email_text": "Wird auch als Benutzername für den Login verwendet", - "email_placeholder": "E-Mail Adresse eingeben", - "passwordhash": "Passwort", - "passwordhash_text": "Login Passwort", - "avatarid": "Benutzerbild", - "avatarid_text": "Bild hochladen", - "languageid": "Sprache", - "languageid_text": "Lege die Backoffice-Sprache für diesen Benutzer fest", - "roles": "Benutzerrollen", - "roles_text": "Berechtigungen der Rollen hinzufügen", - "sections": "Bereiche", - "sections_text": "Lege die freigegebenen Bereiche fest", - "isactive": "Aktiv", - "isdisabled": "Deaktivieren", - "islockedout": "Ausgesperrt", - "islockedout_warning": "Der Benutzer ist ausgesperrt bis", - "isdisabled_warning": "Dieser Benutzer ist deaktiviert und kann sich nicht bei zero anmelden. Der Status kann unter Aktionen geändert werden" - } - }, - "role": { - "name": "Benutzerrolle", - "roles": "Benutzerrollen", - "tab_permissions": "Berechtigungen", - "fields": { - "description": "Beschreibung", - "icon": "Symbol" - } - }, - "permission": { - "states": { - "create": "Erstellen", - "read": "Lesen", - "update": "Aktualisieren", - "delete": "Löschen", - "write": "Bearbeiten", - "createdelete": "Erstellen/Löschen", - "none": "Nichts" - }, - "collections": { - "sections": "Bereiche", - "sections_description": "Zugang zu den folgenden Bereichen erlauben", - "settings": "Einstellungen", - "settings_description": "Lese- und Schreibzugriff für Einstellungsbereiche", - "spaces": "Räume", - "spaces_description": "Zugang zu Räumen bearbeiten", - "modules": "Module", - "modules_description": "Verfügbarkeit von Seitenmodulen" - } - }, - "login": { - "headline": "Hallo und Willkommen", - "button": "Anmelden", - "button_forgot": "Passwort vergessen?", - "fields": { - "email": "Email", - "email_placeholder": "Gib deine Email-Adresse oder den Benutzernamen ein", - "password": "Passwort", - "password_placeholder": "Passwort eingeben" - }, - "errors": { - "unknown": "Ein unbekannter Login-Fehler ist aufgetreten", - "wrongcredentials": "Email oder Passwort ist falsch", - "lockedout": "Der Benutzer wurde aufgrund zu vieler Fehlversuche gesperrt", - "disabled": "Der Benutzer wurde deaktiviert", - "notallowed": "Der Benutzer kann sich nicht anmelden", - "requirestwofactor": "Zwei-Faktor-Authentifizierung ist für den Login erforderlich" - }, - "rejectreasons": { - "logout": "Erfolgreich abgemeldet", - "inactive": "Du warst zu lange inaktiv. Bitte erneut anmelden.", - "terminated": "Deine Session wurde beendet. Bitte erneut anmelden.", - "userchanged": "Die Benutzerdaten haben sich geändert. Bitte erneut anmelden.", - "passwordchanged": "Dein Password wurde erfolgreich geändert. Bitte erneut anmelden." - } - }, - - "modules": { - "add": { - "title": "Hinzufügen", - "text": "Füge Module zu einer Seite zusammen" - }, - "default_group": "Standard", - "notfound": "Es konnte kein Modul [{alias}] im Code gefunden werden.", - "noneavailable": "Es sind keine Module verfügbar" - }, - "page": { - "name": "Seite", - "type": "Seitentyp", - "root": "Top", - "info_tab": "Info", - "folder": { - "name": "Ordner", - "description": "Seiten gruppieren", - "fields": { - "ispartofroute": "Ist Teil der URL", - "ispartofroute_text": "Wenn ja, dann wird dieser Ordner als Teil der URL angezeigt", - "urlalias": "URL Name", - "urlalias_text": "Dieses Feld anstatt des Namens für die URL-Generierung verwenden" - } - }, - "overview": { - "actions": { - "continue": "Weitermachen", - "continue_text": "Du hast zuletzt '{page}' bearbeitet", - "new": "Neue Seite", - "new_text": "Erstelle eine neue Seite im obersten Ordner", - "history": "Verlauf", - "history_text": "Änderungsverlauf der Seiten anzeigen" - } - }, - "schedule": { - "label": "Planen", - "header": "Veröffentlichung planen", - "publish": "Veröffentlichen", - "unpublish": "Veröffentlichung zurückziehen", - "scheduled": "Geplant" - }, - "actions": { - "emptyrecyclebin": "Papierkorb leeren" - }, - "create": { - "title": "Seite erstellen", - "parent": "Seite darüber", - "nonavailable": "Hier sind keine Unterseiten erlaubt" - }, - "preview": { - "title": "Vorschau" - }, - "picker": { - "headline": "Seite auswählen", - "urlnotfound": "URL nicht gefunden" - }, - "infotab": { - "links": "Link", - "revisions": "Revisionen" - }, - "deleteoverlay": { - "title": "Seite löschen", - "text": "Mit dieser Aktion löscht du die Seite inklusive aller Unterseiten. Bist du sicher?", - "warning": "Es werden {pages} Seite(n) gelöscht.", - "success_text": "Die Seite wurde erfolgreich gelöscht" - } - }, - "recyclebin": { - "name": "Papierkorb", - "description": "Zuletzt gelöscht Seiten anzeigen", - "purge": "Leeren", - "fields": { - "originalid": "Seiten ID", - "createddate": "Gelöscht" - }, - "overlay": { - "title": "Aktionen" - } - }, - "country": { - "list": "Länder", - "name": "Land", - "fields": { - "name": "Name", - "code": "Code", - "code_text": "Code im ISO 3166-1 Format (wird zur Anzeige der Flagge benötigt)", - "ispreferred": "Oben anzeigen" - } - }, - "integration": { - "list": "Integrationen", - "name": "Integration", - "activewarning": "Diese Integration ist nicht aktiv und wird somit unter keinen Umständen laufen.", - "errors": { - "typenotfound": "Der Integrationstyp existiert nicht", - "multiplenotallowed": "Es kann nur eine Integration je Typ angelegt werden", - "alreadycreated": "Es wurde bereits eine Integration für diesen Typ angelegt", - "notfound": "Integration konnte nicht gefunden werden", - "couldnotupdatestate": "Nicht aktualisiert", - "noaliasmatch": "Der Typ in der URL stimmt nicht mit dem Typ in den Daten überein" - }, - "setup_button": "Einrichten", - "saveandactivate": "Speichern und aktivieren" - }, - "language": { - "list": "Sprachen", - "name": "Sprache", - "fields": { - "name": "Name", - "locale": "Locale", - "code": "ISO Code", - "code_text": "Code im ISO 3166-1 Format", - "isdefault": "Standard", - "isdefault_text": "Als Standard-Sprache verwenden", - "isoptional": "Optional", - "isoptional_text": "Werte für eine optionale Sprache müssen nicht zwangsweise eingegeben werden", - "inheritedlanguageid": "Ersatz", - "inheritedlanguageid_text": "Wenn ein Inhalt in dieser Sprache nicht verfügbar ist, kann auf die ausgewhälte Sprache zurückgegriffen werden" - }, - "errors": { - "fallback_invalid": "Wähle eine andere Sprache als Ersatz", - "default_unique": "Es wurde bereits eine Standard-Sprache angelegt", - "default_not_optional": "Die Standard-Sprache kann nicht optional sein", - "default_no_fallback": "Die Standard-Sprache darf keinen Ersatz haben", - "needs_default": "Zumindest eine Sprache muss als Standard gesetzt werden" - } - }, - "translation": { - "list": "Übersetzungen", - "name": "Übersetzung", - "display": { - "text": "Text", - "html": "HTML" - }, - "fields": { - "key": "Schlüssel", - "value": "Wert", - "display": "Anzeigetyp" - } - }, - "iconpicker": { - "title": "Symbol auswählen", - "notfound": { - "title": "Symbol-Set nicht gefunden", - "text": "Das Symbol-Set ('{name}') konnte nicht gefunden werden" - } - }, - "colorpicker": { - "placeholder": "Wähle eine Farbe aus (#aabbcc)" - }, - "mediapicker": { - "select_text": "Medien hinzufügen", - "select_description": "Hochladen oder auswählen", - "upload_text": "Hochladen", - "upload_description": "Eine neue Datei hochladen" - }, - "videopicker": { - "headline": "Video auswählen", - "providers": { - "html": "Datei auswählen", - "youtube": "YouTube", - "vimeo": "Vimeo" - }, - "fields": { - "provider": "Quelle", - "videoUrl": "URL", - "videoId": "Video", - "title": "Titel", - "previewImageId": "Vorschaubild", - "foundParsed": "Gefundene Video ID ist {id}" - } - }, - "application": { - "list": "Applikationen", - "name": "Applikation", - "tab_features": "Features", - "tab_domains": "Domains", - "fields": { - "name": "Name", - "name_text": "Kurzer lesbarer Name", - "fullname": "Vollständiger Name", - "fullname_text": "Firmen- oder Produktname", - "imageid": "Bild", - "imageid_text": "Bild der Applikation, used for all mails, PDFs, ...", - "iconid": "Icon", - "iconid_text": "Vereinfachtes Bild", - "email": "Email", - "email_text": "Kontakt-Email", - "domains": "Domains", - "domains_text": "Domains für diese Applikation auswählen", - "domains_help": "Gültige Werte sind: 'example.com', 'www.example.com', 'example.com:8080', oder 'https://www.example.com'.", - "domains_add": "Domain hinzufügen", - "features": "Features", - "features_text": "Zusätzliche Features aktivieren" - } - }, - "media": { - "list": "Medien", - "name": "Datei", - "addfolder": "Neuer Ordner", - "editfolder": "Ordner bearbeiten", - "untitledname": "[kein_name]", - "actions": { - "folderdropdown": "Ordner", - "addfolder": "Ordner erstellen", - "addfolder_text": "Einen neuen Unterordner im aktuellen Ordner erstellen", - "addfile": "Dateien hochladen", - "addfile_text": "Eine oder mehrere Dateien in den aktuellen Ordner hochladen", - "openfile": "Ansehen", - "replacefile": "Datei ersetzen" - }, - "notfound": "Datei konnte nicht gefunden werden ({id})", - "selection": { - "clear": "Auswähl aufheben", - "selected": "{count} ausgewählt", - "selectaction": "Aktion" - }, - "fields": { - "foldername_placeholder": "Name eingeben ...", - "caption": "Untertitel", - "caption_text": "Zusätzlicher Untertitel", - "size": "Dateigröße", - "date": "Zuletzt bearbeitet am", - "filename": "Dateiname", - "source": "Datei", - "imagemeta": { - "alternativetext": "Alternativer Text", - "alternativetext_text": "Wird benutzt, wenn das Bild nicht geladen werden kann", - "dpi": "DPI", - "colorspace": "Farbraum", - "hastransparency": "Transparenz", - "frames": "Bilder/sec.", - "imagetakendate": "Aufnahmedatum", - "dimension": "Dimension" - } - }, - "deleteoverlay": { - "title": "Medien löschen", - "folder_text": "Es werden dieser Ordner sowie alle Unterordner und darin enthaltene Dateien gelöscht.
Bist du sicher?", - "warning": "Löschen von {folders} Ordner und {files} Datei(en).", - "folder_success_text": "Der Ordner wurde erfolgreich gelöscht", - "start": { - "title": "Fortschritt", - "button": "Löschen starten" - } - }, - "child_count_1": "{count} Element", - "child_count_x": "{count} Elemente", - "upload": { - "headline": "Hochladen", - "multipleheadline": "Es werden {count} Datei(en) hochgeladen...", - "singleheadline": "Hochladen..." - } - }, - "mailtemplate": { - "name": "Mailvorlage", - "list": "Mailvorlagen", - "emailbox": "Email-Einstellungen", - "tabs": { - "sender": "Absender", - "recipient": "Empfänger" - }, - "fields": { - "name": "Name", - "key": "Schlüssel", - "key_text": "Wird benötigt, um im Code auf die Vorlage zugreifen zu können", - "subject": "Betreff", - "body": "Inhalt", - "body_text": "Zusätzlicher Text, der in der Email ausgegeben wird", - "preheader": "Preheader", - "preheader_text": "Dieser Text wird in der Vorschau des Mailprogramms angezeigt", - "senderemail": "Absender Email", - "senderemail_text": "Wenn leer, dann wird die Email der Applikation verwendet", - "sendername": "Absendername", - "sendername_text": "Wenn leer, dann wird der Name der Applikation verwendet", - "recipientemail": "Empfänger Email", - "recipientemail_text": "Wird nur für Mails benützt, die keinen dynamischen Empfänger haben (z.B. Reporte)", - "cc": "Kopie an (CC)", - "cc_text": "E-Mails mit Komma trennen", - "bcc": "Unsichtbare Kopie an (BCC)", - "bcc_text": "E-Mails mit Komma trennen" - }, - "errors": { - "sendernotallowed": "Die Absender E-Mail wird vom Mailservice nicht unterstützt. Bitte kontaktiere den Administrator für zusätzliche Hilfe." - } - }, - "filelink": { - "defaultName": "Datei" - }, - "space": { - "list": "Räume", - "name": "Raum" - }, - "preview": { - "name": "Vorschau" - }, - "search": { - "permissions": { - "search_group": "Suche", - "search": "Suchen" - }, - "input_placeholder": "Gehe zu...", - "native_hint": "Drücke erneut STRG+F um die native Browsersuche zu verwenden", - "native_toggle": "Öffnen mit STRG+F", - "noresults": "Keine Ergebnisse", - "collection": { - "page": "Seite", - "mediafolder": "Medien", - "country": "Land", - "language": "Sprache", - "translation": "Übersetzung", - "zeroUser": "Benutzer", - "application": "App", - "mailTemplate": "Mail" - } - }, - - "listfilter": { - "button": "Filter", - "button_selected": "Filter: {name}", - "headline": "Filter", - "button_edit": "Filter bearbeiten", - "button_clear": "Filter aufheben", - "clearitem": "Löschen", - "saveas": "Speichern als...", - "saveas_text": "Der Filter kann für spätere Verwendung gespeichert werden", - "search_placeholder": "Suchbegriff eingeben...", - "xselected": "{count} ausgewählt" - }, - - "blueprint": { - "hint": { - "childtext": "Dieses Element basiert auf einer Blaupause. Die Werte werden automatisch aktualisiert.", - "parenttext": "Diese Blaupause überträgt Änderungen automatisch an alle Kind-Elemente.", - "parentcreatetext": "Diese Blaupause erstellt Kind-Elemente in allen Applikationen und überträgt Änderungen an diese automatisch.", - "gotoblueprint": "Blaupause", - "gotochild": "Implementation", - "settingsbutton": "Einstellungen", - "xunlocked": "{count} freigeschalten" - }, - "errors": { - "cannotdeletechild": "Elemente, welche von einer Blaupause abhängig sind, können nicht gelöscht werden" - } - }, - "notfound": { - "title": "Nicht gefunden", - "text": "Die angeforderte Seite konnte nicht gefunden werden", - "show_routes": "Registrierte Routes", - "hide_routes": "Ausblenden", - "routes": { - "name": "Name", - "path": "URL" - } - } -} \ No newline at end of file diff --git a/zero.Backoffice/Resources/Localization/zero.en-us.json b/zero.Backoffice/Resources/Localization/zero.en-us.json deleted file mode 100644 index 14b31ef7..00000000 --- a/zero.Backoffice/Resources/Localization/zero.en-us.json +++ /dev/null @@ -1,882 +0,0 @@ -{ - "zero": { - "name": "zero", - - "config": { - "linkareas": { - "pages": "Pages", - "media": "Media", - "url": "Url" - } - } - }, - - "nav": { - "apps": { - "manage": "Manage apps" - }, - "account": { - "edit": "Edit", - "changepassword": "Change password", - "logout": "Logout" - }, - "theme": { - "dark": "Dark theme", - "light": "Light theme" - } - }, - - "ui": { - "yes": "Yes", - "no": "No", - "required": "Required", - "more": "More", - "add": "Add", - "actions": "Actions", - "back": "Go back", - "close": "Close", - "cancel": "Cancel", - "ok": "OK", - "confirm": "Confirm", - "save": "Save", - "create": "Create", - "update": "Update", - "createdDate": "Created", - "modifiedDate": "Last modified", - "id": "ID", - "disabled": "Disabled", - "enabled": "Enabled", - "disable": "Disable", - "enable": "Enable", - "active": "Active", - "inactive": "Inactive", - "delete": "Delete", - "deleteQ": "Delete?", - "default": "Default", - "remove": "Remove", - "alias": "Alias", - "link": "Link", - "links": "Links", - "item": "Item", - "url": "URL", - "urls": "URLs", - "emptylist": "There are no items to show in this list", - "pagination": { - "xofy": "Page {x} of {y}", - "next": "Next page", - "previous": "Previous page" - }, - "search": { - "placeholder": "Search ...", - "button": "Search" - }, - "name": "Name", - "select": "Select", - "selection": { - "select": "Select", - "deselect": "Deselect" - }, - "icon": "Icon", - "icon_select": "Select an icon", - "tab_general": "General", - "tab_content": "Content", - "tab_options": "Options", - "tab_infos": "Infos", - "pick": { - "title": "Choose one", - "title_multiple": "Choose", - "title_autocomplete": "Enter a value", - "max": "max. {count}" - }, - "date": { - "set": "Set date", - "select": "Select date...", - "xtoy": "{x} to {y}", - "x": "from {x}", - "y": "until {y}", - "range_header": "Select date range", - "range_from": "Date from", - "range_to": "Date to" - }, - "time": { - "set": "Set time", - "select": "Select time..." - }, - "price": { - "free": "Free", - "xtoy": "from {x} to {y}", - "x": "from {x}", - "y": "to {y}", - "range_from": "Price from", - "range_to": "Price to" - }, - "sort": { - "title": "Sort", - "text": "Drag the different items up or down below to set how they should be arranged." - }, - "move": { - "title": "Move", - "action": "Move", - "text": "Select the new parent for {name} in the tree structure below." - }, - "copy": { - "title": "Copy", - "action": "Copy", - "text": "Copy {name} to the selected page in the tree structure below.", - "includeDescendants": "Include descendants" - }, - "open": { - "title": "Open" - }, - "rename": { - "title": "Rename" - }, - "edit": { - "title": "Edit" - }, - "export": { - "action": "Export" - }, - "parsedinput": { - "placeholder": "Enter a value", - "placeholder_output": "ID" - }, - "entityfields": { - "key": "Key", - "alias": "Alias", - "sort": "Sort", - "hash": "Hash", - "name": "Name", - "isActive": "Active" - } - }, - - "gender": { - "undisclosed": "Undisclosed", - "male": "Male", - "female": "Female", - "nonbinary": "Non-binary", - "unknown": "Unknown" - }, - - "revisions": { - "label": "Revisions", - "actions": { - "updated": "Updated", - "created": "Created", - "deleted": "Deleted" - }, - "view": "View" - }, - - "rte": { - "undo": "Undo", - "redo": "Redo", - "bold": "Bold", - "italic": "Italic", - "underline": "Underline", - "strikethrough": "Strike-through", - "heading": "Heading", - "heading1": "Heading 1", - "heading2": "Heading 2", - "heading3": "Heading 3", - "heading4": "Heading 4", - "heading5": "Heading 5", - "heading6": "Heading 6", - "paragraph": "Paragraph", - "quote": "Quote", - "list": "List", - "olist": "Ordered list", - "ulist": "Unordered list", - "code": "Code", - "line": "Horizontal line", - "link": "Link", - "image": "Image", - "video": "Video", - "accept": "Accept", - "cancel": "Cancel", - "raw": "Edit HTML" - }, - - "links": { - "overlay": { - "title": "Select a link" - }, - "providers": { - "page": "Pages", - "media": "Media" - }, - "target": { - "default": "Default", - "self": "Self (same tab)", - "blank": "Blank (new tab)" - }, - "fields": { - "target": "Target", - "title": "Title", - "title_text": "Displayed when hovering the title", - "url": { - "url": "URL" - } - } - }, - - "flavors": { - "default": { - "name": "Default", - "text": "Create the default entity" - } - }, - - "errors": { - "idnotfound": "Could not find an entity for the given ID", - "childnotallowed": "Not allowed as a child entity", - "onsave": { - "notallowed": "You are not allowed to edit this resource", - "empty": "You need to pass a model", - "noidmatch": "Do not fill out the Id field when creating a resource", - "flavornotfound": "Could not find a registration for this resource flavor" - }, - "ondelete": { - "idnotfound": "Could not find an entity for the given ID" - }, - "onupdate": { - "noidmatch": "The Id as part of the URL does not match the Id of the model", - "changetokenmismatch": "The change token is not valid anymore" - }, - "onmove": { - "title": "Could not move entity" - }, - "oncopy": { - "title": "Could not copy entity" - }, - "onsort": { - "title": "Could not sort entities" - }, - "http": { - "403": "Unauthorized", - "403_text": "You are not allowed to view this resource", - "404": "Not found", - "404_text": "The requested resource could not be found
({path})", - "409": "Conflict", - "409_text": "The operation could not be completed as it is not valid anymore. Please reload the page", - "4xx": "Client error", - "4xx_text": "There was an internal client error (code: {code})", - "504": "Timed out", - "504_text": "The backoffice did not receive a timely response from the server", - "5xx": "Server error", - "5xx_text": "There was an internal server error (code: {code})" - }, - "role": { - "emptyclaim": "A permission needs both a key and a value", - "nosection": "You have to select at least one section to give users access to" - }, - "changepassword": { - "emptyfields": "Please fill out all fields", - "nouser": "User is invalid", - "newpasswordsnotmatching": "The new password does not match the confirmation", - "passwordincorrect": "The current password for this user is wrong" - }, - "preview": { - "notfound": "Not found", - "notfound_text": "Could not find entity with ID \"{id}\"" - }, - "page": { - "parentnotallowed": "The page is not allowed as a children of the selected parent", - "sortingmultipleparents": "Sorting pages is only allowed for a specific parent page" - }, - "treeentity": { - "parentnotallowed": "This entity is not allowed as a children of the selected parent", - "sortingmultipleparents": "The selected entities have multiple parents, which is not allowed" - }, - "forms": { - "email_invalid": "The email address is not valid", - "emails_invalid": "The email address(es) is/are not valid", - "hex_format": "The input is not in a valid HEX #aabbcc format", - "url_format": "The input is no well-formed URL", - "not_unique": "The property must be unique in this collection", - "not_unique_alone": "There must be at least one entity in this collection which fulfills this condition", - "culture": "Could not find a culture for the given ISO code", - "reference_notfound": "The reference could not be found" - } - }, - - "unsavedchanges": { - "title": "You have unsaved changes", - "text": "Are you sure you want to navigate away from this page?", - "close": "Discard changes", - "confirm": "Stay on page" - }, - - "deleteoverlay": { - "close": "Cancel", - "confirm": "Delete", - "title": "Delete entity", - "text": "Are you sure you want to delete this entity?", - "success": "Deleted", - "success_text": "You have successfully deleted this entity", - "page_text": "This will delete the page and all its descendants. Are you sure?", - "page_success_text": "You have successfully deleted this page" - }, - - "changepasswordoverlay": { - "title": "Change password", - "confirm": "Change password", - "regenerate": "Regenerate", - "regenerate_help": "Copy the new password before updating the user", - "fields": { - "currentPassword": "Current password", - "newPassword": "New password", - "confirmNewPassword": "Confirm new password" - } - }, - - "addoverlay": { - "title": "Create entity", - "gotoeditor": "Next" - }, - - "sections": { - "item": { - "dashboard": "Dashboard", - "spaces": "Spaces", - "media": "Media", - "pages": "Pages", - "settings": "Settings" - } - }, - - "settings": { - "groups": { - "system": "System", - "application": "Application", - "integrations": "Integrations" - }, - "system": { - "updates": { - "name": "Updates", - "text": "Version {zero_version}", - "text_default": "Update current zero version" - }, - "applications": { - "name": "Applications", - "text": "Edit website applications" - }, - "users": { - "name": "Users & Permissions", - "text": "Administration of backoffice users" - }, - "logs": { - "name": "Logging", - "text": "Debug und view logs" - }, - "plugins": { - "name": "Plugins", - "text": "{plugin_count} installed plugin(s)", - "text_default": "Manage and install plugins" - }, - "create": { - "name": "Create a plugin", - "text": "Create from existing code" - } - }, - "application": { - "languages": { - "name": "Languages", - "text": "Frontend languages" - }, - "translations": { - "name": "Translations", - "text": "Frontend texts and translations" - }, - "countries": { - "name": "Countries", - "text": "Manage list of countries" - }, - "mails": { - "name": "Mails", - "text": "Edit mail templates" - }, - "integrations": { - "name": "Integrations", - "text": "Configure available integrations" - } - } - }, - - "user": { - "name": "User", - "users": "Users", - "add_user": "Add user", - "add_role": "Add role", - "title": "Users & Permissions", - "count_permissions": "{count} permissions", - "one_permission": "1 permission", - "tab_permissions": "Permissions", - "changePassword": "Change password", - "fields": { - "name_placeholder": "Enter your real name or a username", - "email": "Email", - "email_text": "Also used as login username", - "email_placeholder": "Enter your email address", - "passwordHash": "Password", - "passwordHash_text": "Password used for login", - "avatarId": "Avatar", - "avatarId_text": "Upload a user image", - "languageId": "Language", - "languageId_text": "Set the backoffice language for this user", - "roles": "Roles", - "roles_text": "Add default permissions from roles", - "sections": "Sections", - "sections_text": "Specify access to backoffice sections", - "isActive": "Can login", - "isDisabled": "Disable", - "isLockedOut": "Locked out", - "isLockedOut_warning": "The user is locked out until", - "isDisabled_warning": "This user is disabled and cannot log into zero anymore. Status can be changed in Actions dropdown" - } - }, - - "role": { - "name": "Role", - "roles": "Roles", - "tab_permissions": "Permissions", - "fields": { - "description": "Description", - "icon": "Icon" - } - }, - - "permission": { - "states": { - "create": "Create", - "read": "View", - "update": "Update", - "delete": "Delete", - "write": "Edit", - "createdelete": "Create/delete", - "none": "None" - }, - "collections": { - "sections": "Sections", - "sections_description": "Allow access to the following sections", - "settings": "Settings", - "settings_description": "Define read and write access for settings areas", - "spaces": "Spaces", - "spaces_description": "Granular control of spaces", - "modules": "Modules", - "modules_description": "Availability of composing block modules" - } - }, - - "login": { - "headline": "hello and welcome", - "button": "Login", - "button_forgot": "Forgot password?", - "fields": { - "email": "Email", - "email_placeholder": "Enter your email or username", - "password": "Password", - "password_placeholder": "Enter your password" - }, - "errors": { - "unknown": "An unknown login error happened", - "wrongcredentials": "Email or password is wrong", - "lockedout": "The user has been locked out due to many failed password attempts", - "disabled": "The user has been deactivated", - "notallowed": "The user is not allowed to sign in", - "requirestwofactor": "Two-factor authentication is required to login" - }, - "rejectReasons": { - "logout": "You have successfully logged out", - "inactive": "You have been inactive for too long. Please login again.", - "terminated": "Your session has been terminated. Please login again.", - "userchanged": "Your user data has changed. Please login again.", - "passwordchanged": "Your password was successfully changed. Please login again." - } - }, - - "modules": { - "add": { - "title": "Add content", - "text": "Compose the page by adding modules" - }, - "default_group": "Default", - "notfound": "Could not find a registered module [{alias}] in the code.", - "noneavailable": "There are no modules available" - }, - - "page": { - "name": "Page", - "type": "Type", - "root": "Root", - "info_tab": "Info", - - "folder": { - "name": "Folder", - "description": "Group pages together", - "fields": { - "isPartOfRoute": "Is part of Url", - "isPartOfRoute_text": "Whether to render the page name as part of the Url", - "urlAlias": "Url alias", - "urlAlias_text": "Use this field instead of the page name for Url generation" - } - }, - - "overview": { - "actions": { - "continue": "Continue", - "continue_text": "You have last edited \"{page}\"", - "new": "New page", - "new_text": "Create a new page on root", - "history": "History", - "history_text": "View page editing history" - } - }, - "schedule": { - "label": "Schedule", - "header": "Schedule publishing", - "publish": "Publish", - "unpublish": "Unpublish", - "scheduled": "Scheduled" - }, - - "actions": { - "emptyrecyclebin": "Empty recycle bin" - }, - - "create": { - "title": "Create page", - "parent": "Parent", - "nonavailable": "There are no page types allowed here" - }, - - "preview": { - "title": "Preview" - }, - - "picker": { - "headline": "Select a page", - "urlnotfound": "URL not found" - }, - - "infotab": { - "links": "Link", - "revisions": "Revisions" - }, - - "deleteoverlay": { - "title": "Delete page", - "text": "This will delete the page as well as all its descendants.
Are you sure?", - "warning": "You are about to delete {pages} page(s).", - "success_text": "You have successfully deleted this page" - } - }, - - "recyclebin": { - "name": "Recycle bin", - "description": "View recently deleted entities", - "purge": "Purge", - "fields": { - "originalId": "Page Id", - "createdDate": "Deleted" - }, - "overlay": { - "title": "Actions" - } - }, - - "country": { - "list": "Countries", - "name": "Country", - "fields": { - "name": "Name", - "code": "Code", - "code_text": "Code in ISO 3166-1 format which is used to display the appropriate flag", - "isPreferred": "Show on top" - } - }, - - "integration": { - "list": "Integrations", - "name": "Integration", - "activeWarning": "This integration is not activated and will therefore not run under any circumstances.", - "errors": { - "typenotfound": "The integration type does not exist", - "multiplenotallowed": "Can not create multiple integrations per type", - "alreadycreated": "You have already created an integration for this type", - "notfound": "Could not find a matching integration", - "couldnotupdatestate": "Not updated", - "noaliasmatch": "The alias as part of the URL does not match the alias of the model" - }, - "setup_button": "Setup", - "saveandactivate": "Save and activate", - "fields": { - - } - }, - - "language": { - "list": "Languages", - "name": "Language", - "fields": { - "name": "Name", - "locale": "Locale", - "code": "ISO Code", - "code_text": "Code in ISO 3166-1 format", - "isDefault": "Default", - "isDefault_text": "Use as default language", - "isOptional": "Optional", - "isOptional_text": "Values for an optional language must not be entered, even if the field is required", - "inheritedLanguageId": "Fallback", - "inheritedLanguageId_text": "To allow multi-lingual content to fall back to another language if not present in the requested language, select it here" - }, - "errors": { - "fallback_invalid": "Select a different language as a fallback", - "default_unique": "There is already another language which is set as the default", - "default_not_optional": "The default language can't be set as optional", - "default_no_fallback": "The default language can't have a fallback", - "needs_default": "At least one language has to be set as the default" - } - }, - - "translation": { - "list": "Translations", - "name": "Translation", - "display": { - "text": "Text", - "html": "HTML" - }, - "fields": { - "key": "Key", - "value": "Value", - "display": "Display type" - } - }, - - "iconpicker": { - "title": "Pick an icon", - "notfound": { - "title": "Icon set not found", - "text": "Could not locate a registered icon set (\"{name}\")" - } - }, - - "colorpicker": { - "placeholder": "Select or enter a color (#aabbcc)" - }, - - "mediapicker": { - "select_text": "Add media", - "select_description": "Upload or select", - "upload_text": "Upload", - "upload_description": "Upload a new file" - }, - - "videopicker": { - "headline": "Pick a video", - "providers": { - "html": "Media upload", - "youtube": "YouTube", - "vimeo": "Vimeo" - }, - "fields": { - "provider": "Provider", - "videoUrl": "URL", - "videoId": "Pick video", - "title": "Title", - "previewImageId": "Poster image", - "foundParsed": "Parsed video ID is {id}" - } - }, - - "application": { - "list": "Applications", - "name": "Application", - "tab_features": "Features", - "tab_domains": "Domains", - "fields": { - "name": "Name", - "name_text": "Short human-readable name", - "fullName": "Full name", - "fullName_text": "Full company or product name", - "imageid": "Image", - "imageid_text": "Image of the app (with transparent background), used for all mails, PDFs, ...", - "iconid": "Icon", - "iconid_text": "Simplified image for minor application parts", - "email": "Email", - "email_text": "Generic contact email", - "domains": "Domains", - "domains_text": "Select domains for this application", - "domains_help": "Valid domain names are: \"example.com\", \"www.example.com\", \"example.com:8080\", or \"https://www.example.com\".", - "domains_add": "Add domain", - "features": "Features", - "features_text": "Enable additional features for this application" - } - }, - - "media": { - "list": "Media", - "name": "Media", - "addfolder": "Add folder", - "editfolder": "Edit folder", - "untitledName": "[untitled]", - "actions": { - "folderdropdown": "Folder", - "addfolder": "Create folder", - "addfolder_text": "Adds a new folder in the current parent folder", - "addfile": "Upload files", - "addfile_text": "Add one or more files to the current filter", - "openfile": "Open", - "replacefile": "Replace file" - }, - "notfound": "Could not find media ({id})", - "selection": { - "clear": "Clear selection", - "selected": "{count} selected", - "selectaction": "Action" - }, - "fields": { - "foldername_placeholder": "Enter a name ...", - "caption": "Caption", - "caption_text": "Additional caption text", - "size": "Size", - "date": "Last modified at", - "filename": "Filename", - "source": "File", - "imageMeta": { - "alternativeText": "Alternative text", - "alternativeText_text": "Text which is used when the image can't be loaded", - "dpi": "DPI", - "colorSpace": "Color space", - "hasTransparency": "Has transparency", - "frames": "Frames", - "imageTakenDate": "Date taken", - "dimension": "Dimension" - } - }, - "deleteoverlay": { - "title": "Delete media", - "folder_text": "This will delete the selected items as well as all its descendants including subfolders and files.

Database entries as well as persisted files are deleted.
Are you sure?", - "warning": "You are about to delete {folders} folder(s) and {files} file(s).", - "folder_success_text": "You have successfully deleted this folder", - "start": { - "title": "Progress", - "button": "Start deletion" - } - }, - "child_count_1": "{count} item", - "child_count_x": "{count} items", - "upload": { - "headline": "Upload", - "multipleHeadline": "Uploading {count} items...", - "singleHeadline": "Uploading..." - } - }, - - "mailTemplate": { - "name": "Mail template", - "list": "Mail templates", - "emailBox": "Email settings", - "tabs": { - "sender": "Sender", - "recipient": "Recipient" - }, - "fields": { - "name": "Name", - "key": "Key", - "key_text": "Used to query for the template in code", - "subject": "Subject", - "body": "Body", - "body_text": "Additional body which is rendered into the mail template", - "preheader": "Preheader", - "preheader_text": "This text is rendered as part of the preview in your mail program", - "senderEmail": "Sender email", - "senderEmail_text": "Leave empty to use application email", - "senderName": "Sender name", - "senderName_text": "Leave empty to use application name", - "recipientEmail": "Recipient email", - "recipientEmail_text": "Only used for mails which do not have a dynamic recipient (e.g. reports)", - "cc": "Send copy to (CC)", - "cc_text": "Comma-separated list of e-mails", - "bcc": "Send invisible copy to (BCC)", - "bcc_text": "Comma-separated list of e-mails" - }, - "errors": { - "senderNotAllowed": "The sender email is currently not supported for this registered mail dispatcher. Please contact the administrator for help." - } - }, - - "filelink": { - "defaultName": "File" - }, - - "space": { - "list": "Spaces", - "name": "Space" - }, - - "preview": { - "name": "Preview" - }, - - "search": { - "permissions": { - "search_group": "Search", - "search": "Use search" - }, - "input_placeholder": "Go to...", - "native_hint": "Press CTRL+F again to use native browser search", - "native_toggle": "Open on CTRL+F", - "noresults": "No results", - "collection": { - "page": "Page", - "mediaFolder": "Media folder", - "country": "Country", - "language": "Language", - "translation": "Translation", - "zeroUser": "User", - "application": "App", - "mailTemplate": "Mail" - } - }, - - "listfilter": { - "button": "Filter", - "button_selected": "Filter: {name}", - "headline": "Filter", - "button_edit": "Edit filter", - "button_clear": "Clear filter", - "clearitem": "Clear", - "saveas": "Save as...", - "saveas_text": "You can optionally save this filter for future reference", - "search_placeholder": "Enter a search term...", - "xselected": "{count} selected" - }, - - "blueprint": { - "hint": { - "childText": "This entity is a child of a blueprint. Its properties are automatically updated.", - "parentText": "This blueprint will automatically pass changes to its children.", - "parentCreateText": "This blueprint will create children in all registered apps and automatically pass changes to them.", - "goToBlueprint": "Blueprint", - "goToChild": "View child", - "settingsButton": "Settings", - "xUnlocked": "{count} unlocked" - }, - "errors": { - "cannotDeleteChild": "Entities which are synchronized with a blueprint cannot be deleted" - } - }, - - "notfound": { - "title": "Not found", - "text": "The requested resource could not be found", - "show_routes": "Defined routes", - "hide_routes": "Hide", - "routes": { - "name": "Name", - "path": "Path" - } - } -} \ No newline at end of file diff --git a/zero.Backoffice/Resources/backoffice.tpl.html b/zero.Backoffice/Resources/backoffice.tpl.html deleted file mode 100644 index ba239606..00000000 --- a/zero.Backoffice/Resources/backoffice.tpl.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - {top} - zero - - - -
- {svg} - {bottom} - - - - \ No newline at end of file diff --git a/zero.Backoffice/ServiceCollectionExtensions.cs b/zero.Backoffice/ServiceCollectionExtensions.cs deleted file mode 100644 index 4985b668..00000000 --- a/zero.Backoffice/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Backoffice; - -public static class ServiceCollectionExtensions -{ - public static ZeroBuilder AddBackoffice(this ZeroBuilder builder) - { - return builder.AddPlugin(); - } -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Icons/BackofficeIconSetPresentation.cs b/zero.Backoffice/Services/Icons/BackofficeIconSetPresentation.cs deleted file mode 100644 index 9cb0efb0..00000000 --- a/zero.Backoffice/Services/Icons/BackofficeIconSetPresentation.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace zero.Backoffice.Services; - -public class BackofficeIconSetPresentation -{ - public string Alias { get; set; } - - public string Name { get; set; } - - public string Prefix { get; set; } - - public IEnumerable Icons { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Icons/IconService.cs b/zero.Backoffice/Services/Icons/IconService.cs deleted file mode 100644 index e86a00c1..00000000 --- a/zero.Backoffice/Services/Icons/IconService.cs +++ /dev/null @@ -1,113 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.Collections.Concurrent; -using System.IO; -using System.Text; -using System.Xml.Linq; - -namespace zero.Backoffice.Services; - -public class IconService : IIconService -{ - protected IOptions Options { get; set; } - - protected IBackofficeAssetFileSystem FileSystem { get; set; } - - protected ILogger Logger { get; set; } - - protected ConcurrentBag CachedSets { get; private set; } = new(); - - protected string CachedSvg { get; set; } - - protected bool IsLoaded { get; set; } - - - public IconService(IOptions options, IBackofficeAssetFileSystem fileSystem, ILogger logger) - { - Options = options; - FileSystem = fileSystem; - Logger = logger; - } - - - /// - public async Task> GetSets() - { - await EnsureIconsAreLoaded(); - return CachedSets; - } - - - /// - public async Task GetCompiledSvg() - { - await EnsureIconsAreLoaded(); - return CachedSvg; - } - - - async Task EnsureIconsAreLoaded() - { - if (IsLoaded) - { - return; - } - - StringBuilder svg = new(); - - foreach (BackofficeIconSet set in Options.Value.IconSets) - { - if (!await FileSystem.Exists(set.SpritePath)) - { - Logger.LogWarning("Could not load icon set {alias} from path {path}", set.Alias, FileSystem.Map(set.SpritePath)); - continue; - } - - using Stream stream = await FileSystem.StreamFile(set.SpritePath); - - XDocument xml = XDocument.Load(stream); - IEnumerable symbols = xml.Descendants().Where(x => x.Name.LocalName == "symbol"); - - if (!symbols.Any()) - { - Logger.LogWarning("Icon set {alias} does not contain any ", set.Alias); - continue; - } - - HashSet icons = new(); - - foreach (XElement symbol in symbols) - { - string symbolAlias = set.Prefix + "-" + symbol.Attribute("id").Value.ToString(); - symbol.SetAttributeValue("id", symbolAlias); - svg.Append(symbol.ToString().RemoveNewLines()); - icons.Add(symbolAlias); - } - - CachedSets.Add(new() - { - Alias = set.Alias, - Name = set.Name, - Prefix = set.Prefix, - Icons = icons - }); - } - - CachedSvg = svg.ToString(); - IsLoaded = true; - } -} - - -public interface IIconService -{ - /// - /// Get all registered icon sets with all their containing icons - /// - Task> GetSets(); - - /// - /// Get compiled SVG string for alle registered icon sets - /// - Task GetCompiledSvg(); -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Resources/ResourceService.cs b/zero.Backoffice/Services/Resources/ResourceService.cs deleted file mode 100644 index 86506585..00000000 --- a/zero.Backoffice/Services/Resources/ResourceService.cs +++ /dev/null @@ -1,116 +0,0 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json.Linq; -using System.IO; -using System.Text; - -namespace zero.Backoffice.Services; - -public class ResourceService : IResourceService -{ - protected IOptions Options { get; set; } - - protected IBackofficeAssetFileSystem AssetFileSystem { get; set; } - - protected IBackofficeResourceFileSystem ResourceFileSystem { get; set; } - - protected ILogger Logger { get; set; } - - protected IEnumerable Plugins { get; set; } - - protected IWebHostEnvironment Env { get; set; } - - - public ResourceService(IOptions options, IBackofficeAssetFileSystem assetFileSystem, IBackofficeResourceFileSystem resourceFileSystem, ILogger logger, - IEnumerable plugins, IWebHostEnvironment env) - { - Options = options; - AssetFileSystem = assetFileSystem; - ResourceFileSystem = resourceFileSystem; - Logger = logger; - Plugins = plugins; - Env = env; - } - - - /// - public Task> GetTranslations(string cultureIsoCode) - { - Dictionary zeroTranslations = new(); // CreateTranslationsForFile("O:/zero/zero.Backoffice/Resources/Localization/zero.en-us.json", cultureIsoCode); // TODO - - foreach (IZeroPlugin plugin in Plugins) - { - if (plugin.Options.LocalizationPaths.Count > 0) - { - foreach (string path in plugin.Options.LocalizationPaths) - { - Dictionary translations = CreateTranslationsForFile(path, cultureIsoCode); - - foreach (var translation in translations) - { - zeroTranslations.Add(translation.Key, translation.Value); - } - } - } - } - - return Task.FromResult(zeroTranslations); - } - - - Dictionary CreateTranslationsForFile(string path, string culture) - { - Dictionary items = new(); - culture = culture.Or("en-us").ToLower(); - - if (path.Contains("{lang}")) - { - path = path.Replace("{lang}", culture); - } - - string fullpath = Path.Combine(AppContext.BaseDirectory, path); - - if (!Env.IsDevelopment()) - { - try - { - fullpath = ResourceFileSystem.Map(path); - } - catch { } - } - - if (!File.Exists(fullpath)) - { - return items; - } - - string text = File.ReadAllText(fullpath, Encoding.GetEncoding("UTF-8")); - - JObject json = JObject.Parse(text); - IEnumerable tokens = json.Descendants().Where(p => !p.Any()); - - Dictionary translationItems = tokens.Aggregate(new Dictionary(), (properties, token) => - { - properties.Add(token.Path.ToLowerInvariant(), token.ToString()); - return properties; - }); - - foreach (var translation in translationItems) - { - items[translation.Key] = translation.Value; - } - - return items; - } -} - - -public interface IResourceService -{ - /// - /// Get all backoffice translations from all registered plugins - /// - Task> GetTranslations(string cultureIsoCode); -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Sections/BackofficeSectionPresentation.cs b/zero.Backoffice/Services/Sections/BackofficeSectionPresentation.cs deleted file mode 100644 index ef34cd5e..00000000 --- a/zero.Backoffice/Services/Sections/BackofficeSectionPresentation.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace zero.Backoffice.Services; - -public class BackofficeSectionPresentation -{ - public string Alias { get; set; } - - public string Name { get; set; } - - public string Icon { get; set; } - - public string Color { get; set; } - - public string Url { get; set; } - - public bool IsExternal { get; set; } - - public IEnumerable Children { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Sections/BackofficeSettingPresentation.cs b/zero.Backoffice/Services/Sections/BackofficeSettingPresentation.cs deleted file mode 100644 index 59a5ef08..00000000 --- a/zero.Backoffice/Services/Sections/BackofficeSettingPresentation.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace zero.Backoffice.Services; - -public class BackofficeSettingGroupPresentation -{ - public string Name { get; set; } - - public IEnumerable Items { get; set; } -} - -public class BackofficeSettingPresentation -{ - public string Alias { get; set; } - - public string Name { get; set; } - - public string Description { get; set; } - - public string Icon { get; set; } - - public string Url { get; set; } - - public bool IsPlugin { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/Services/Sections/SectionService.cs b/zero.Backoffice/Services/Sections/SectionService.cs deleted file mode 100644 index f7844491..00000000 --- a/zero.Backoffice/Services/Sections/SectionService.cs +++ /dev/null @@ -1,150 +0,0 @@ -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace zero.Backoffice.Services; - -public class SectionService : ISectionService -{ - protected IZeroOptions Options { get; set; } - - protected IBackofficeAssetFileSystem FileSystem { get; set; } - - protected ILogger Logger { get; set; } - - protected IEnumerable Sections { get; set; } - - protected IEnumerable SettingsGroups { get; set; } - - - public SectionService(IZeroOptions options, IBackofficeAssetFileSystem fileSystem, ILogger logger, IEnumerable sections, IEnumerable settingsGroups) - { - Options = options; - FileSystem = fileSystem; - Logger = logger; - Sections = sections; - SettingsGroups = settingsGroups; - } - - - /// - public Task> GetSections() - { - //bool isSuperUser = AuthenticationApi.IsSuper(); - //IList permissions = AuthenticationApi.GetPermissions(Permissions.Sections.PREFIX); - - List sections = new(); - - foreach (IBackofficeSection section in Sections.OrderBy(x => x.Sort)) - { - //if (!isSuperUser && !Permission.CanReadKey(permissions, section.Alias, true)) - //{ - // continue; - //} - - string url = Safenames.Alias(section.Alias).EnsureStartsWith('/'); - - if (section.Alias == Constants.Sections.Dashboard) - { - url = "/"; - } - - BackofficeSectionPresentation backofficeSection = new() - { - Alias = section.Alias, - Name = section.Name, - Icon = section.Icon, - Color = section.Color, - Url = url, - IsExternal = false - }; - - List children = new(); - - foreach (IBackofficeSection child in section.Children) - { - children.Add(new() - { - Alias = child.Alias, - Name = child.Name, - Url = backofficeSection.Url.EnsureEndsWith('/') + Safenames.Alias(child.Alias), - IsExternal = false - }); - } - - backofficeSection.Children = children; - - sections.Add(backofficeSection); - } - - return Task.FromResult>(sections); - } - - - /// - public Task> GetSettingsAreas() - { - //bool isSuperUser = AuthenticationApi.IsSuper(); - //IList permissions = AuthenticationApi.GetPermissions(Permissions.Settings.PREFIX); - - List groups = new(); - - bool hasIntegrations = Options.For().GetAll().Any(); - - foreach (SettingsGroup group in SettingsGroups) - { - List areas = new(); - - foreach (SettingsArea area in group.Areas) - { - //if (!isSuperUser && !Permission.CanReadKey(permissions, area.Alias, true)) - //{ - // continue; - //} - - if (area.Alias == Constants.Settings.Integrations && !hasIntegrations) - { - continue; - } - - //bool isPlugin = !(area is InternalSettingsArea); - - BackofficeSettingPresentation settingsArea = new() - { - Alias = area.Alias, - Name = area.Name, - Description = area.Description, - Icon = area.Icon, - Url = Constants.Sections.Settings.EnsureStartsWith('/') + area.CustomUrl.Or(Safenames.Alias(area.Alias)).EnsureStartsWith('/'), - IsPlugin = true - }; - - areas.Add(settingsArea); - } - - if (areas.Count > 0) - { - groups.Add(new() - { - Name = group.Name, - Items = areas - }); - } - } - - return Task.FromResult>(groups); - } -} - - -public interface ISectionService -{ - /// - /// Get all registered backoffice sections - /// - Task> GetSections(); - - /// - /// Get all registered backoffice settings - /// - Task> GetSettingsAreas(); -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/BackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/BackofficeSection.cs deleted file mode 100644 index 6b0e5e00..00000000 --- a/zero.Backoffice/UIComposition/Sections/BackofficeSection.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// A section is a main part of the backoffice application -/// -public class BackofficeSection : IBackofficeSection, IChildBackofficeSection -{ - /// - public string Alias { get; set; } - - /// - public string Name { get; set; } - - /// - public string Icon { get; set; } - - /// - public int Sort { get; set; } - - /// - /// HEX color (#aabbcc or #abc). Defaults to a neutral color - /// - public string Color { get; set; } - - /// - public IList Children { get; } = new List(); - - - public BackofficeSection() { } - - public BackofficeSection(string alias, string name, string icon = null, string color = null, int sort = 0) - { - Alias = alias; - Name = name; - Icon = icon; - Color = color; - Sort = sort; - } -} diff --git a/zero.Backoffice/UIComposition/Sections/DashboardSection.cs b/zero.Backoffice/UIComposition/Sections/DashboardSection.cs deleted file mode 100644 index b13eca02..00000000 --- a/zero.Backoffice/UIComposition/Sections/DashboardSection.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// The dashboard aggregates data from all sections -/// -public class DashboardSection : IInternalBackofficeSection -{ - /// - public string Alias => Constants.Sections.Dashboard; - - /// - public string Name => "@sections.item.dashboard"; - - /// - public string Icon => "fth-pie-chart"; - - /// - public string Color => null; - - /// - public int Sort => 0; - - /// - public IList Children => new List(); -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs deleted file mode 100644 index 549593f4..00000000 --- a/zero.Backoffice/UIComposition/Sections/IBackofficeSection.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// Internal section -/// -internal interface IInternalBackofficeSection : IBackofficeSection { } - -/// -/// A section is a main part of the backoffice application -/// -public interface IBackofficeSection -{ - /// - /// The section alias which acts as the url slug for navigation - /// - string Alias { get; } - - /// - /// The name of the section (either a string or a translation key with @ prefix) - /// - string Name { get; } - - /// - /// Icon of the section - /// - string Icon { get; } - - /// - /// HEX color (#aabbcc or #abc) - /// - string Color { get; } - - /// - /// Children are displayed as a sub-navigation in the main nav area - /// - IList Children { get; } - - /// - /// Sort order - /// - int Sort { get; } -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs b/zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs deleted file mode 100644 index f25c6e5b..00000000 --- a/zero.Backoffice/UIComposition/Sections/IChildBackofficeSection.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// A child section is a sub-navigation item of a section -/// -public interface IChildBackofficeSection -{ - /// - /// The section alias which acts as the url slug for navigation - /// - public string Alias { get; } - - /// - /// The name of the section (either a string or a translation key with @ prefix) - /// - public string Name { get; } -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/MediaSection.cs b/zero.Backoffice/UIComposition/Sections/MediaSection.cs deleted file mode 100644 index 2e48859a..00000000 --- a/zero.Backoffice/UIComposition/Sections/MediaSection.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// Media items (images, videos, documents) grouped in folders -/// -public class MediaSection : IInternalBackofficeSection -{ - /// - public string Alias => Constants.Sections.Media; - - /// - public string Name => "@sections.item.media"; - - /// - public string Icon => "fth-image"; - - /// - public string Color => "#d82853"; - - /// - public int Sort => 300; - - /// - public IList Children => new List(); -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/PagesSection.cs b/zero.Backoffice/UIComposition/Sections/PagesSection.cs deleted file mode 100644 index 1f47b113..00000000 --- a/zero.Backoffice/UIComposition/Sections/PagesSection.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// Manage the page tree in this section -/// -public class PagesSection : IInternalBackofficeSection -{ - /// - public string Alias => Constants.Sections.Pages; - - /// - public string Name => "@sections.item.pages"; - - /// - public string Icon => "fth-folder"; - - /// - public string Color => "#0cb0f5"; - - /// - public int Sort => 100; - - /// - public IList Children => new List(); -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/SectionPermissions.cs b/zero.Backoffice/UIComposition/Sections/SectionPermissions.cs deleted file mode 100644 index 869dc88c..00000000 --- a/zero.Backoffice/UIComposition/Sections/SectionPermissions.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -public class SectionPermissions : PermissionProvider -{ - protected IEnumerable Sections { get; private set; } - - - public SectionPermissions(IEnumerable sections) - { - Sections = sections; - } - - - public override Task Configure(IPermissionContext context) - { - PermissionGroup group = new("zero.sections", "@permissions.collections.sections"); - - foreach (IBackofficeSection section in Sections) - { - Permission permission = new("zero.sections." + section.Alias, section.Name); - - foreach (IChildBackofficeSection child in section.Children) - { - Permission childPermission = new(permission.Key + "." + child.Alias, child.Name); - permission.Children.Add(childPermission); - } - - group.Add(permission); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Sections/SettingsSection.cs b/zero.Backoffice/UIComposition/Sections/SettingsSection.cs deleted file mode 100644 index 1d5152ca..00000000 --- a/zero.Backoffice/UIComposition/Sections/SettingsSection.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// Website and backoffice settings -/// -public class SettingsSection : IInternalBackofficeSection -{ - /// - public string Alias => Constants.Sections.Settings; - - /// - public string Name => "@sections.item.settings"; - - /// - public string Icon => "fth-settings"; - - /// - public string Color => null; - - /// - public int Sort => 1000; - - /// - public IList Children => new List(); -} diff --git a/zero.Backoffice/UIComposition/Sections/SpacesSection.cs b/zero.Backoffice/UIComposition/Sections/SpacesSection.cs deleted file mode 100644 index a0b471dd..00000000 --- a/zero.Backoffice/UIComposition/Sections/SpacesSection.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -/// -/// Global list entities -/// -public class SpacesSection : IInternalBackofficeSection -{ - /// - public string Alias => Constants.Sections.Spaces; - - /// - public string Name => "@sections.item.spaces"; - - /// - public string Icon => "fth-layers"; - - /// - public string Color => "#f9c202"; - - /// - public int Sort => 200; - - /// - public IList Children => new List(); -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/ServiceCollectionExtensions.cs b/zero.Backoffice/UIComposition/ServiceCollectionExtensions.cs deleted file mode 100644 index 8b99bd91..00000000 --- a/zero.Backoffice/UIComposition/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace zero.Backoffice.UIComposition; - -public static class ServiceCollectionExtensions -{ - public static IServiceCollection AddZeroBackofficeUIComposition(this IServiceCollection services) - { - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(); - services.AddSingleton(); - - services.AddScoped(); - - services.AddOptions(); - - return services; - } -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs b/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs deleted file mode 100644 index f0f87fb9..00000000 --- a/zero.Backoffice/UIComposition/Settings/ApplicationSettings.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -public class ApplicationSettings : SettingsGroup -{ - public ApplicationSettings() : base("@settings.groups.application") - { - 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"); - } -} \ No newline at end of file diff --git a/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs b/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs deleted file mode 100644 index 309ce944..00000000 --- a/zero.Backoffice/UIComposition/Settings/ISettingsArea.cs +++ /dev/null @@ -1,32 +0,0 @@ -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 deleted file mode 100644 index 548ca37e..00000000 --- a/zero.Backoffice/UIComposition/Settings/ISettingsGroup.cs +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index afa933f1..00000000 --- a/zero.Backoffice/UIComposition/Settings/SettingsArea.cs +++ /dev/null @@ -1,30 +0,0 @@ -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 deleted file mode 100644 index 6107b59c..00000000 --- a/zero.Backoffice/UIComposition/Settings/SettingsGroup.cs +++ /dev/null @@ -1,23 +0,0 @@ -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/SettingsOptions.cs b/zero.Backoffice/UIComposition/Settings/SettingsOptions.cs deleted file mode 100644 index ea18b15d..00000000 --- a/zero.Backoffice/UIComposition/Settings/SettingsOptions.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -public class BackofficeSettingsOptions : List -{ - public void AddGroup(int index = -1) where T : SettingsGroup, new() - { - if (index > -1 && index < Count) - { - Insert(index, new T()); - } - else - { - Add(new T()); - } - } - - - public void AddGroup(SettingsGroup group, int index = -1) - { - if (index > -1 && index < Count) - { - Insert(index, group); - } - else - { - Add(group); - } - } - - - public void AddToDefaultGroup(SettingsArea item, int index = -1) - { - SettingsGroup group = this.FirstOrDefault(x => x.Name == "@settings.groups.system"); - - if (group == null) - { - return; - } - - if (index > -1 && index < group.Areas.Count) - { - group.Areas.Insert(index, item); - } - else - { - group.Areas.Add(item); - } - } -} diff --git a/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs b/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs deleted file mode 100644 index 57b0a1a6..00000000 --- a/zero.Backoffice/UIComposition/Settings/SettingsPermissions.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace zero.Backoffice.UIComposition; - -public class SettingsPermissions : PermissionProvider -{ - //public SettingsPermissions() : base("@permissions.collections.settings") { } - - //public const string Dashboard = "zero.sections.dashboard"; - //public const string Pages = "zero.sections.pages"; - //public const string Spaces = "zero.sections.spaces"; - //public const string Media = "zero.sections.media"; - //public const string Settings = "zero.sections.settings"; - - - ///// - //public override IEnumerable GetPermissions() => new Permission[] - //{ - // new(Dashboard, "@sections.item.dashboard"), - // new(Pages, "@sections.item.pages"), - // new(Spaces, "@sections.item.spaces"), - // new(Media, "@sections.item.media"), - // new(Settings, "@sections.item.settings") - //}; -} - -//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 deleted file mode 100644 index 6dec000e..00000000 --- a/zero.Backoffice/UIComposition/Settings/SystemSettings.cs +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 90f9abd4..00000000 --- a/zero.Backoffice/Usings.cs +++ /dev/null @@ -1,31 +0,0 @@ - -global using System; -global using System.Collections.Generic; -global using System.Linq; -global using System.Threading; -global using System.Threading.Tasks; - -global using zero.Applications; -global using zero.Architecture; -global using zero.Stores; -global using zero.Configuration; -global using zero.Context; -global using zero.Extensions; -global using zero.FileStorage; -global using zero.Identity; -global using zero.Localization; -global using zero.Media; -global using zero.Models; -global using zero.Pages; -global using zero.Persistence; -global using zero.Routing; -global using zero.Utils; -global using zero.Mapper; - -global using zero.Backoffice.Abstractions; -global using zero.Backoffice.Configuration; -global using zero.Backoffice.Controllers; -global using zero.Backoffice.UIComposition; -global using zero.Backoffice.DevServer; - -global using zero.Api.Attributes; \ No newline at end of file diff --git a/zero.Backoffice/Views/Zero/Index.cshtml b/zero.Backoffice/Views/Zero/Index.cshtml deleted file mode 100644 index 9bd1e0cf..00000000 --- a/zero.Backoffice/Views/Zero/Index.cshtml +++ /dev/null @@ -1,42 +0,0 @@ -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@model zero.Backoffice.ZeroBackofficeModel - - - - - - - - - - - - - - - - - - - - zero - - - @Model.Meta.AppLastModifiedDate -
- @* - @Html.Raw(Model.Vue.GetIconSvg()) - - - - - - - *@ - - \ No newline at end of file diff --git a/zero.Backoffice/Views/Zero/Setup.cshtml b/zero.Backoffice/Views/Zero/Setup.cshtml deleted file mode 100644 index 18f7de61..00000000 --- a/zero.Backoffice/Views/Zero/Setup.cshtml +++ /dev/null @@ -1,30 +0,0 @@ -@*@using zero.Core.Extensions -@inject zero.Core.Options.IZeroOptions Options -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@{ - Layout = null; -} - - - - - - - - - - - - - - zero - - -
- - - -*@ \ No newline at end of file diff --git a/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs b/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs deleted file mode 100644 index 4d3352fe..00000000 --- a/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using System.Text; -using zero.Api.Controllers; - -namespace zero.Backoffice; - -public class ZeroBackofficeControllerModelConvention : ZeroApiControllerModelConvention -{ - public ZeroBackofficeControllerModelConvention(string path, bool isAppAware = false) : base(path, isAppAware) - { - BaseClassType = typeof(ZeroBackofficeController); - } - - - protected override AttributeRouteModel BuildRouteModel(string pathSegment, bool appAware = false) - { - StringBuilder path = new(); - path.Append(pathSegment.EnsureSurroundedWith('/')); - - path.Append("{zero_app_key}/"); - // TODO add route constraint which only allows registered app-ids - // see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/ - - path.Append("backoffice/[controller]"); - - return new AttributeRouteModel(new RouteAttribute(path.ToString())); - } -} \ No newline at end of file diff --git a/zero.Backoffice/ZeroBackofficeMetaInfo.cs b/zero.Backoffice/ZeroBackofficeMetaInfo.cs deleted file mode 100644 index 2608dd21..00000000 --- a/zero.Backoffice/ZeroBackofficeMetaInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Text.Json.Serialization; - -namespace zero.Backoffice; - -internal class ZeroBackofficeMetaInfo -{ - [JsonPropertyName("zeroVersion")] - public string ZeroVersion { get; set; } - - [JsonPropertyName("appVersion")] - public string AppVersion { get; set; } - - [JsonPropertyName("appLastModifiedDate")] - public DateTimeOffset AppLastModifiedDate { get; set; } -} \ No newline at end of file diff --git a/zero.Backoffice/ZeroBackofficeModel.cs b/zero.Backoffice/ZeroBackofficeModel.cs deleted file mode 100644 index 75df5874..00000000 --- a/zero.Backoffice/ZeroBackofficeModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace zero.Backoffice; - -internal class ZeroBackofficeModel -{ - public ZeroBackofficeMetaInfo Meta { get; set; } -} - - -internal class ZeroVueManifest -{ - -} - - -internal class ZeroVueManifestFile -{ - -} \ No newline at end of file diff --git a/zero.Backoffice/ZeroBackofficeMvcOptions.cs b/zero.Backoffice/ZeroBackofficeMvcOptions.cs deleted file mode 100644 index 449cd166..00000000 --- a/zero.Backoffice/ZeroBackofficeMvcOptions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace zero.Backoffice; - -internal class ZeroBackofficeMvcOptions : IConfigureOptions -{ - IZeroOptions Options { get; set; } - - public ZeroBackofficeMvcOptions(IZeroOptions options) - { - Options = options; - } - - public void Configure(MvcOptions options) - { - options.Conventions.Add(new ZeroBackofficeControllerModelConvention(Options.ZeroPath + "/api", Options.Applications.Count > 1)); - } -} \ No newline at end of file diff --git a/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs b/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs deleted file mode 100644 index 2e4a440e..00000000 --- a/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Builder; - -namespace zero.Backoffice; - -public static class ZeroEndpointRouteBuilderExtensions -{ - public static void MapZeroBackoffice(this IZeroEndpointRouteBuilder endpoints, string path = "/zero") - { - endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "{**path}", "Index", "ZeroIndex"); - //endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "backoffice/{**path}", "Index", "NotFoundZeroApi"); - //app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path + "/api"), app1 => - //{ - // app1.UseEndpoints(endpoints => - // { - // //IZeroOptions options = app.ApplicationServices.GetService(); // TODO oO - // // see https://our.umbraco.com/documentation/reference/routing/custom-routes#where-to-put-your-routing-logic - // //string path = options.BackofficePath.EnsureStartsWith('/').TrimEnd('/'); - // //endpoints.MapFallbackToController(path + "/{**path}", "Index", "ZeroIndex"); - - // //endpoints.MapControllers(); - // }); - //}); - } -} diff --git a/zero.Backoffice/zero.Backoffice.csproj b/zero.Backoffice/zero.Backoffice.csproj deleted file mode 100644 index 7ff80742..00000000 --- a/zero.Backoffice/zero.Backoffice.csproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - zero.Backoffice - 0.1.0 - preview - net6.0 - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/zero.Backoffice/zero.Backoffice.targets b/zero.Backoffice/zero.Backoffice.targets deleted file mode 100644 index 0bcc4d76..00000000 --- a/zero.Backoffice/zero.Backoffice.targets +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - $(PrepareForRunDependsOn); - CopyZeroBackofficeUi - - - - - - - - - - \ No newline at end of file diff --git a/zero.Core/Applications/Application.cs b/zero.Core/Applications/Application.cs index 5275d43c..6e723a23 100644 --- a/zero.Core/Applications/Application.cs +++ b/zero.Core/Applications/Application.cs @@ -1,10 +1,9 @@ -namespace zero.Applications; +namespace zero.Applications; /// /// An application is a website or app. zero can host multiple websites at once which share common assets /// -[RavenCollection("Applications")] -public class Application : ZeroEntity +public class Application { /// /// Raven database name for application data diff --git a/zero.Demo/zero.Demo.csproj b/zero.Demo/zero.Demo.csproj index c43da96a..a6a4ea6f 100644 --- a/zero.Demo/zero.Demo.csproj +++ b/zero.Demo/zero.Demo.csproj @@ -12,9 +12,6 @@ - - - diff --git a/zero.sln b/zero.sln index e8fcad10..57a79e97 100644 --- a/zero.sln +++ b/zero.sln @@ -5,50 +5,14 @@ VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Commerce", "plugins\zero.Commerce\zero.Commerce.csproj", "{63A8AD15-15F0-4555-BD62-C38B4465FFC1}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1CE271AD-3D9F-46EA-9938-066560A77E54}" - ProjectSection(SolutionItems) = preProject - build\build-bootstrap.ps1 = build\build-bootstrap.ps1 - build\build-tmp.ps1 = build\build-tmp.ps1 - build\build.ps1 = build\build.ps1 - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Stories", "plugins\zero.Stories\zero.Stories.csproj", "{C23CF90A-DB90-427F-816C-0E2FE20E29D0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Forms", "plugins\zero.Forms\zero.Forms.csproj", "{A8E5F34F-5400-4F92-96C6-7F91645BC220}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{6FAA92A8-CA1A-48EA-9857-C9092971B4D1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Backoffice", "zero.Backoffice\zero.Backoffice.csproj", "{355432DA-01AF-4E1E-B87F-8A8D99E52411}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Core", "zero.Core\zero.Core.csproj", "{CED2A7FA-8D35-4A2A-AF57-8B95307547CB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Web", "zero.Web\zero.Web.csproj", "{1E4EE00E-96BB-4382-AE6D-4AA2B8C600B7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Api", "zero.Api\zero.Api.csproj", "{C0442589-3915-43B5-9F78-2D5F9E8D8C94}" -EndProject -Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "zero.Backoffice.UI", "zero.Backoffice.UI\", "{8CE1A69A-35DB-4748-AE1C-86F5BC2E11D4}" - ProjectSection(WebsiteProperties) = preProject - TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5" - Debug.AspNetCompiler.VirtualPath = "/localhost_56763" - Debug.AspNetCompiler.PhysicalPath = "zero.Backoffice.UI\" - Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_56763\" - Debug.AspNetCompiler.Updateable = "true" - Debug.AspNetCompiler.ForceOverwrite = "true" - Debug.AspNetCompiler.FixedNames = "false" - Debug.AspNetCompiler.Debug = "True" - Release.AspNetCompiler.VirtualPath = "/localhost_56763" - Release.AspNetCompiler.PhysicalPath = "zero.Backoffice.UI\" - Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_56763\" - Release.AspNetCompiler.Updateable = "true" - Release.AspNetCompiler.ForceOverwrite = "true" - Release.AspNetCompiler.FixedNames = "false" - Release.AspNetCompiler.Debug = "False" - VWDPort = "56763" - SlnRelativePath = "zero.Backoffice.UI\" - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Demo", "zero.Demo\zero.Demo.csproj", "{8AD56129-2104-4DF5-A08E-1A94A8EC205B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -67,30 +31,10 @@ Global {A8E5F34F-5400-4F92-96C6-7F91645BC220}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8E5F34F-5400-4F92-96C6-7F91645BC220}.Release|Any CPU.ActiveCfg = Release|Any CPU {A8E5F34F-5400-4F92-96C6-7F91645BC220}.Release|Any CPU.Build.0 = Release|Any CPU - {355432DA-01AF-4E1E-B87F-8A8D99E52411}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {355432DA-01AF-4E1E-B87F-8A8D99E52411}.Debug|Any CPU.Build.0 = Debug|Any CPU - {355432DA-01AF-4E1E-B87F-8A8D99E52411}.Release|Any CPU.ActiveCfg = Release|Any CPU - {355432DA-01AF-4E1E-B87F-8A8D99E52411}.Release|Any CPU.Build.0 = Release|Any CPU {CED2A7FA-8D35-4A2A-AF57-8B95307547CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {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 - {C0442589-3915-43B5-9F78-2D5F9E8D8C94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C0442589-3915-43B5-9F78-2D5F9E8D8C94}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C0442589-3915-43B5-9F78-2D5F9E8D8C94}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C0442589-3915-43B5-9F78-2D5F9E8D8C94}.Release|Any CPU.Build.0 = Release|Any CPU - {8CE1A69A-35DB-4748-AE1C-86F5BC2E11D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8CE1A69A-35DB-4748-AE1C-86F5BC2E11D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8CE1A69A-35DB-4748-AE1C-86F5BC2E11D4}.Release|Any CPU.ActiveCfg = Debug|Any CPU - {8CE1A69A-35DB-4748-AE1C-86F5BC2E11D4}.Release|Any CPU.Build.0 = Debug|Any CPU - {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE