feat(core): add journal search results to bs doc search (#9052)
fix AF-1842
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
|||||||
RecentDocsQuickSearchSession,
|
RecentDocsQuickSearchSession,
|
||||||
} from '@affine/core/modules/quicksearch';
|
} from '@affine/core/modules/quicksearch';
|
||||||
import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links';
|
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 { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { isNewTabTrigger } from '@affine/core/utils';
|
import { isNewTabTrigger } from '@affine/core/utils';
|
||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
@@ -331,7 +332,7 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
const QuickSearch = QuickSearchExtension({
|
const QuickSearch = QuickSearchExtension({
|
||||||
async openQuickSearch() {
|
async openQuickSearch() {
|
||||||
let searchResult: QuickSearchResult = null;
|
let searchResult: QuickSearchResult = null;
|
||||||
searchResult = await new Promise(resolve =>
|
searchResult = await new Promise((resolve, reject) =>
|
||||||
framework.get(QuickSearchService).quickSearch.show(
|
framework.get(QuickSearchService).quickSearch.show(
|
||||||
[
|
[
|
||||||
framework.get(RecentDocsQuickSearchSession),
|
framework.get(RecentDocsQuickSearchSession),
|
||||||
@@ -339,6 +340,7 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
framework.get(DocsQuickSearchSession),
|
framework.get(DocsQuickSearchSession),
|
||||||
framework.get(LinksQuickSearchSession),
|
framework.get(LinksQuickSearchSession),
|
||||||
framework.get(ExternalLinksQuickSearchSession),
|
framework.get(ExternalLinksQuickSearchSession),
|
||||||
|
framework.get(JournalsQuickSearchSession),
|
||||||
],
|
],
|
||||||
result => {
|
result => {
|
||||||
if (result === null) {
|
if (result === null) {
|
||||||
@@ -372,6 +374,18 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.source === 'date-picker') {
|
||||||
|
result.payload
|
||||||
|
.getDocId()
|
||||||
|
.then(docId => {
|
||||||
|
if (docId) {
|
||||||
|
resolve({ docId });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (result.source === 'external-link') {
|
if (result.source === 'external-link') {
|
||||||
const externalUrl = result.payload.url;
|
const externalUrl = result.payload.url;
|
||||||
resolve({ externalUrl });
|
resolve({ externalUrl });
|
||||||
|
|||||||
@@ -63,13 +63,23 @@ export const DateSelectorDialog = ({
|
|||||||
>
|
>
|
||||||
{/* hack the menu positioning using the following fixed anchor */}
|
{/* hack the menu positioning using the following fixed anchor */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={
|
||||||
position: 'fixed',
|
position
|
||||||
left: position[0],
|
? {
|
||||||
top: position[1],
|
position: 'fixed',
|
||||||
width: position[2],
|
left: position[0],
|
||||||
height: position[3],
|
top: position[1],
|
||||||
}}
|
width: position[2],
|
||||||
|
height: position[3],
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
position: 'fixed',
|
||||||
|
left: '50%',
|
||||||
|
top: '50%',
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export type WORKSPACE_DIALOG_SCHEMA = {
|
|||||||
onBeforeConfirm?: (ids: string[], cb: () => void) => void;
|
onBeforeConfirm?: (ids: string[], cb: () => void) => void;
|
||||||
}) => string[];
|
}) => string[];
|
||||||
'date-selector': (props: {
|
'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;
|
onSelect?: (date?: string) => void;
|
||||||
}) => string;
|
}) => string;
|
||||||
import: () => {
|
import: () => {
|
||||||
|
|||||||
110
packages/frontend/core/src/modules/quicksearch/impls/journals.ts
Normal file
110
packages/frontend/core/src/modules/quicksearch/impls/journals.ts
Normal file
@@ -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<string | undefined> }
|
||||||
|
>;
|
||||||
|
|
||||||
|
export class JournalsQuickSearchSession
|
||||||
|
extends Entity
|
||||||
|
implements
|
||||||
|
QuickSearchSession<
|
||||||
|
'date-picker',
|
||||||
|
{ getDocId: () => Promise<string | undefined> }
|
||||||
|
>
|
||||||
|
{
|
||||||
|
constructor(
|
||||||
|
private readonly journalService: JournalService,
|
||||||
|
private readonly dialogService: WorkspaceDialogService,
|
||||||
|
private readonly docDisplayMetaService: DocDisplayMetaService
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
query$ = new LiveData('');
|
||||||
|
|
||||||
|
items$: LiveData<JournalQuickSearchItem[]> = 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,10 @@ import {
|
|||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
|
|
||||||
import { CollectionService } from '../collection';
|
import { CollectionService } from '../collection';
|
||||||
|
import { WorkspaceDialogService } from '../dialogs';
|
||||||
import { DocDisplayMetaService } from '../doc-display-meta/services/doc-display-meta';
|
import { DocDisplayMetaService } from '../doc-display-meta/services/doc-display-meta';
|
||||||
import { DocsSearchService } from '../docs-search';
|
import { DocsSearchService } from '../docs-search';
|
||||||
|
import { JournalService } from '../journal';
|
||||||
import { TagService } from '../tag';
|
import { TagService } from '../tag';
|
||||||
import { WorkbenchService } from '../workbench';
|
import { WorkbenchService } from '../workbench';
|
||||||
import { QuickSearch } from './entities/quick-search';
|
import { QuickSearch } from './entities/quick-search';
|
||||||
@@ -18,6 +20,7 @@ import { CommandsQuickSearchSession } from './impls/commands';
|
|||||||
import { CreationQuickSearchSession } from './impls/creation';
|
import { CreationQuickSearchSession } from './impls/creation';
|
||||||
import { DocsQuickSearchSession } from './impls/docs';
|
import { DocsQuickSearchSession } from './impls/docs';
|
||||||
import { ExternalLinksQuickSearchSession } from './impls/external-links';
|
import { ExternalLinksQuickSearchSession } from './impls/external-links';
|
||||||
|
import { JournalsQuickSearchSession } from './impls/journals';
|
||||||
import { LinksQuickSearchSession } from './impls/links';
|
import { LinksQuickSearchSession } from './impls/links';
|
||||||
import { RecentDocsQuickSearchSession } from './impls/recent-docs';
|
import { RecentDocsQuickSearchSession } from './impls/recent-docs';
|
||||||
import { TagsQuickSearchSession } from './impls/tags';
|
import { TagsQuickSearchSession } from './impls/tags';
|
||||||
@@ -68,5 +71,10 @@ export function configureQuickSearchModule(framework: Framework) {
|
|||||||
.entity(RecentDocsQuickSearchSession, [
|
.entity(RecentDocsQuickSearchSession, [
|
||||||
RecentDocsService,
|
RecentDocsService,
|
||||||
DocDisplayMetaService,
|
DocDisplayMetaService,
|
||||||
|
])
|
||||||
|
.entity(JournalsQuickSearchSession, [
|
||||||
|
JournalService,
|
||||||
|
WorkspaceDialogService,
|
||||||
|
DocDisplayMetaService,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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.placeholder": "Set a workspace name",
|
||||||
"com.affine.upgrade-to-team-page.create-and-upgrade-confirm.confirm": "Continue to Pricing",
|
"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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ test('can use @ to open quick search to search for doc and insert into canvas',
|
|||||||
await insertInputText(page, url);
|
await insertInputText(page, url);
|
||||||
|
|
||||||
// expect the default page to be selected
|
// 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
|
// press enter to insert the page to canvas
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
|
|||||||
Reference in New Issue
Block a user