From a79b33ae8b80fc0a54b909b04afdde90c9ae35ad Mon Sep 17 00:00:00 2001 From: Tobias Klika Date: Thu, 3 Sep 2020 14:50:41 +0200 Subject: [PATCH] edit, move + delete works for media files + folders now --- zero.Core/Api/BackofficeApi.cs | 1 + zero.Core/Api/MediaApi.cs | 22 +++ zero.Core/Api/MediaFolderApi.cs | 48 +++-- .../App/components/datagrid/datagrid.vue | 88 ++++++++- .../App/components/overlays/confirm.vue | 5 + .../pickers/mediaPicker/overlay.vue | 4 +- zero.Web.UI/App/pages/media/media-item.vue | 4 +- zero.Web.UI/App/pages/media/media.vue | 112 ++++++++++- .../App/pages/media/{ => overlays}/folder.vue | 23 +-- zero.Web.UI/App/pages/media/overlays/move.vue | 179 ++++++++++++++++++ .../media/{ => overlays}/upload-status.vue | 0 zero.Web.UI/App/resources/media-folder.js | 5 + zero.Web.UI/App/resources/media.js | 5 + zero.Web/Controllers/MediaController.cs | 4 + zero.Web/Controllers/MediaFolderController.cs | 5 + zero.Web/Controllers/PagesController.cs | 16 +- zero.Web/Models/ActionCopyModel.cs | 11 ++ .../Resources/Localization/zero.en-us.json | 14 ++ 18 files changed, 489 insertions(+), 57 deletions(-) rename zero.Web.UI/App/pages/media/{ => overlays}/folder.vue (76%) create mode 100644 zero.Web.UI/App/pages/media/overlays/move.vue rename zero.Web.UI/App/pages/media/{ => overlays}/upload-status.vue (100%) create mode 100644 zero.Web/Models/ActionCopyModel.cs diff --git a/zero.Core/Api/BackofficeApi.cs b/zero.Core/Api/BackofficeApi.cs index aca0ec13..c895d555 100644 --- a/zero.Core/Api/BackofficeApi.cs +++ b/zero.Core/Api/BackofficeApi.cs @@ -229,6 +229,7 @@ namespace zero.Core.Api public async Task> DeleteById(string id) where T : IZeroIdEntity { using IAsyncDocumentSession session = Raven.OpenAsyncSession(); + session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false); T entity = await session.LoadAsync(id); IAppAwareEntity appAwareEntity = entity as IAppAwareEntity; diff --git a/zero.Core/Api/MediaApi.cs b/zero.Core/Api/MediaApi.cs index b5504cf1..04f093eb 100644 --- a/zero.Core/Api/MediaApi.cs +++ b/zero.Core/Api/MediaApi.cs @@ -111,6 +111,23 @@ namespace zero.Core.Api } + /// + public async Task> Move(string id, string parentId) + { + IMedia model = await GetById(id); + IMediaFolder parent = await GetById(parentId); + + if (model == null || (!parentId.IsNullOrEmpty() && parent == null)) + { + return EntityResult.Fail("@errors.idnotfound"); + } + + model.FolderId = parent?.Id; + + return await Save(model); + } + + /// public async Task> Delete(string id) { @@ -252,6 +269,11 @@ namespace zero.Core.Api /// Task> Save(IMedia model); + /// + /// Move a file to a new parent + /// + Task> Move(string id, string parentId); + /// /// Deletes a media item by Id /// diff --git a/zero.Core/Api/MediaFolderApi.cs b/zero.Core/Api/MediaFolderApi.cs index fd011c75..b3efd261 100644 --- a/zero.Core/Api/MediaFolderApi.cs +++ b/zero.Core/Api/MediaFolderApi.cs @@ -48,7 +48,7 @@ namespace zero.Core.Api IList folders = await session.Query() .Scope(Scope) .WhereIf(x => x.ParentId == parentId, !parentId.IsNullOrEmpty(), x => x.ParentId == null) - .OrderByDescending(x => x.Name) + .OrderByDescending(x => x.CreatedDate).ThenBy(x => x.Name) .ToListAsync(); @@ -103,18 +103,18 @@ namespace zero.Core.Api } } - if (parentId.IsNullOrEmpty()) - { - items.Add(new TreeItem() - { - Id = "recyclebin", - ParentId = null, - Sort = 99999, - Name = "@recyclebin.name", - Icon = "fth-trash", - HasChildren = false - }); - } + //if (parentId.IsNullOrEmpty()) + //{ + // items.Add(new TreeItem() + // { + // Id = "recyclebin", + // ParentId = null, + // Sort = 99999, + // Name = "@recyclebin.name", + // Icon = "fth-trash", + // HasChildren = false + // }); + //} return items; } @@ -152,6 +152,23 @@ namespace zero.Core.Api } + /// + public async Task> Move(string id, string parentId) + { + IMediaFolder model = await GetById(id); + IMediaFolder parent = await GetById(parentId); + + if (model == null || (!parentId.IsNullOrEmpty() && parent == null)) + { + return EntityResult.Fail("@errors.idnotfound"); + } + + model.ParentId = parent?.Id; + + return await Save(model); + } + + /// public async Task> Delete(string id) { @@ -187,6 +204,11 @@ namespace zero.Core.Api /// Task> Save(IMediaFolder model); + /// + /// Move a folder to a new parent + /// + Task> Move(string id, string parentId); + /// /// Deletes a folder /// diff --git a/zero.Web.UI/App/components/datagrid/datagrid.vue b/zero.Web.UI/App/components/datagrid/datagrid.vue index e404a647..354219c4 100644 --- a/zero.Web.UI/App/components/datagrid/datagrid.vue +++ b/zero.Web.UI/App/components/datagrid/datagrid.vue @@ -2,7 +2,9 @@
- +
+ +
@@ -19,6 +21,10 @@ + + + +
@@ -93,14 +99,27 @@ pageSize: 30, search: null }, - debouncedUpdate: null + debouncedUpdate: null, + actionProps: { + item: null + } }), + + computed: { + actionsDefined() + { + return this.$scopedSlots.hasOwnProperty('actions'); + } + }, + + mounted() { this.initialize(); }, + methods: { initialize() @@ -175,6 +194,65 @@ } this.debouncedUpdate(); + }, + + + // right clicked on an item + onRightClicked(item, ev) + { + if (this.actionsDefined) + { + ev.preventDefault(); + this.onActionsClicked(item, ev); + } + }, + + + // actions button clicked on item + onActionsClicked(item, ev) + { + let dropdown = this.$refs.dropdown; + + if (!this.actionsDefined || (typeof this.hasActions === 'function' && !this.hasActions(item))) + { + return; + } + + this.actionProps.item = item; + this.actionProps.event = ev; + + dropdown.toggle(); + + if (!dropdown.open) + { + return; + } + + this.$nextTick(() => + { + let target = ev.target; + do + { + if (target.classList.contains('ui-datagrid-cell')) + { + break; + } + } + while (target = target.parentElement); + + var width = 240; + + var position = { + x: ev.pageX, + y: ev.pageY + }; + + let element = dropdown.$el.querySelector('.ui-dropdown'); + + element.style.top = position.y + 'px'; + element.style.left = position.x + 'px'; + element.style.width = width + 'px'; + }); } } } @@ -211,4 +289,10 @@ font-size: 34px; margin-bottom: 20px; } + + .ui-datagrid-dropdown .ui-dropdown + { + position: fixed; + min-width: 200px; + } \ No newline at end of file diff --git a/zero.Web.UI/App/components/overlays/confirm.vue b/zero.Web.UI/App/components/overlays/confirm.vue index 53b36c2b..2c64a458 100644 --- a/zero.Web.UI/App/components/overlays/confirm.vue +++ b/zero.Web.UI/App/components/overlays/confirm.vue @@ -70,4 +70,9 @@ { margin-top: 30px; } + + .app-confirm p + { + line-height: 1.4; + } \ No newline at end of file diff --git a/zero.Web.UI/App/components/pickers/mediaPicker/overlay.vue b/zero.Web.UI/App/components/pickers/mediaPicker/overlay.vue index 97d0360c..d1b5f116 100644 --- a/zero.Web.UI/App/components/pickers/mediaPicker/overlay.vue +++ b/zero.Web.UI/App/components/pickers/mediaPicker/overlay.vue @@ -40,8 +40,8 @@ diff --git a/zero.Web.UI/App/pages/media/folder.vue b/zero.Web.UI/App/pages/media/overlays/folder.vue similarity index 76% rename from zero.Web.UI/App/pages/media/folder.vue rename to zero.Web.UI/App/pages/media/overlays/folder.vue index ecda15b6..2c2194af 100644 --- a/zero.Web.UI/App/pages/media/folder.vue +++ b/zero.Web.UI/App/pages/media/overlays/folder.vue @@ -1,12 +1,12 @@