Skip to content

Commit 76b329a

Browse files
authored
Merge branch 'develop' into fix/table-row-deletion-480
2 parents ff897e2 + 0fce112 commit 76b329a

28 files changed

+1527
-874
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,18 @@ on:
66
branches:
77
- develop
88
- main
9-
- wiki-v3
9+
- version-3
10+
paths-ignore:
11+
- '**.js'
12+
- '**.vue'
13+
- '**.css'
14+
- '**.ts'
1015
pull_request:
16+
paths-ignore:
17+
- '**.js'
18+
- '**.vue'
19+
- '**.css'
20+
- '**.ts'
1121

1222
concurrency:
1323
group: develop-wiki-${{ github.event.number }}

e2e/tests/change-request-flow.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,4 +512,89 @@ test.describe('Change Request Flow', () => {
512512
changeCard.getByText('Reordered', { exact: true }),
513513
).toBeVisible();
514514
});
515+
516+
test('should navigate to published page after merging from space editor', async ({
517+
page,
518+
request,
519+
}) => {
520+
await page.goto('/wiki/spaces');
521+
await page.waitForLoadState('networkidle');
522+
523+
const timestamp = Date.now();
524+
const spaceName = `CR Merge Nav Space ${timestamp}`;
525+
const spaceRoute = `cr-merge-nav-${timestamp}`;
526+
const pageTitle = `merge-nav-page-${timestamp}`;
527+
const pageContent = `Merge nav content ${timestamp}`;
528+
529+
// Create a new space
530+
await page.getByRole('button', { name: 'New Space' }).click();
531+
await page.waitForSelector('[role="dialog"]', { state: 'visible' });
532+
await page.getByLabel('Space Name').fill(spaceName);
533+
await page.getByLabel('Route').fill(spaceRoute);
534+
await page
535+
.getByRole('dialog')
536+
.getByRole('button', { name: 'Create' })
537+
.click();
538+
await page.waitForLoadState('networkidle');
539+
await expect(page).toHaveURL(/\/wiki\/spaces\//);
540+
541+
// Create a new page draft
542+
const createFirstPage = page.getByRole('button', {
543+
name: 'Create First Page',
544+
});
545+
const newPageButton = page.getByRole('button', { name: 'New Page' });
546+
547+
if (await createFirstPage.isVisible({ timeout: 2000 }).catch(() => false)) {
548+
await createFirstPage.click();
549+
} else {
550+
await newPageButton.click();
551+
}
552+
553+
await page.getByLabel('Title').fill(pageTitle);
554+
await page
555+
.getByRole('dialog')
556+
.getByRole('button', { name: 'Save Draft' })
557+
.click();
558+
await page.waitForTimeout(500);
559+
560+
// Open the draft page from sidebar
561+
await page.locator('aside').getByText(pageTitle, { exact: true }).click();
562+
await page.waitForURL(/\/draft\/[^/?#]+/);
563+
564+
// Add content
565+
const editor = page
566+
.locator('.ProseMirror, [contenteditable="true"]')
567+
.first();
568+
await expect(editor).toBeVisible({ timeout: 10000 });
569+
await page.waitForFunction(() => window.wikiEditor !== undefined, {
570+
timeout: 10000,
571+
});
572+
await page.evaluate((content) => {
573+
window.wikiEditor.commands.setContent(content, {
574+
contentType: 'markdown',
575+
});
576+
}, pageContent);
577+
await editor.click();
578+
await page.getByRole('button', { name: 'Save Draft' }).click();
579+
await page.waitForTimeout(500);
580+
581+
// Merge directly from within the space editor (manager can merge Draft CRs)
582+
const mergeButton = page.getByRole('button', { name: 'Merge' });
583+
await expect(mergeButton).toBeVisible({ timeout: 10000 });
584+
await mergeButton.click();
585+
await expect(
586+
page.locator('text=Change request merged').first(),
587+
).toBeVisible({ timeout: 15000 });
588+
589+
// The fix: after merge, URL should navigate to the published page route
590+
// and NOT remain on the /draft/ route
591+
await page.waitForURL(/\/page\//, { timeout: 10000 });
592+
expect(page.url()).toMatch(/\/spaces\/[^/]+\/page\//);
593+
expect(page.url()).not.toMatch(/\/draft\//);
594+
595+
// The published page content should be visible without needing a hard refresh
596+
await expect(page.getByText(pageContent)).toBeVisible({
597+
timeout: 10000,
598+
});
599+
});
515600
});

e2e/tests/wiki.spec.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,17 @@ test.describe('Wiki Editor', () => {
113113
// Should have sidebar with space management buttons
114114
await expect(page.locator('aside')).toBeVisible();
115115

116+
// Wait for the tree to load (CR mode requires async init)
116117
// Should have either "Create First Page" (empty space) or icon buttons for New Group/Page
117-
// The "New Page" button has title="New Page" and icon="file-plus"
118118
const createFirstPage = page.locator(
119119
'button:has-text("Create First Page")',
120120
);
121121
const newPageButton = page.locator('button[title="New Page"]');
122122

123-
const hasCreateFirst = await createFirstPage
124-
.isVisible({ timeout: 2000 })
125-
.catch(() => false);
126-
const hasNewPage = await newPageButton
127-
.isVisible({ timeout: 2000 })
128-
.catch(() => false);
129-
130-
expect(hasCreateFirst || hasNewPage).toBe(true);
123+
// Use a combined locator with sufficient timeout for CR tree loading
124+
await expect(createFirstPage.or(newPageButton)).toBeVisible({
125+
timeout: 10000,
126+
});
131127
});
132128

133129
test('should open wiki editor when clicking page in sidebar', async ({

frontend/src/components/SpaceList.vue

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,48 @@
1010
</Button>
1111
</div>
1212

13-
<ListView
14-
class="h-full"
15-
:columns="columns"
16-
:rows="spaces.data || []"
17-
:options="{
18-
selectable: false,
19-
showTooltip: true,
20-
resizeColumn: false,
21-
getRowRoute: (row) => ({ name: 'SpaceDetails', params: { spaceId: row.name } }),
22-
emptyState: {
23-
title: __('No Wiki Spaces'),
24-
description: isManager ? __('Create your first wiki space to get started') : __('No wiki spaces available'),
25-
button: isManager ? {
26-
label: __('New Space'),
27-
variant: 'solid',
28-
onClick: () => (showCreateDialog = true),
29-
} : undefined,
30-
},
31-
}"
32-
row-key="name"
33-
>
34-
<template #cell="{ item, column }">
35-
<Badge
36-
v-if="column.key === 'is_published'"
37-
variant="subtle"
38-
:theme="item ? 'green' : 'orange'"
39-
size="sm"
40-
:label="item ? __('Published') : __('Unpublished')"
13+
<div class="flex-1 overflow-auto">
14+
<ListView
15+
:columns="columns"
16+
:rows="spaces.data || []"
17+
:options="{
18+
selectable: false,
19+
showTooltip: true,
20+
resizeColumn: false,
21+
getRowRoute: (row) => ({ name: 'SpaceDetails', params: { spaceId: row.name } }),
22+
emptyState: {
23+
title: __('No Wiki Spaces'),
24+
description: isManager ? __('Create your first wiki space to get started') : __('No wiki spaces available'),
25+
button: isManager ? {
26+
label: __('New Space'),
27+
variant: 'solid',
28+
onClick: () => (showCreateDialog = true),
29+
} : undefined,
30+
},
31+
}"
32+
row-key="name"
33+
>
34+
<template #cell="{ item, column }">
35+
<Badge
36+
v-if="column.key === 'is_published'"
37+
variant="subtle"
38+
:theme="item ? 'green' : 'orange'"
39+
size="sm"
40+
:label="item ? __('Published') : __('Unpublished')"
41+
/>
42+
<span v-else>{{ item }}</span>
43+
</template>
44+
</ListView>
45+
46+
<div v-if="spaces.hasNextPage" class="flex px-2 py-2">
47+
<Button
48+
@click="() => spaces.next()"
49+
:loading="spaces.list.loading"
50+
:label="__('Load more')"
51+
icon-left="refresh-cw"
4152
/>
42-
<span v-else>{{ item }}</span>
43-
</template>
44-
</ListView>
53+
</div>
54+
</div>
4555

4656
<Dialog
4757
v-model="showCreateDialog"
@@ -156,7 +166,7 @@ const spaces = createListResource({
156166
doctype: "Wiki Space",
157167
fields: ["name", "space_name", "route", "root_group", "is_published"],
158168
orderBy: "creation desc",
159-
limit: 100,
169+
pageLength: 25,
160170
auto: true,
161171
insert: {
162172
onSuccess: (doc) => {

frontend/src/components/WikiDocumentPanel.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ const isSaving = computed(() => {
177177
});
178178
179179
const editorKey = computed(() => {
180-
if (wikiDoc.doc?.name === props.pageId) {
180+
if (wikiDoc.doc?.name === props.pageId && !crPageResource.loading) {
181181
return props.pageId;
182182
}
183183
return null;

0 commit comments

Comments
 (0)