fix(core): open template doc on sidebar template entrance (#9766)
close AF-2135, AF-2136, AF-2138, AF-2133
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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 />
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user