From 6460de963afd3a61038e4d0efb792f98559dd5e0 Mon Sep 17 00:00:00 2001 From: antoine Date: Wed, 4 Jun 2025 17:59:55 +0200 Subject: [PATCH 01/14] Allow sub-entities --- demo/app/Sharp/Entities/PostBlockEntity.php | 17 ++- .../Sharp/Entities/PostBlockTextEntity.php | 13 +++ .../Sharp/Entities/PostBlockVideoEntity.php | 13 +++ .../Sharp/Entities/PostBlockVisualsEntity.php | 13 +++ demo/app/Sharp/Posts/Blocks/PostBlockList.php | 2 +- resources/js/Layouts/Layout.vue | 6 +- resources/js/entity-list/EntityList.ts | 27 +---- .../js/entity-list/components/EntityList.vue | 35 +++--- resources/js/types/generated.d.ts | 19 ++-- resources/js/types/routes.d.ts | 8 ++ src/Data/EntityList/EntityListConfigData.php | 2 +- src/Data/EntityList/EntityListData.php | 10 +- src/Data/EntityList/EntityListItemMeta.php | 15 +++ .../EntityList/EntityListMultiformData.php | 18 --- .../EntityList/EntityListSubEntityData.php | 29 +++++ .../QuickCreate/QuickCreationCommand.php | 11 +- src/EntityList/SharpEntityList.php | 16 ++- src/Http/Context/SharpBreadcrumb.php | 11 +- ...tityListQuickCreationCommandController.php | 10 +- src/Http/Controllers/EntityListController.php | 103 +++++++++++++++--- src/Utils/Entities/BaseSharpEntity.php | 6 + src/Utils/Entities/SharpEntity.php | 52 +++++++-- src/routes/api.php | 4 +- .../Http/Api/ApiEntityListControllerTest.php | 60 +++++----- tests/Http/EntityListControllerTest.php | 59 +++++++--- tests/Http/FiltersInRequestTest.php | 102 +++++++++++------ tests/Unit/EntityList/SharpEntityListTest.php | 2 +- 27 files changed, 460 insertions(+), 203 deletions(-) create mode 100644 demo/app/Sharp/Entities/PostBlockTextEntity.php create mode 100644 demo/app/Sharp/Entities/PostBlockVideoEntity.php create mode 100644 demo/app/Sharp/Entities/PostBlockVisualsEntity.php create mode 100644 src/Data/EntityList/EntityListItemMeta.php delete mode 100644 src/Data/EntityList/EntityListMultiformData.php create mode 100644 src/Data/EntityList/EntityListSubEntityData.php diff --git a/demo/app/Sharp/Entities/PostBlockEntity.php b/demo/app/Sharp/Entities/PostBlockEntity.php index 2d5c3891a..0687a5fc7 100644 --- a/demo/app/Sharp/Entities/PostBlockEntity.php +++ b/demo/app/Sharp/Entities/PostBlockEntity.php @@ -15,12 +15,21 @@ class PostBlockEntity extends SharpEntity protected ?string $policy = PostBlockPolicy::class; protected string $label = 'Block'; - public function getMultiforms(): array + // public function getMultiforms(): array + // { + // return [ + // 'text' => [PostBlockTextForm::class, 'Text block'], + // 'visuals' => [PostBlockVisualsForm::class, 'Visuals block'], + // 'video' => [PostBlockVideoForm::class, 'Video block'], + // ]; + // } + + public function getSubEntities(): array { return [ - 'text' => [PostBlockTextForm::class, 'Text block'], - 'visuals' => [PostBlockVisualsForm::class, 'Visuals block'], - 'video' => [PostBlockVideoForm::class, 'Video block'], + 'text' => PostBlockTextEntity::class, + 'video' => PostBlockVideoEntity::class, + 'visuals' => PostBlockVisualsEntity::class, ]; } } diff --git a/demo/app/Sharp/Entities/PostBlockTextEntity.php b/demo/app/Sharp/Entities/PostBlockTextEntity.php new file mode 100644 index 000000000..024f7132b --- /dev/null +++ b/demo/app/Sharp/Entities/PostBlockTextEntity.php @@ -0,0 +1,13 @@ +configureMultiformAttribute('type') + $this->configureSubEntityAttribute('type') ->configureReorderable(new SimpleEloquentReorderHandler(PostBlock::class)) ->configureQuickCreationForm(); } diff --git a/resources/js/Layouts/Layout.vue b/resources/js/Layouts/Layout.vue index 8b48edf9c..abb9c0dd4 100644 --- a/resources/js/Layouts/Layout.vue +++ b/resources/js/Layouts/Layout.vue @@ -219,8 +219,8 @@ - - @@ -233,7 +233,7 @@
- + {{ __('sharp::menu.logout_label') }}
diff --git a/resources/js/entity-list/EntityList.ts b/resources/js/entity-list/EntityList.ts index 14d9ecfbb..d40459e71 100644 --- a/resources/js/entity-list/EntityList.ts +++ b/resources/js/entity-list/EntityList.ts @@ -14,7 +14,7 @@ export class EntityList implements EntityListData { config: EntityListData['config']; data: EntityListData['data']; fields: EntityListData['fields']; - forms: EntityListData['forms']; + subEntities: EntityListData['subEntities']; meta: EntityListData['meta']; pageAlert: EntityListData['pageAlert']; query: EntityListData['query']; @@ -110,31 +110,6 @@ export class EntityList implements EntityListData { return instance[this.config.instanceIdAttribute]; } - instanceUrl(instance: EntityListInstance): string | null { - const entityKey = this.entityKey; - const instanceId = this.instanceId(instance); - - if(!this.authorizations.view.includes(instanceId)) { - return null; - } - - const multiform = this.forms && Object.values(this.forms).find(form => form.instances.includes(instanceId)); - - if(this.config.hasShowPage) { - return route('code16.sharp.show.show', { - parentUri: getAppendableParentUri(), - entityKey: multiform ? `${entityKey}:${multiform.key}` : entityKey, - instanceId, - }); - } - - return route('code16.sharp.form.edit', { - parentUri: getAppendableParentUri(), - entityKey: multiform ? `${entityKey}:${multiform.key}` : entityKey, - instanceId, - }); - } - instanceState(instance: EntityListInstance): string | number | null { return this.config.state ? instance[this.config.state.attribute] diff --git a/resources/js/entity-list/components/EntityList.vue b/resources/js/entity-list/components/EntityList.vue index 2c858ff8c..39e977ca0 100644 --- a/resources/js/entity-list/components/EntityList.vue +++ b/resources/js/entity-list/components/EntityList.vue @@ -3,7 +3,7 @@ import { FilterManager } from "@/filters/FilterManager"; import { EntityList } from "../EntityList"; import { - CommandData, EntityListFieldData, EntityListMultiformData, EntityListQueryParamsData, + CommandData, EntityListFieldData, EntityListSubEntityData, EntityListQueryParamsData, EntityStateValueData, FilterData } from "@/types"; @@ -68,6 +68,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { useElementVisibility } from "@vueuse/core"; import StateBadge from "@/components/ui/StateBadge.vue"; + import Icon from "@/components/ui/Icon.vue"; // import StateBadgeTest from "@/components/dev/StateBadgeTest.vue"; const props = withDefaults(defineProps<{ @@ -175,7 +176,7 @@ }); } - async function onCreate(event: MouseEvent, form?: EntityListMultiformData) { + async function onCreate(event: MouseEvent, subEntity?: EntityListSubEntityData) { if(event.metaKey || event.ctrlKey || event.shiftKey) { return; } @@ -186,19 +187,18 @@ if(props.entityList.config.quickCreationForm) { await props.commands.send({ hasForm: true } as CommandData, { postCommand: route('code16.sharp.api.list.command.quick-creation-form.store', { - entityKey: form ? `${entityKey}:${form.key}` : entityKey, + entityKey, + formEntityKey: subEntity ? subEntity.entityKey : entityKey, }), getForm: route('code16.sharp.api.list.command.quick-creation-form.create', { - entityKey: form ? `${entityKey}:${form.key}` : entityKey, + entityKey, + formEntityKey: subEntity ? subEntity.entityKey : entityKey, }), query: props.entityList.query, - entityKey: form ? `${entityKey}:${form.key}` : entityKey, + entityKey: subEntity ? subEntity.entityKey : entityKey, }); } else { - router.visit(route('code16.sharp.form.create', { - parentUri: getAppendableParentUri(), - entityKey: form ? `${entityKey}:${form.key}` : entityKey, - })); + router.visit(subEntity.formCreateUrl); } } @@ -469,7 +469,7 @@