Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion resources/js/common/slideouts/useElementEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ export function useElementEditor(
panel.nestedOwnerId = await panel.prepareNestedOwner();
}

if (panel?.nestedOwnerId) {
// Element types without drafts (e.g. variants) save in place.
if (panel?.nestedOwnerId && instance.settings.canCreateDrafts) {
if (!instance.settings.draftId) {
await instance.saveDraft();
}
Expand Down
26 changes: 26 additions & 0 deletions resources/js/modules/elements/composables/useElementEditor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1937,6 +1937,32 @@ describe('useElementEditor', () => {
});
});

it('saves draft-less elements in place when the opener prepares an owner draft', async () => {
const slideout = handledSlideout();
const prepareNestedOwner = vi.fn().mockResolvedValue(73);
Object.assign(slideout.instance, {prepareNestedOwner});
const request = stubSaveRequest(() => Promise.resolve({data: {}}));
const {editor} = mount(
payload({
canAutosave: false,
nestedContext,
saveForDerivativeUrl:
'/actions/elements/save-nested-element-for-derivative',
}),
slideout
);

editor.save();

await vi.waitFor(() => expect(request).toHaveBeenCalledOnce());
expect(prepareNestedOwner).toHaveBeenCalledOnce();
expect(postSpy).not.toHaveBeenCalled();
expect(request.mock.calls[0]![0]).toMatchObject({
url: '/actions/entries/save-entry',
data: expect.not.objectContaining({newOwnerId: expect.anything()}),
});
});

it('announces invalid nested elements when a save fails', async () => {
const displayError = vi.fn();
vi.stubGlobal('Craft', {cp: {displayError}});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,8 @@ export function useElementEditor({saveData, root, transform}: Options = {}) {
try {
const ownerId = await slideout!.instance.prepareNestedOwner!();

if (!ownerId) {
// Element types without drafts (e.g. variants) save in place.
if (!ownerId || !props.canAutosave) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ describe('NestedElementsControl', () => {
) {
const legacyElementEditor = {
settings: {
canCreateDrafts: true,
draftId: 6,
saveParams: null as Record<string, unknown> | null,
},
Expand Down Expand Up @@ -590,6 +591,33 @@ describe('NestedElementsControl', () => {
});
});

it('saves draft-less elements in place in the legacy editor', async () => {
const {createElementEditor, legacyElementEditor} = mount({
vueSlideout: false,
cards: [
nestedElement({
id: 18,
siteId: 1,
ownerId: 31,
editUrl:
'/admin/actions/elements/edit?elementId=18&siteId=1&fieldId=7&ownerId=31',
cardAttributes: {data: {editable: true}},
}),
],
});
legacyElementEditor.settings.canCreateDrafts = false;
legacyElementEditor.settings.draftId = null as unknown as number;
await nextTick();

root.querySelector<HTMLAnchorElement>('a[href]')!.click();
await vi.waitFor(() => expect(createElementEditor).toHaveBeenCalledOnce());

const settings = createElementEditor.mock.lastCall![1];
await expect(settings.onBeforeSubmit()).resolves.toBeUndefined();
expect(legacyElementEditor.saveDraft).not.toHaveBeenCalled();
expect(legacyElementEditor.settings.saveParams).toBeNull();
});

it('opens the entry’s own edit page in a new tab on a modified click', async () => {
const open = vi.spyOn(window, 'open').mockReturnValue(null);
mount({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface LegacyElementEditorSlideout {
): void;
elementEditor: {
settings: {
canCreateDrafts?: boolean;
draftId?: number | null;
saveParams?: Record<string, unknown> | null;
};
Expand Down Expand Up @@ -335,7 +336,10 @@ export function useNestedElementOperations(
prepareNestedOwner
? async (slideout) => {
const preparedOwnerId = await prepareNestedOwner();
if (!preparedOwnerId) {
if (
!preparedOwnerId ||
!slideout.elementEditor.settings.canCreateDrafts
) {
return;
}

Expand Down
Loading