From e8159f8eb0b63f7fa2d6169dd35b91cd67a73230 Mon Sep 17 00:00:00 2001 From: Tobias Klika Date: Thu, 16 Dec 2021 00:19:51 +0100 Subject: [PATCH] start media section --- .../ZeroApiEntityStoreController.cs | 12 +- .../ZeroApiTreeEntityStoreController.cs | 12 +- .../Media/Indexes/zero_Api_Media_Listing.cs | 6 +- zero.Api/Endpoints/Media/Maps/MediaBasic.cs | 12 +- .../Media/Maps/MediaMapperProfile.cs | 8 +- zero.Api/Endpoints/Media/MediaController.cs | 26 +- zero.Backoffice.UI/app/core/zeroRuntime.ts | 3 +- zero.Backoffice.UI/app/modules/index.ts | 3 +- zero.Backoffice.UI/app/modules/media/api.ts | 17 + .../app/modules/media/detail.vue | 12 + zero.Backoffice.UI/app/modules/media/index.ts | 10 + .../app/modules/media/overview.vue | 89 ++ .../modules/media/partials/overview-item.vue | 156 ++++ .../app/modules/media/plugin.ts | 17 + .../app/modules/media/schemas/editor.ts | 12 + .../app/modules/media/schemas/list.ts | 19 + .../app/modules/media/ui-countrypicker.vue | 61 ++ zero.Backoffice.UI/app/modules/media/ui.d.ts | 5 + .../pickers/languagePicker/languagepicker.vue | 58 -- .../old_app/components/pickers/pick.vue | 769 ------------------ 20 files changed, 443 insertions(+), 864 deletions(-) create mode 100644 zero.Backoffice.UI/app/modules/media/api.ts create mode 100644 zero.Backoffice.UI/app/modules/media/detail.vue create mode 100644 zero.Backoffice.UI/app/modules/media/index.ts create mode 100644 zero.Backoffice.UI/app/modules/media/overview.vue create mode 100644 zero.Backoffice.UI/app/modules/media/partials/overview-item.vue create mode 100644 zero.Backoffice.UI/app/modules/media/plugin.ts create mode 100644 zero.Backoffice.UI/app/modules/media/schemas/editor.ts create mode 100644 zero.Backoffice.UI/app/modules/media/schemas/list.ts create mode 100644 zero.Backoffice.UI/app/modules/media/ui-countrypicker.vue create mode 100644 zero.Backoffice.UI/app/modules/media/ui.d.ts delete mode 100644 zero.Backoffice.UI/old_app/components/pickers/languagePicker/languagepicker.vue delete mode 100644 zero.Backoffice.UI/old_app/components/pickers/pick.vue diff --git a/zero.Api/Abstractions/ZeroApiEntityStoreController.cs b/zero.Api/Abstractions/ZeroApiEntityStoreController.cs index 9225cd9c..8e589240 100644 --- a/zero.Api/Abstractions/ZeroApiEntityStoreController.cs +++ b/zero.Api/Abstractions/ZeroApiEntityStoreController.cs @@ -25,7 +25,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> EmptyModel(string flavorAlias = null, Action modify = null) where T : DisplayModel + protected async Task> EmptyModel(string flavorAlias = null, Action modify = null) { TModel model = await Store.Empty(flavorAlias); @@ -54,7 +54,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> GetModel(string id, string changeVector = null) where T : DisplayModel + protected async Task> GetModel(string id, string changeVector = null) { TModel model = await Store.Load(id, changeVector); @@ -84,7 +84,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> GetModels(ListQuery query) where T : BasicModel + protected async Task> GetModels(ListQuery query) { query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); query.SearchSelector ??= x => x.Name; @@ -103,7 +103,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> GetModelsByIndex(ListQuery query) where T : BasicModel where TIndex : AbstractCommonApiForIndexes, new() + protected async Task> GetModelsByIndex(ListQuery query) where TIndex : AbstractCommonApiForIndexes, new() { query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); query.SearchSelector ??= x => x.Name; @@ -122,7 +122,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> CreateModel(T saveModel) where T : SaveModel where TEdit : DisplayModel + protected 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); @@ -156,7 +156,7 @@ public abstract class ZeroApiEntityStoreController : ZeroApiCont } - protected async Task> UpdateModel(string id, T updateModel, string changeToken = null) where T : SaveModel where TEdit : DisplayModel + protected async Task> UpdateModel(string id, T updateModel, string changeToken = null) where T : ZeroIdEntity { if (id != updateModel.Id) { diff --git a/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs b/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs index 89ff9021..80581d73 100644 --- a/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs +++ b/zero.Api/Abstractions/ZeroApiTreeEntityStoreController.cs @@ -10,7 +10,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi public ZeroApiTreeEntityStoreController(TStore store) : base(store) { } - protected async Task> GetChildModels(string parentId, ListQuery query) where T : BasicModel + protected async Task> GetChildModels(string parentId, ListQuery query) { query.OrderQuery ??= q => q.OrderByDescending(x => x.CreatedDate); Paged result = await Store.LoadChildren(parentId, query.Page, query.PageSize, q => q.Filter(query)); @@ -28,7 +28,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi } - protected async Task> GetChildModelsByIndex(string parentId, ListQuery query) where T : BasicModel where TIndex : AbstractCommonApiForIndexes, new() + 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(parentId, query.Page, query.PageSize, q => q.Filter(query)); @@ -52,7 +52,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi } - protected async Task> MoveModel(string pageId, string newParentId) where TEdit : DisplayModel + protected async Task> MoveModel(string pageId, string newParentId) { return await PutOperation(async () => await Store.Move(pageId, newParentId)); } @@ -64,7 +64,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi } - protected async Task> CopyModel(string pageId, string newParentId) where TEdit : DisplayModel + protected async Task> CopyModel(string pageId, string newParentId) { return await PutOperation(async () => await Store.Copy(pageId, newParentId)); } @@ -76,7 +76,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi } - protected async Task> CopyModelWithDescendants(string pageId, string newParentId) where TEdit : DisplayModel + protected async Task> CopyModelWithDescendants(string pageId, string newParentId) { return await PutOperation(async () => await Store.CopyWithDescendants(pageId, newParentId)); } @@ -103,7 +103,7 @@ public abstract class ZeroApiTreeEntityStoreController : ZeroApi } - async Task> PutOperation(Func>> action) where TEdit : DisplayModel + async Task> PutOperation(Func>> action) { Result result = await action(); diff --git a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs b/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs index c0a262be..cafad3f8 100644 --- a/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs +++ b/zero.Api/Endpoints/Media/Indexes/zero_Api_Media_Listing.cs @@ -9,10 +9,14 @@ public class zero_Api_Media_Listing : ZeroIndex Map = items => items.Select(item => new { Name = item.Name, - ParentId = item.ParentId + ParentId = item.ParentId, + CreatedDate = item.CreatedDate, + Type = item.Type }); Index(x => x.Name, FieldIndexing.Search); Index(x => x.ParentId, FieldIndexing.Exact); + Index(x => x.CreatedDate, FieldIndexing.Exact); + Index(x => x.Type, 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 index ead721df..3cbaae97 100644 --- a/zero.Api/Endpoints/Media/Maps/MediaBasic.cs +++ b/zero.Api/Endpoints/Media/Maps/MediaBasic.cs @@ -1,8 +1,14 @@ namespace zero.Api.Endpoints.Media; -public class MediaBasic : BasicModel +public class MediaBasic : ZeroIdEntity { - public bool IsPreferred { get; set; } + public string ParentId { get; set; } - public string Code { get; set; } + public string Name { get; set; } + + public bool IsFolder { get; set; } + + public string Image { get; set; } + + public int Children { get; set; } } \ No newline at end of file diff --git a/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs b/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs index 472376e7..b23350af 100644 --- a/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs +++ b/zero.Api/Endpoints/Media/Maps/MediaMapperProfile.cs @@ -14,8 +14,12 @@ public class MediaMapperProfile : ZeroMapperProfile protected virtual void Map(zero.Media.Media source, MediaBasic target, IZeroMapperContext ctx) { - this.MapBasicData(source, target); - + target.Id = source.Id; + target.Name = source.Name; + target.ParentId = source.ParentId; + target.IsFolder = source.Type == MediaType.Folder; + target.Image = null; + target.Children = 0; } protected virtual void Map(zero.Media.Media source, MediaEdit target, IZeroMapperContext ctx) diff --git a/zero.Api/Endpoints/Media/MediaController.cs b/zero.Api/Endpoints/Media/MediaController.cs index ec5eca74..9534d305 100644 --- a/zero.Api/Endpoints/Media/MediaController.cs +++ b/zero.Api/Endpoints/Media/MediaController.cs @@ -17,28 +17,20 @@ public class MediaController : ZeroApiTreeEntityStoreController> Empty(MediaType type, string flavor = null) => await EmptyModel(flavor, x => x.Type = type); + public virtual async Task> Empty(MediaType type, string flavor = null) => await EmptyModel(flavor, x => x.Type = type); [HttpGet("{id}")] [ZeroAuthorize(MediaPermissions.Read)] - public virtual async Task> Get(string id, string changeVector = null) + public virtual async Task> Get(string id, string changeVector = null) => await GetModel(id, changeVector); + + + [HttpGet("{parentId}/children")] + [ZeroAuthorize(MediaPermissions.Read)] + public virtual async Task> GetChildren(string parentId, [FromQuery] ListQuery query) { - zero.Media.Media model = await Store.Load(id, changeVector); - - if (model == null) - { - return NotFound(); - } - - HttpContext.Items[ApiConstants.ChangeToken] = Store.GetChangeToken(model); - - if (model.Type == MediaType.Folder) - { - return Mapper.Map(model); - } - - return Mapper.Map(model); + query.OrderQuery = q => q.OrderBy(x => x.Type).OrderByDescending(x => x.CreatedDate); + return await GetChildModelsByIndex(parentId == "root" ? null : parentId, query); } diff --git a/zero.Backoffice.UI/app/core/zeroRuntime.ts b/zero.Backoffice.UI/app/core/zeroRuntime.ts index d8f876e6..367c68c2 100644 --- a/zero.Backoffice.UI/app/core/zeroRuntime.ts +++ b/zero.Backoffice.UI/app/core/zeroRuntime.ts @@ -9,7 +9,7 @@ import registerComponents from '../components/register'; import registerFormComponents from '../forms/register'; import registerEditorComponents from '../editor/register'; import { getRouterConfig, appendRouterGuards } from './router/routerConfig'; -import { countryPlugin, applicationPlugin, settingsPlugin, languagePlugin } from '../modules'; +import { countryPlugin, applicationPlugin, settingsPlugin, languagePlugin, mediaPlugin } from '../modules'; import { ZeroSchema } from 'zero/schemas'; import { ZeroSchemaProp } from './zero'; import * as zeroOptions from '../options'; @@ -86,6 +86,7 @@ export class ZeroRuntime implements Zero applicationPlugin.install(pluginOptions); settingsPlugin.install(pluginOptions); languagePlugin.install(pluginOptions); + mediaPlugin.install(pluginOptions); } diff --git a/zero.Backoffice.UI/app/modules/index.ts b/zero.Backoffice.UI/app/modules/index.ts index 78545f26..c1bb5a22 100644 --- a/zero.Backoffice.UI/app/modules/index.ts +++ b/zero.Backoffice.UI/app/modules/index.ts @@ -2,4 +2,5 @@ export * from './countries'; export * from './applications'; export * from './settings'; -export * from './languages'; \ No newline at end of file +export * from './languages'; +export * from './media'; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/api.ts b/zero.Backoffice.UI/app/modules/media/api.ts new file mode 100644 index 00000000..811788be --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/api.ts @@ -0,0 +1,17 @@ +import { MediaType } from 'zero/media'; +import { get, post, put, del, ApiRequestConfig, ApiRequestQuery } from '../../services/request'; + +export default { + + getEmpty: (type: MediaType, flavor?: string, config?: ApiRequestConfig) => get("media/empty", { ...config, params: { type, flavor } }), + + getById: (id: string, changeVector?: string, config?: ApiRequestConfig) => get('media/' + id, { ...config, params: { changeVector } }), + + getChildren: (parentId: string, query: ApiRequestQuery, config?: ApiRequestConfig) => get(`media/${parentId}/children`, { ...config, params: { ...query } }), + + //create: (model: any, config?: ApiRequestConfig) => post('countries', model, config), + + //update: (model: any, config?: ApiRequestConfig) => put('countries/' + model.id, model, config), + + //delete: (id: string, config?: ApiRequestConfig) => del('countries/' + id, config), +}; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/detail.vue b/zero.Backoffice.UI/app/modules/media/detail.vue new file mode 100644 index 00000000..00bd85a0 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/detail.vue @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/index.ts b/zero.Backoffice.UI/app/modules/media/index.ts new file mode 100644 index 00000000..882091cd --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/index.ts @@ -0,0 +1,10 @@ +import api from './api'; +import editor from './schemas/editor'; +//import list from './schemas/list'; +import plugin from './plugin'; + +export { + api as mediaApi, + editor as mediaSchema, + plugin as mediaPlugin +}; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/overview.vue b/zero.Backoffice.UI/app/modules/media/overview.vue new file mode 100644 index 00000000..dbe09b04 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/overview.vue @@ -0,0 +1,89 @@ + + + + + + + \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/partials/overview-item.vue b/zero.Backoffice.UI/app/modules/media/partials/overview-item.vue new file mode 100644 index 00000000..9e4ac9c0 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/partials/overview-item.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/zero.Backoffice.UI/app/modules/media/plugin.ts b/zero.Backoffice.UI/app/modules/media/plugin.ts new file mode 100644 index 00000000..519db62e --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/plugin.ts @@ -0,0 +1,17 @@ +import { ZeroPlugin, ZeroPluginOptions } from '../../core'; +import { defineAsyncComponent } from 'vue'; + +export default { + name: "zero.countries", + + install(app: ZeroPluginOptions) + { + //app.vue.component('ui-countrypicker', defineAsyncComponent(() => import('./ui-countrypicker.vue'))); + + app.route({ name: 'media', path: '/media/:parentId?', component: () => import('./overview.vue'), props: true }); + app.route({ name: 'media-edit', path: '/media/edit/:id?', component: () => import('./detail.vue'), props: true }); + + //app.schema('countries', () => import('./schemas/list')); + //app.schema('countries:edit', () => import('./schemas/editor')); + } +} as ZeroPlugin; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/schemas/editor.ts b/zero.Backoffice.UI/app/modules/media/schemas/editor.ts new file mode 100644 index 00000000..d884066b --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/schemas/editor.ts @@ -0,0 +1,12 @@ + +import Editor from '../../../editor/editor'; + +const editor = new Editor('countries:edit', '@country.fields.'); +editor.blueprintAlias = 'country'; + +editor.field('name', { label: '@ui.name' }).text(120).required(); +//editor.field('alias', { label: '@ui.alias' }).text().required(); +editor.field('code').text(2).required(); +editor.field('isPreferred').toggle(); + +export default editor; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/schemas/list.ts b/zero.Backoffice.UI/app/modules/media/schemas/list.ts new file mode 100644 index 00000000..4e575282 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/schemas/list.ts @@ -0,0 +1,19 @@ + +import List from '../../../schemas/list/list'; +import api from '../api'; + +const list = new List('countries'); +const prefix = '@country.fields.'; + +list.templateLabel = x => prefix + x; +list.link = 'countries-edit'; + +list.onFetch(filter => api.getByQuery(filter)); + +list.column('flag', { width: 62, canSort: false, hideLabel: true }).custom((value, model) => ``, true, 'flag'); +list.column('name').name(); +list.column('code').custom(val => val.toUpperCase()); +list.column('isPreferred').boolean(); +list.column('isActive').active(); + +export default list; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/ui-countrypicker.vue b/zero.Backoffice.UI/app/modules/media/ui-countrypicker.vue new file mode 100644 index 00000000..34356f88 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/ui-countrypicker.vue @@ -0,0 +1,61 @@ + + + + \ No newline at end of file diff --git a/zero.Backoffice.UI/app/modules/media/ui.d.ts b/zero.Backoffice.UI/app/modules/media/ui.d.ts new file mode 100644 index 00000000..2f080111 --- /dev/null +++ b/zero.Backoffice.UI/app/modules/media/ui.d.ts @@ -0,0 +1,5 @@ + +declare module 'zero/media' +{ + export type MediaType = 'folder' | 'file' | 'image'; +} \ No newline at end of file diff --git a/zero.Backoffice.UI/old_app/components/pickers/languagePicker/languagepicker.vue b/zero.Backoffice.UI/old_app/components/pickers/languagePicker/languagepicker.vue deleted file mode 100644 index c122cbfb..00000000 --- a/zero.Backoffice.UI/old_app/components/pickers/languagePicker/languagepicker.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - \ No newline at end of file diff --git a/zero.Backoffice.UI/old_app/components/pickers/pick.vue b/zero.Backoffice.UI/old_app/components/pickers/pick.vue deleted file mode 100644 index 1c512f40..00000000 --- a/zero.Backoffice.UI/old_app/components/pickers/pick.vue +++ /dev/null @@ -1,769 +0,0 @@ - - - - - - \ No newline at end of file