diff --git a/resources/js/content/ContentEmbedManager.ts b/resources/js/content/ContentEmbedManager.ts index c726c34e3..7d6de18cc 100644 --- a/resources/js/content/ContentEmbedManager.ts +++ b/resources/js/content/ContentEmbedManager.ts @@ -1,5 +1,5 @@ import { Form } from "@/form/Form"; -import { EmbedData, FormData, FormEditorFieldData } from "@/types"; +import { EmbedData, FormData, FormEditorFieldData, RequestFieldContainerData } from "@/types"; import { api } from "@/api/api"; import { route } from "@/utils/url"; import { Show } from "@/show/Show"; @@ -97,7 +97,7 @@ export class ContentEmbedManager { }; } - postResolveForm(id: string, embed: EmbedData): Promise { + postResolveForm(id: string, embed: EmbedData, fieldContainerData: RequestFieldContainerData): Promise { const { entityKey, instanceId } = this.root; return api @@ -105,19 +105,27 @@ export class ContentEmbedManager { instanceId ? route('code16.sharp.api.embed.instance.form.show', { embedKey: embed.key, entityKey, instanceId }) : route('code16.sharp.api.embed.form.show', { embedKey: embed.key, entityKey }), - { ...this.contentEmbeds[embed.key]?.[id]?.value } + { ...this.contentEmbeds[embed.key]?.[id]?.value }, + { params: { ...fieldContainerData } }, ) .then(response => response.data); } - async postForm(id: string, embed: EmbedData, locale: string | null, data: EmbedData['value']): Promise<{ id:string }> { + async postForm( + id: string, + embed: EmbedData, + locale: string | null, + fieldContainerData: RequestFieldContainerData, + data: EmbedData['value'], + ): Promise<{ id:string }> { const { entityKey, instanceId } = this.root; const responseData = await api .post( instanceId ? route('code16.sharp.api.embed.instance.form.update', { embedKey: embed.key, entityKey, instanceId }) : route('code16.sharp.api.embed.form.update', { embedKey: embed.key, entityKey }), - { ...data } + { ...data }, + { params: { ...fieldContainerData } } ) .then(response => response.data); diff --git a/resources/js/form/Form.ts b/resources/js/form/Form.ts index 08d89bef5..3947a817c 100644 --- a/resources/js/form/Form.ts +++ b/resources/js/form/Form.ts @@ -42,18 +42,24 @@ export class Form implements FormData, CommandFormData, EventTarget { entityKey: string; instanceId: string | number | null; embedKey?: string; + embedEditorKey?: string; commandKey?: string; constructor( data: FormData | EmbedFormData, entityKey: string, instanceId: string | number | null, - additionalProps?: { embedKey?: string, commandKey?: string } + additionalProps?: { + embedKey?: string, + embedEditorKey?: string, + commandKey?: string, + } ) { Object.assign(this, data); this.entityKey = entityKey; this.instanceId = instanceId; this.embedKey = additionalProps?.embedKey; + this.embedEditorKey = additionalProps?.embedEditorKey; this.commandKey = additionalProps?.commandKey; } diff --git a/resources/js/form/components/fields/editor/extensions/embed/EditorEmbedModal.vue b/resources/js/form/components/fields/editor/extensions/embed/EditorEmbedModal.vue index 54c1b1f4b..d0ac8fb1f 100644 --- a/resources/js/form/components/fields/editor/extensions/embed/EditorEmbedModal.vue +++ b/resources/js/form/components/fields/editor/extensions/embed/EditorEmbedModal.vue @@ -16,23 +16,26 @@ } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import type FormComponent from "@/form/components/Form.vue"; + import { useFieldContainerData } from "@/form/useFieldContainerData"; const props = defineProps<{ field: FormEditorFieldData, editor: Editor, }>(); const parentForm = useParentForm(); - const embedManager = useParentEditor().embedManager; + const parentEditor = useParentEditor(); const modalEmbed = ref<{ id?: string, embed: EmbedData, locale: string | null, form?: Form, loading?: boolean } | null>(null); const modalForm = useTemplateRef>('modalForm'); const modalOpen = ref(false); + const fieldContainerData = useFieldContainerData(parentForm); async function postForm(data: EmbedData['value']) { modalEmbed.value.loading = true; - const { id } = await embedManager.postForm( + const { id } = await parentEditor.embedManager.postForm( modalEmbed.value.id, modalEmbed.value.embed, modalEmbed.value.locale, + fieldContainerData, data ) .finally(() => { @@ -51,12 +54,19 @@ async function open({ id, embed, locale }: { id?: string, embed: EmbedData, locale: string | null }) { if(Object.keys(embed.fields).length > 0) { - const embedForm = await embedManager.postResolveForm(id, embed); + const embedForm = await parentEditor.embedManager.postResolveForm(id, embed, fieldContainerData); modalEmbed.value = { id, embed, locale, - form: new Form(embedForm, parentForm.entityKey, parentForm.instanceId, { embedKey: embed.key }), + form: new Form( + embedForm, + parentForm.entityKey, + parentForm.instanceId, + { + embedKey: embed.key, + } + ), } modalOpen.value = true; } else { diff --git a/resources/js/form/useFieldContainerData.ts b/resources/js/form/useFieldContainerData.ts index dc84d425a..2ff927ef5 100644 --- a/resources/js/form/useFieldContainerData.ts +++ b/resources/js/form/useFieldContainerData.ts @@ -1,13 +1,16 @@ import { RequestFieldContainerData } from "@/types"; import { useParentCommands } from "@/commands/useCommands"; import { Form } from "@/form/Form"; +import { useParentEditor } from "@/form/components/fields/editor/useParentEditor"; export function useFieldContainerData(form: Form): RequestFieldContainerData { const parentCommands = useParentCommands(); + const parentEditor = useParentEditor(); return { embed_key: form.embedKey, + embed_editor_key: parentEditor?.props.field.key, entity_list_command_key: parentCommands?.commandContainer === 'entityList' ? form.commandKey : null, show_command_key: parentCommands?.commandContainer === 'show' ? form.commandKey : null, dashboard_command_key: parentCommands?.commandContainer === 'dashboard' ? form.commandKey : null, diff --git a/resources/js/types/generated.d.ts b/resources/js/types/generated.d.ts index 35bb75464..99ba2fb52 100644 --- a/resources/js/types/generated.d.ts +++ b/resources/js/types/generated.d.ts @@ -814,6 +814,7 @@ export type PieGraphWidgetData = { }; export type RequestFieldContainerData = { embed_key: string | null; + embed_editor_key: string | null; entity_list_command_key: string | null; show_command_key: string | null; dashboard_command_key: string | null; diff --git a/src/Data/RequestFieldContainerData.php b/src/Data/RequestFieldContainerData.php index 90d449ba6..e4b498e8d 100644 --- a/src/Data/RequestFieldContainerData.php +++ b/src/Data/RequestFieldContainerData.php @@ -9,6 +9,7 @@ final class RequestFieldContainerData extends Data { public function __construct( public ?string $embed_key, + public ?string $embed_editor_key, public ?string $entity_list_command_key, public ?string $show_command_key, public ?string $dashboard_command_key, @@ -19,6 +20,7 @@ public static function from(array $request): self { return new self( embed_key: $request['embed_key'] ?? null, + embed_editor_key: $request['embed_editor_key'] ?? null, entity_list_command_key: $request['entity_list_command_key'] ?? null, show_command_key: $request['show_command_key'] ?? null, dashboard_command_key: $request['dashboard_command_key'] ?? null, diff --git a/src/Http/Controllers/Api/Embeds/ApiEmbedsFormController.php b/src/Http/Controllers/Api/Embeds/ApiEmbedsFormController.php index 96fdac71f..17b7bfb7c 100644 --- a/src/Http/Controllers/Api/Embeds/ApiEmbedsFormController.php +++ b/src/Http/Controllers/Api/Embeds/ApiEmbedsFormController.php @@ -3,11 +3,13 @@ namespace Code16\Sharp\Http\Controllers\Api\Embeds; use Code16\Sharp\Data\Embeds\EmbedFormData; +use Code16\Sharp\Http\Controllers\Api\HandlesFieldContainer; use Code16\Sharp\Http\Controllers\Controller; class ApiEmbedsFormController extends Controller { use HandlesEmbed; + use HandlesFieldContainer; public function show(string $globalFilter, string $embedKey, string $entityKey, ?string $instanceId = null) { @@ -17,7 +19,7 @@ public function show(string $globalFilter, string $embedKey, string $entityKey, $this->authorizationManager->check('entity', $entityKey); } - $embed = $this->getEmbedFromKey($embedKey); + $embed = $this->getEmbedFromKey($entityKey, $embedKey); return EmbedFormData::from([ 'fields' => $embed->fields(), @@ -36,7 +38,7 @@ public function update(string $globalFilter, string $embedKey, string $entityKey $this->authorizationManager->check('create', $entityKey); } - $embed = $this->getEmbedFromKey($embedKey); + $embed = $this->getEmbedFromKey($entityKey, $embedKey); $data = $embed->updateContent( $embed->formatRequestData(request()->all()) diff --git a/src/Http/Controllers/Api/Embeds/HandlesEmbed.php b/src/Http/Controllers/Api/Embeds/HandlesEmbed.php index b065bb342..9294d15fa 100644 --- a/src/Http/Controllers/Api/Embeds/HandlesEmbed.php +++ b/src/Http/Controllers/Api/Embeds/HandlesEmbed.php @@ -2,15 +2,29 @@ namespace Code16\Sharp\Http\Controllers\Api\Embeds; +use Code16\Sharp\Data\RequestFieldContainerData; +use Code16\Sharp\Exceptions\SharpException; use Code16\Sharp\Form\Fields\Embeds\SharpFormEditorEmbed; -use Illuminate\Support\Str; +use Code16\Sharp\Form\Fields\SharpFormEditorField; +use Code16\Sharp\Utils\Entities\ValueObjects\EntityKey; trait HandlesEmbed { - protected function getEmbedFromKey(string $embedKey): SharpFormEditorEmbed - { - $embed = app(Str::replace('.', '\\', $embedKey)); - $embed->buildEmbedConfig(); + protected function getEmbedFromKey( + string $entityKey, + string $embedKey, + ?RequestFieldContainerData $requestFieldContainerData = null, + ): SharpFormEditorEmbed { + $requestFieldContainerData ??= RequestFieldContainerData::from(request()->query()); + $requestFieldContainerData->embed_key = null; // remove embed key to prevent infinite loop + $container = $this->getFieldContainer(new EntityKey($entityKey), $requestFieldContainerData); + /** @var SharpFormEditorField $editorField */ + $editorField = $container->findFieldByKey($requestFieldContainerData->embed_editor_key); + $embed = $editorField->embeds()->first(fn (SharpFormEditorEmbed $embed) => $embed->key() === $embedKey); + + if (! $embed) { + throw new SharpException('Embed not found'); + } return $embed; } diff --git a/src/Http/Controllers/Api/HandlesFieldContainer.php b/src/Http/Controllers/Api/HandlesFieldContainer.php index 65ef1e8d5..ad1c70445 100644 --- a/src/Http/Controllers/Api/HandlesFieldContainer.php +++ b/src/Http/Controllers/Api/HandlesFieldContainer.php @@ -19,12 +19,15 @@ trait HandlesFieldContainer use HandlesEntityCommand; use HandlesInstanceCommand; - private function getFieldContainer(EntityKey $entityKey): SharpFormEditorEmbed|Command|SharpForm + private function getFieldContainer(EntityKey $entityKey, ?RequestFieldContainerData $requestFieldContainerData = null): SharpFormEditorEmbed|Command|SharpForm { - $requestFieldContainerData = RequestFieldContainerData::from(request()->query()); + $requestFieldContainerData ??= RequestFieldContainerData::from(request()->query()); if ($requestFieldContainerData->embed_key) { - return $this->getEmbedFromKey($requestFieldContainerData->embed_key); + return $this->getEmbedFromKey( + $entityKey, + $requestFieldContainerData->embed_key, + ); } $entity = $this->entityManager->entityFor($entityKey);