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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to

### Changed

- ♻️(frontend) search on all docs if no children #1184
- ♻️(frontend) redirect to doc after duplicate #1175
- 🔧(project) change env.d system by using local files #1200
- ⚡️(frontend) improve tree stability #1207
Expand Down
105 changes: 70 additions & 35 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-search.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect, test } from '@playwright/test';

import { createDoc, randomName, verifyDocName } from './utils-common';
import { createRootSubPage } from './utils-sub-pages';

test.beforeEach(async ({ page }) => {
await page.goto('/');
Expand Down Expand Up @@ -98,39 +99,46 @@ test.describe('Document search', () => {
).toBeHidden();
});

test("it checks we don't see filters in search modal", async ({ page }) => {
test('it check the presence of filters in search modal', async ({
page,
browserName,
}) => {
// Doc grid filters are not visible
const searchButton = page
.getByTestId('left-panel-desktop')
.getByRole('button', { name: 'search' });
.getByRole('button', { name: 'search', exact: true });

const filters = page.getByTestId('doc-search-filters');

await expect(searchButton).toBeVisible();
await page.getByRole('button', { name: 'search', exact: true }).click();
await searchButton.click();
await expect(
page.getByRole('combobox', { name: 'Quick search input' }),
).toBeVisible();
await expect(page.getByTestId('doc-search-filters')).toBeHidden();
});
});
await expect(filters).toBeHidden();

test.describe('Sub page search', () => {
test('it check the presence of filters in search modal', async ({
page,
browserName,
}) => {
await page.goto('/');
const [doc1Title] = await createDoc(
page,
'My sub page search',
browserName,
1,
);
await page.getByRole('button', { name: 'close' }).click();

// Create a doc without children for the moment
// and check that filters are not visible
const [doc1Title] = await createDoc(page, 'My page search', browserName, 1);
await verifyDocName(page, doc1Title);
const searchButton = page
.getByTestId('left-panel-desktop')
.getByRole('button', { name: 'search' });

await searchButton.click();
const filters = page.getByTestId('doc-search-filters');
await expect(
page.getByRole('combobox', { name: 'Quick search input' }),
).toBeVisible();
await expect(filters).toBeHidden();

await page.getByRole('button', { name: 'close' }).click();

// Create a sub page
// and check that filters are visible
await createRootSubPage(page, browserName, 'My sub page search');

await searchButton.click();

await expect(filters).toBeVisible();

await filters.click();
await filters.getByRole('button', { name: 'Current doc' }).click();
await expect(
Expand All @@ -139,43 +147,70 @@ test.describe('Sub page search', () => {
await expect(
page.getByRole('menuitem', { name: 'Current doc' }),
).toBeVisible();
await page.getByRole('menuitem', { name: 'Current doc' }).click();
await page.getByRole('menuitem', { name: 'All docs' }).click();

await expect(page.getByRole('button', { name: 'Reset' })).toBeVisible();
});

test('it searches sub pages', async ({ page, browserName }) => {
await page.goto('/');

const [doc1Title] = await createDoc(
// First doc
const [firstDocTitle] = await createDoc(
page,
'My sub page search',
'My first sub page search',
browserName,
1,
);
await verifyDocName(page, doc1Title);
await verifyDocName(page, firstDocTitle);

// Create a new doc - for the moment without children
await page.getByRole('button', { name: 'New doc' }).click();
await verifyDocName(page, '');
await page.getByRole('textbox', { name: 'doc title input' }).click();
await page
.getByRole('textbox', { name: 'doc title input' })
.press('ControlOrMeta+a');
const [randomDocName] = randomName('doc-sub-page', browserName, 1);
const [secondDocTitle] = randomName(
'My second sub page search',
browserName,
1,
);
await page
.getByRole('textbox', { name: 'doc title input' })
.fill(randomDocName);
.fill(secondDocTitle);

const searchButton = page
.getByTestId('left-panel-desktop')
.getByRole('button', { name: 'search' });

await searchButton.click();
await page.getByRole('combobox', { name: 'Quick search input' }).click();
await page
.getByRole('combobox', { name: 'Quick search input' })
.fill('sub page search');

// Expect to find the first doc
await expect(
page.getByRole('button', { name: 'Current doc' }),
page.getByRole('presentation').getByLabel(firstDocTitle),
).toBeVisible();
await page.getByRole('combobox', { name: 'Quick search input' }).click();
await expect(
page.getByRole('presentation').getByLabel(secondDocTitle),
).toBeVisible();

await page.getByRole('button', { name: 'close' }).click();

// Create a sub page
await createRootSubPage(page, browserName, secondDocTitle);
await searchButton.click();
await page
.getByRole('combobox', { name: 'Quick search input' })
.fill('sub');
await expect(page.getByLabel(randomDocName)).toBeVisible();
.fill('sub page search');

// Now there is a sub page - expect to have the focus on the current doc
await expect(
page.getByRole('presentation').getByLabel(secondDocTitle),
).toBeVisible();
await expect(
page.getByRole('presentation').getByLabel(firstDocTitle),
).toBeHidden();
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './useCollaboration';
export * from './useCopyDocLink';
export * from './useDocUtils';
export * from './useIsCollaborativeEditable';
export * from './useTrans';
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Doc } from '@/docs/doc-management';

export const useTreeUtils = (doc: Doc) => {
export const useDocUtils = (doc: Doc) => {
return {
isTopRoot: doc.depth === 1,
isChild: doc.depth > 1,
hasChildren: doc.numchild > 0,
isDesynchronized: !!(
doc.ancestors_link_reach &&
(doc.computed_link_reach !== doc.ancestors_link_reach ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { useDebouncedCallback } from 'use-debounce';

import { Box } from '@/components';
import { QuickSearch } from '@/components/quick-search';
import { Doc, useDocUtils } from '@/docs/doc-management';
import { useResponsiveStore } from '@/stores';

import { Doc } from '../../doc-management';
import EmptySearchIcon from '../assets/illustration-docs-empty.png';

import { DocSearchContent } from './DocSearchContent';
Expand All @@ -20,18 +20,18 @@ import {
} from './DocSearchFilters';
import { DocSearchSubPageContent } from './DocSearchSubPageContent';

type DocSearchModalProps = {
type DocSearchModalGlobalProps = {
onClose: () => void;
isOpen: boolean;
showFilters?: boolean;
defaultFilters?: DocSearchFiltersValues;
};

export const DocSearchModal = ({
const DocSearchModalGlobal = ({
showFilters = false,
defaultFilters,
...modalProps
}: DocSearchModalProps) => {
}: DocSearchModalGlobalProps) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);

Expand Down Expand Up @@ -126,3 +126,42 @@ export const DocSearchModal = ({
</Modal>
);
};

type DocSearchModalDetailProps = DocSearchModalGlobalProps & {
doc: Doc;
};

const DocSearchModalDetail = ({
doc,
...modalProps
}: DocSearchModalDetailProps) => {
const { hasChildren, isChild } = useDocUtils(doc);
const isWithChildren = isChild || hasChildren;

let defaultFilters = DocSearchTarget.ALL;
let showFilters = false;
if (isWithChildren) {
defaultFilters = DocSearchTarget.CURRENT;
showFilters = true;
}

return (
<DocSearchModalGlobal
{...modalProps}
showFilters={showFilters}
defaultFilters={{ target: defaultFilters }}
/>
);
};

type DocSearchModalProps = DocSearchModalGlobalProps & {
doc?: Doc;
};

export const DocSearchModal = ({ doc, ...modalProps }: DocSearchModalProps) => {
if (doc) {
return <DocSearchModalDetail doc={doc} {...modalProps} />;
}

return <DocSearchModalGlobal {...modalProps} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
LinkReach,
LinkRole,
getDocLinkReach,
useDocUtils,
useUpdateDocLink,
} from '@/docs/doc-management';
import { useTreeUtils } from '@/docs/doc-tree';
import { useResponsiveStore } from '@/stores';

import { useTranslatedShareSettings } from '../hooks/';
Expand All @@ -37,7 +37,7 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
const canManage = doc.abilities.accesses_manage;
const docLinkReach = getDocLinkReach(doc);
const docLinkRole = doc.computed_link_role ?? LinkRole.READER;
const { isDesynchronized } = useTreeUtils(doc);
const { isDesynchronized } = useDocUtils(doc);
const { linkModeTranslations, linkReachChoices, linkReachTranslations } =
useTranslatedShareSettings();

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './api';
export * from './components';
export * from './hooks';
export * from './utils';
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { useRouter } from 'next/router';
import { PropsWithChildren, useCallback, useState } from 'react';

import { Box, Icon, SeparatedSection } from '@/components';
import { DocSearchModal, DocSearchTarget } from '@/docs/doc-search/';
import { useDocStore } from '@/docs/doc-management';
import { DocSearchModal } from '@/docs/doc-search/';
import { useAuth } from '@/features/auth';
import { useCmdK } from '@/hook/useCmdK';

Expand All @@ -12,10 +13,9 @@ import { useLeftPanelStore } from '../stores';
import { LeftPanelHeaderButton } from './LeftPanelHeaderButton';

export const LeftPanelHeader = ({ children }: PropsWithChildren) => {
const { currentDoc } = useDocStore();
const router = useRouter();
const { authenticated } = useAuth();
const isDoc = router.pathname === '/docs/[id]';

const [isSearchModalOpen, setIsSearchModalOpen] = useState(false);

const openSearchModal = useCallback(() => {
Expand Down Expand Up @@ -81,10 +81,7 @@ export const LeftPanelHeader = ({ children }: PropsWithChildren) => {
<DocSearchModal
onClose={closeSearchModal}
isOpen={isSearchModalOpen}
showFilters={isDoc}
defaultFilters={{
target: isDoc ? DocSearchTarget.CURRENT : undefined,
}}
doc={currentDoc}
/>
)}
</>
Expand Down
Loading