fix(core): open template doc on sidebar template entrance (#9766)

close AF-2135, AF-2136, AF-2138, AF-2133
This commit is contained in:
CatsJuice
2025-01-18 16:44:05 +00:00
parent 9c3365aaca
commit f8abe997f5
4 changed files with 15 additions and 23 deletions

View File

@@ -26,7 +26,6 @@ import { track } from '@affine/track';
import type { Store } from '@blocksuite/affine/store'; import type { Store } from '@blocksuite/affine/store';
import { import {
AllDocsIcon, AllDocsIcon,
GithubIcon,
ImportIcon, ImportIcon,
JournalIcon, JournalIcon,
SettingsIcon, SettingsIcon,
@@ -192,11 +191,6 @@ export const RootAppSidebar = memo((): ReactElement => {
icon={<JournalIcon />} icon={<JournalIcon />}
label={t['com.affine.app-sidebar.learn-more']()} label={t['com.affine.app-sidebar.learn-more']()}
/> />
<ExternalMenuLinkItem
href="https://github.com/toeverything/affine"
icon={<GithubIcon />}
label={t['com.affine.app-sidebar.star-us']()}
/>
</div> </div>
</SidebarScrollableContainer> </SidebarScrollableContainer>
<SidebarContainer> <SidebarContainer>

View File

@@ -10,28 +10,16 @@ import { TemplateIcon, TemplateOutlineIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useService } from '@toeverything/infra';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { useAsyncCallback } from '../hooks/affine-async-hooks';
export const TemplateDocEntrance = () => { export const TemplateDocEntrance = () => {
const t = useI18n(); const t = useI18n();
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const docsService = useService(DocsService);
const featureFlagService = useService(FeatureFlagService); const featureFlagService = useService(FeatureFlagService);
const workbench = useService(WorkbenchService).workbench;
const enabled = useLiveData(featureFlagService.flags.enable_template_doc.$); const enabled = useLiveData(featureFlagService.flags.enable_template_doc.$);
const toggleMenu = useCallback(() => { const toggleMenu = useCallback(() => {
setMenuOpen(prev => !prev); setMenuOpen(prev => !prev);
}, []); }, []);
const createDocFromTemplate = useAsyncCallback(
async (templateId: string) => {
const docId = await docsService.duplicateFromTemplate(templateId);
workbench.openDoc(docId);
},
[docsService, workbench]
);
if (!enabled) { if (!enabled) {
return null; return null;
} }
@@ -49,10 +37,11 @@ export const TemplateDocEntrance = () => {
align: 'end', align: 'end',
alignOffset: -4, alignOffset: -4,
sideOffset: 16, sideOffset: 16,
style: { width: 280 },
}} }}
items={ items={
<TemplateListMenuContentScrollable <TemplateListMenuContentScrollable
onSelect={createDocFromTemplate} asLink
suffixItems={ suffixItems={
<> <>
<MenuSeparator /> <MenuSeparator />

View File

@@ -7,17 +7,19 @@ import { useState } from 'react';
import { type DocRecord } from '../../doc'; import { type DocRecord } from '../../doc';
import { DocDisplayMetaService } from '../../doc-display-meta'; import { DocDisplayMetaService } from '../../doc-display-meta';
import { WorkbenchLink } from '../../workbench';
import { TemplateDocService } from '../services/template-doc'; import { TemplateDocService } from '../services/template-doc';
import * as styles from './styles.css'; import * as styles from './styles.css';
interface CommonProps { interface CommonProps {
onSelect?: (docId: string) => void; onSelect?: (docId: string) => void;
asLink?: boolean;
} }
interface DocItemProps extends CommonProps { interface DocItemProps extends CommonProps {
doc: DocRecord; doc: DocRecord;
} }
const DocItem = ({ doc, onSelect }: DocItemProps) => { const DocItem = ({ doc, onSelect, asLink }: DocItemProps) => {
const docDisplayService = useService(DocDisplayMetaService); const docDisplayService = useService(DocDisplayMetaService);
const Icon = useLiveData(docDisplayService.icon$(doc.id)); const Icon = useLiveData(docDisplayService.icon$(doc.id));
const title = useLiveData(docDisplayService.title$(doc.id)); const title = useLiveData(docDisplayService.title$(doc.id));
@@ -26,7 +28,7 @@ const DocItem = ({ doc, onSelect }: DocItemProps) => {
onSelect?.(doc.id); onSelect?.(doc.id);
}, [doc.id, onSelect]); }, [doc.id, onSelect]);
return ( const menuItem = (
<MenuItem <MenuItem
prefixIcon={<Icon />} prefixIcon={<Icon />}
onClick={onClick} onClick={onClick}
@@ -35,6 +37,11 @@ const DocItem = ({ doc, onSelect }: DocItemProps) => {
{title} {title}
</MenuItem> </MenuItem>
); );
if (asLink) {
return <WorkbenchLink to={`/${doc.id}`}>{menuItem}</WorkbenchLink>;
}
return menuItem;
}; };
const Empty = () => { const Empty = () => {
@@ -95,6 +102,7 @@ interface TemplateListMenuProps
export const TemplateListMenu = ({ export const TemplateListMenu = ({
children, children,
onSelect, onSelect,
asLink,
prefixItems, prefixItems,
suffixItems, suffixItems,
contentOptions, contentOptions,
@@ -105,6 +113,7 @@ export const TemplateListMenu = ({
items={ items={
<TemplateListMenuContentScrollable <TemplateListMenuContentScrollable
onSelect={onSelect} onSelect={onSelect}
asLink={asLink}
prefixItems={prefixItems} prefixItems={prefixItems}
suffixItems={suffixItems} suffixItems={suffixItems}
/> />

View File

@@ -216,7 +216,7 @@ test('set default template for journal', async ({ page }) => {
await expect(page.getByText('This is a journal template doc')).toBeVisible(); await expect(page.getByText('This is a journal template doc')).toBeVisible();
}); });
test('create doc from template via sidebar entrance', async ({ page }) => { test('open template doc from sidebar template entrance', async ({ page }) => {
await openHomePage(page); await openHomePage(page);
await createDocAndMarkAsTemplate(page, 'Test Template', async () => { await createDocAndMarkAsTemplate(page, 'Test Template', async () => {
await page.keyboard.type('# Template'); await page.keyboard.type('# Template');
@@ -235,7 +235,7 @@ test('create doc from template via sidebar entrance', async ({ page }) => {
await expect(page.getByText('This is a template doc')).toBeVisible(); await expect(page.getByText('This is a template doc')).toBeVisible();
}); });
test('create template from sidebar template entrance', async ({ page }) => { test('create template doc from sidebar template entrance', async ({ page }) => {
await openHomePage(page); await openHomePage(page);
await page.getByTestId('sidebar-template-doc-entrance').click(); await page.getByTestId('sidebar-template-doc-entrance').click();
await page.getByTestId('template-doc-item-create').click(); await page.getByTestId('template-doc-item-create').click();