using FluentValidation; using Raven.Client.Documents; using Raven.Client.Documents.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using zero.Core.Database.Indexes; namespace zero.Core.Collections { public class MediaFolderCollection : EntityStore, IMediaFolderCollection { public MediaFolderCollection(IStoreContext context) : base(context) { Options = new(true); } /// public override Task> Save(MediaFolder model) { model.IsActive = true; return base.Save(model); } /// public async Task> LoadByParent(string parentId = null) { return await Session.Query() .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) .OrderByDescending(x => x.Name) .ToListAsync(); } /// public async Task> Move(string id, string parentId) { MediaFolder model = await Load(id); MediaFolder parent = await Load(parentId); if (model == null || (!parentId.IsNullOrEmpty() && parent == null)) { return EntityResult.Fail("@errors.idnotfound"); } model.ParentId = parent?.Id; return await Save(model); } /// 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> GetHierarchy(string id) { MediaFolder_ByHierarchy.Result result = await Session.Query() .ProjectInto() .Include(x => x.Path.Select(p => p.Id)) .FirstOrDefaultAsync(x => x.Id == id); if (result == null) { return new List(); } List ids = result.Path.Select(x => x.Id).ToList(); ids.Add(id); return (await Session.LoadAsync(ids)).Select(x => x.Value).ToList(); } /// protected override void ValidationRules(ZeroValidator validator) { validator.RuleFor(x => x.Name).Length(2, 80); validator.RuleFor(x => x.IsActive).Equal(true); validator.RuleFor(x => x.ParentId).Exists(Context.Store); } } public interface IMediaFolderCollection : IEntityStore { /// /// Get hierarchy for a folder /// Task> GetHierarchy(string id); /// /// Get all folders with the specified parent or on root /// Task> LoadByParent(string parentId = null); /// /// Get all folders with the specified parent or on root for tree output /// Task> LoadAsTree(string parentId = null, string activeId = null); /// /// Move a folder to a new parent /// Task> Move(string id, string parentId); } }