diff --git a/apps/web-antdv-next/src/views/blog/article/list.spec.ts b/apps/web-antdv-next/src/views/blog/article/list.spec.ts index e605080..63b07ff 100644 --- a/apps/web-antdv-next/src/views/blog/article/list.spec.ts +++ b/apps/web-antdv-next/src/views/blog/article/list.spec.ts @@ -7,6 +7,22 @@ import { describe, expect, it } from 'vitest'; const source = readFileSync(new URL('list.tsx', import.meta.url), 'utf8'); describe('blog article list preview entry', () => { + /** + * Reads a source slice between two stable markers for modal ordering guards. + * @param start Marker before the function body under assertion. + * @param end Marker after the function body under assertion. + * @returns Source slice used by regression assertions. + */ + function getSourceSlice(start: string, end: string) { + const startIndex = source.indexOf(start); + const endIndex = source.indexOf(end, startIndex + start.length); + + expect(startIndex).toBeGreaterThanOrEqual(0); + expect(endIndex).toBeGreaterThan(startIndex); + + return source.slice(startIndex, endIndex); + } + it('keeps the preview row action wired to the hidden iframe route', () => { expect(source).toContain("key: 'preview'"); expect(source).toContain("permissionCodes: ['Blog:Article:Preview']"); @@ -14,6 +30,31 @@ describe('blog article list preview entry', () => { expect(source).toContain('articleId: row.id'); }); + it('opens the article modal before waiting for modal-contained form schema updates', () => { + const openCreateBody = getSourceSlice( + 'async function openCreate', + 'function openEdit', + ); + const openEditBody = getSourceSlice( + 'function openEdit', + 'function openPreview', + ); + + expect(source).toContain('void resetArticleModalForm('); + expect(openCreateBody).toContain( + 'articleModalApi.setData({ values }).open();', + ); + expect(openEditBody).toContain( + 'articleModalApi.setData({ values }).open();', + ); + expect(openCreateBody).not.toMatch( + /await setArticleEditorMode[\s\S]*articleModalApi\.setData\(\{ values \}\)\.open\(\)/, + ); + expect(openEditBody).not.toMatch( + /await setArticleEditorMode[\s\S]*articleModalApi\.setData\(\{ values \}\)\.open\(\)/, + ); + }); + it('wires Tiptap editor mode switching without dropping current content', () => { expect(source).toContain( "import { KtTiptapHtmlEditor } from '#/components/richText';", diff --git a/apps/web-antdv-next/src/views/blog/article/list.tsx b/apps/web-antdv-next/src/views/blog/article/list.tsx index 878e0cb..398521b 100644 --- a/apps/web-antdv-next/src/views/blog/article/list.tsx +++ b/apps/web-antdv-next/src/views/blog/article/list.tsx @@ -174,7 +174,9 @@ export default defineComponent({ const { values } = articleModalApi.getData<{ values?: BlogArticleFormValues; }>(); - void resetArticleForm(values || getBlogArticleCreateFormDefaults()); + void resetArticleModalForm( + values || getBlogArticleCreateFormDefaults(), + ); }, }); const columns: Array> = [ @@ -391,6 +393,15 @@ export default defineComponent({ }); } + /** + * Applies editor schema and form values after the modal has opened so the modal-contained form can mount first. + * @param values Article values selected for the current modal session. + */ + async function resetArticleModalForm(values: BlogArticleFormValues) { + await setArticleEditorMode(values.editorMode || 'markdown'); + await resetArticleForm(values); + } + /** * Resets modal form state before applying create or edit values. * @param values Article values selected for the current modal session. @@ -460,7 +471,6 @@ export default defineComponent({ editingId.value = undefined; const values = getBlogArticleCreateFormDefaults(searchValues); - await setArticleEditorMode(values.editorMode || 'markdown'); articleModalApi.setData({ values }).open(); } @@ -468,10 +478,9 @@ export default defineComponent({ * Opens the article modal using raw HTML mode for imported WordPress/Argon content. * @param row Article row selected from the table. */ - async function openEdit(row: WordpressBlogApi.Article) { + function openEdit(row: WordpressBlogApi.Article) { editingId.value = `${row.id}`; const values = getBlogArticleEditFormValues(row); - await setArticleEditorMode(values.editorMode || 'markdown'); articleModalApi.setData({ values }).open(); }