From 30d679397805258b78ede5e8cdd0045415e257d5 Mon Sep 17 00:00:00 2001 From: pengx17 Date: Thu, 12 Dec 2024 02:25:00 +0000 Subject: [PATCH] feat(core): add journal search results to bs doc search (#9052) fix AF-1842 --- .../specs/custom/spec-patchers.tsx | 16 ++- .../src/desktop/dialogs/selectors/date.tsx | 24 ++-- .../core/src/modules/dialogs/constant.ts | 2 +- .../src/modules/quicksearch/impls/journals.ts | 110 ++++++++++++++++++ .../core/src/modules/quicksearch/index.ts | 8 ++ packages/frontend/i18n/src/resources/en.json | 4 +- tests/affine-local/e2e/quick-search.spec.ts | 2 +- 7 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 packages/frontend/core/src/modules/quicksearch/impls/journals.ts diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx index 489d4fd0e..97464e369 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx @@ -20,6 +20,7 @@ import { RecentDocsQuickSearchSession, } from '@affine/core/modules/quicksearch'; import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links'; +import { JournalsQuickSearchSession } from '@affine/core/modules/quicksearch/impls/journals'; import { WorkbenchService } from '@affine/core/modules/workbench'; import { isNewTabTrigger } from '@affine/core/utils'; import { DebugLogger } from '@affine/debug'; @@ -331,7 +332,7 @@ export function patchQuickSearchService(framework: FrameworkProvider) { const QuickSearch = QuickSearchExtension({ async openQuickSearch() { let searchResult: QuickSearchResult = null; - searchResult = await new Promise(resolve => + searchResult = await new Promise((resolve, reject) => framework.get(QuickSearchService).quickSearch.show( [ framework.get(RecentDocsQuickSearchSession), @@ -339,6 +340,7 @@ export function patchQuickSearchService(framework: FrameworkProvider) { framework.get(DocsQuickSearchSession), framework.get(LinksQuickSearchSession), framework.get(ExternalLinksQuickSearchSession), + framework.get(JournalsQuickSearchSession), ], result => { if (result === null) { @@ -372,6 +374,18 @@ export function patchQuickSearchService(framework: FrameworkProvider) { return; } + if (result.source === 'date-picker') { + result.payload + .getDocId() + .then(docId => { + if (docId) { + resolve({ docId }); + } + }) + .catch(reject); + return; + } + if (result.source === 'external-link') { const externalUrl = result.payload.url; resolve({ externalUrl }); diff --git a/packages/frontend/core/src/desktop/dialogs/selectors/date.tsx b/packages/frontend/core/src/desktop/dialogs/selectors/date.tsx index 0761bf7e0..c690f2154 100644 --- a/packages/frontend/core/src/desktop/dialogs/selectors/date.tsx +++ b/packages/frontend/core/src/desktop/dialogs/selectors/date.tsx @@ -63,13 +63,23 @@ export const DateSelectorDialog = ({ > {/* hack the menu positioning using the following fixed anchor */}
); diff --git a/packages/frontend/core/src/modules/dialogs/constant.ts b/packages/frontend/core/src/modules/dialogs/constant.ts index 9eaa9855a..1537e3991 100644 --- a/packages/frontend/core/src/modules/dialogs/constant.ts +++ b/packages/frontend/core/src/modules/dialogs/constant.ts @@ -60,7 +60,7 @@ export type WORKSPACE_DIALOG_SCHEMA = { onBeforeConfirm?: (ids: string[], cb: () => void) => void; }) => string[]; 'date-selector': (props: { - position: [number, number, number, number]; // [x, y, width, height] + position?: [number, number, number, number]; // [x, y, width, height] onSelect?: (date?: string) => void; }) => string; import: () => { diff --git a/packages/frontend/core/src/modules/quicksearch/impls/journals.ts b/packages/frontend/core/src/modules/quicksearch/impls/journals.ts new file mode 100644 index 000000000..8d21e5cb0 --- /dev/null +++ b/packages/frontend/core/src/modules/quicksearch/impls/journals.ts @@ -0,0 +1,110 @@ +import { I18n, i18nTime } from '@affine/i18n'; +import { DateTimeIcon } from '@blocksuite/icons/rc'; +import { Entity, LiveData } from '@toeverything/infra'; + +import type { WorkspaceDialogService } from '../../dialogs'; +import type { DocDisplayMetaService } from '../../doc-display-meta'; +import { type JournalService, suggestJournalDate } from '../../journal'; +import type { QuickSearchSession } from '../providers/quick-search-provider'; +import type { QuickSearchGroup } from '../types/group'; +import type { QuickSearchItem } from '../types/item'; + +const group: QuickSearchGroup = { + id: 'journals', + label: { + i18nKey: 'com.affine.cmdk.affine.category.affine.journal', + }, + score: 0, +}; + +type JournalQuickSearchItem = QuickSearchItem< + 'date-picker', + { getDocId: () => Promise } +>; + +export class JournalsQuickSearchSession + extends Entity + implements + QuickSearchSession< + 'date-picker', + { getDocId: () => Promise } + > +{ + constructor( + private readonly journalService: JournalService, + private readonly dialogService: WorkspaceDialogService, + private readonly docDisplayMetaService: DocDisplayMetaService + ) { + super(); + } + + query$ = new LiveData(''); + + items$: LiveData = LiveData.computed(get => { + const getDateDocId = (date?: string) => { + if (date) { + return this.journalService.ensureJournalByDate(date).id; + } + return undefined; + }; + + const items: JournalQuickSearchItem[] = [ + { + icon: DateTimeIcon, + id: 'journal:pick-a-date', + source: 'date-picker', + group: group, + label: { + title: I18n.t('com.affine.cmdk.affine.category.affine.date-picker'), + }, + score: 0, + payload: { + getDocId: () => { + return new Promise(resolve => { + const id = this.dialogService.open('date-selector', { + onSelect: date => { + resolve(getDateDocId(date)); + this.dialogService.close(id); + }, + }); + }); + }, + }, + }, + ]; + + const query = get(this.query$); + const suggestedDate = suggestJournalDate(query); + + if (suggestedDate) { + const { dateString, alias } = suggestedDate; + const dateDisplay = i18nTime(dateString, { + absolute: { accuracy: 'day' }, + }); + + const icon = this.docDisplayMetaService.getJournalIcon(dateString, { + type: 'rc', + }); + + items.unshift({ + icon, + id: 'journal:date-' + dateString, + source: 'date-picker', + group: group, + label: { + title: alias ? `${alias}, ${dateDisplay}` : dateDisplay, + }, + score: 0, + payload: { + getDocId: () => Promise.resolve(getDateDocId(dateString)), + }, + }); + } + + return items; + }); + + query(query: string) { + this.query$.next(query); + } +} diff --git a/packages/frontend/core/src/modules/quicksearch/index.ts b/packages/frontend/core/src/modules/quicksearch/index.ts index e0de6f7c7..85cd2445e 100644 --- a/packages/frontend/core/src/modules/quicksearch/index.ts +++ b/packages/frontend/core/src/modules/quicksearch/index.ts @@ -8,8 +8,10 @@ import { } from '@toeverything/infra'; import { CollectionService } from '../collection'; +import { WorkspaceDialogService } from '../dialogs'; import { DocDisplayMetaService } from '../doc-display-meta/services/doc-display-meta'; import { DocsSearchService } from '../docs-search'; +import { JournalService } from '../journal'; import { TagService } from '../tag'; import { WorkbenchService } from '../workbench'; import { QuickSearch } from './entities/quick-search'; @@ -18,6 +20,7 @@ import { CommandsQuickSearchSession } from './impls/commands'; import { CreationQuickSearchSession } from './impls/creation'; import { DocsQuickSearchSession } from './impls/docs'; import { ExternalLinksQuickSearchSession } from './impls/external-links'; +import { JournalsQuickSearchSession } from './impls/journals'; import { LinksQuickSearchSession } from './impls/links'; import { RecentDocsQuickSearchSession } from './impls/recent-docs'; import { TagsQuickSearchSession } from './impls/tags'; @@ -68,5 +71,10 @@ export function configureQuickSearchModule(framework: Framework) { .entity(RecentDocsQuickSearchSession, [ RecentDocsService, DocDisplayMetaService, + ]) + .entity(JournalsQuickSearchSession, [ + JournalService, + WorkspaceDialogService, + DocDisplayMetaService, ]); } diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index c35e36f9a..60709d924 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -1596,5 +1596,7 @@ "com.affine.upgrade-to-team-page.create-and-upgrade-confirm.description": "A workspace is your virtual space to capture, create and plan as just one person or together as a team.", "com.affine.upgrade-to-team-page.create-and-upgrade-confirm.placeholder": "Set a workspace name", "com.affine.upgrade-to-team-page.create-and-upgrade-confirm.confirm": "Continue to Pricing", - "com.affine.workspace.storage": "Workspace storage" + "com.affine.workspace.storage": "Workspace storage", + "com.affine.cmdk.affine.category.affine.journal": "Journal", + "com.affine.cmdk.affine.category.affine.date-picker": "Select a specific date" } diff --git a/tests/affine-local/e2e/quick-search.spec.ts b/tests/affine-local/e2e/quick-search.spec.ts index 44240a199..64023e4b5 100644 --- a/tests/affine-local/e2e/quick-search.spec.ts +++ b/tests/affine-local/e2e/quick-search.spec.ts @@ -479,7 +479,7 @@ test('can use @ to open quick search to search for doc and insert into canvas', await insertInputText(page, url); // expect the default page to be selected - await expect(page.locator('[cmdk-group-items] [cmdk-item]')).toHaveCount(3); + await expect(page.locator('[cmdk-group-items] [cmdk-item]')).toHaveCount(5); // press enter to insert the page to canvas await page.keyboard.press('Enter');