feat: add import snapshot option to import dialog (#8778)
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
|||||||
MarkdownTransformer,
|
MarkdownTransformer,
|
||||||
NotionHtmlTransformer,
|
NotionHtmlTransformer,
|
||||||
openFileOrFiles,
|
openFileOrFiles,
|
||||||
|
ZipTransformer,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import type { DocCollection } from '@blocksuite/affine/store';
|
import type { DocCollection } from '@blocksuite/affine/store';
|
||||||
import {
|
import {
|
||||||
@@ -18,14 +19,19 @@ import {
|
|||||||
HelpIcon,
|
HelpIcon,
|
||||||
NotionIcon,
|
NotionIcon,
|
||||||
} from '@blocksuite/icons/rc';
|
} from '@blocksuite/icons/rc';
|
||||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
import {
|
||||||
|
FeatureFlagService,
|
||||||
|
useLiveData,
|
||||||
|
useService,
|
||||||
|
WorkspaceService,
|
||||||
|
} from '@toeverything/infra';
|
||||||
import { cssVar } from '@toeverything/theme';
|
import { cssVar } from '@toeverything/theme';
|
||||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||||
import { type ReactElement, useCallback, useState } from 'react';
|
import { type ReactElement, useCallback, useState } from 'react';
|
||||||
|
|
||||||
import * as style from './styles.css';
|
import * as style from './styles.css';
|
||||||
|
|
||||||
type ImportType = 'markdown' | 'markdownZip' | 'notion';
|
type ImportType = 'markdown' | 'markdownZip' | 'notion' | 'snapshot';
|
||||||
type AcceptType = 'Markdown' | 'Zip';
|
type AcceptType = 'Markdown' | 'Zip';
|
||||||
type Status = 'idle' | 'importing' | 'success' | 'error';
|
type Status = 'idle' | 'importing' | 'success' | 'error';
|
||||||
type ImportResult = {
|
type ImportResult = {
|
||||||
@@ -46,6 +52,7 @@ const DISCORD_URL = 'https://discord.gg/whd5mjYqVw';
|
|||||||
|
|
||||||
const importOptions = [
|
const importOptions = [
|
||||||
{
|
{
|
||||||
|
key: 'markdown',
|
||||||
label: 'com.affine.import.markdown-files',
|
label: 'com.affine.import.markdown-files',
|
||||||
prefixIcon: (
|
prefixIcon: (
|
||||||
<ExportToMarkdownIcon
|
<ExportToMarkdownIcon
|
||||||
@@ -58,6 +65,7 @@ const importOptions = [
|
|||||||
type: 'markdown' as ImportType,
|
type: 'markdown' as ImportType,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
key: 'markdownZip',
|
||||||
label: 'com.affine.import.markdown-with-media-files',
|
label: 'com.affine.import.markdown-with-media-files',
|
||||||
prefixIcon: (
|
prefixIcon: (
|
||||||
<ExportToMarkdownIcon
|
<ExportToMarkdownIcon
|
||||||
@@ -70,6 +78,7 @@ const importOptions = [
|
|||||||
type: 'markdownZip' as ImportType,
|
type: 'markdownZip' as ImportType,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
key: 'notion',
|
||||||
label: 'com.affine.import.notion',
|
label: 'com.affine.import.notion',
|
||||||
prefixIcon: <NotionIcon color={cssVar('black')} width={20} height={20} />,
|
prefixIcon: <NotionIcon color={cssVar('black')} width={20} height={20} />,
|
||||||
suffixIcon: (
|
suffixIcon: (
|
||||||
@@ -137,6 +146,21 @@ const importConfigs: Record<ImportType, ImportConfig> = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
snapshot: {
|
||||||
|
fileOptions: { acceptType: 'Zip', multiple: false },
|
||||||
|
importFunction: async (docCollection, file) => {
|
||||||
|
if (Array.isArray(file)) {
|
||||||
|
throw new Error('Expected a single zip file for snapshot import');
|
||||||
|
}
|
||||||
|
const docIds = (await ZipTransformer.importDocs(docCollection, file))
|
||||||
|
.filter(doc => doc !== undefined)
|
||||||
|
.map(doc => doc.id);
|
||||||
|
|
||||||
|
return {
|
||||||
|
docIds,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImportOptionItem = ({
|
const ImportOptionItem = ({
|
||||||
@@ -176,14 +200,27 @@ const ImportOptions = ({
|
|||||||
onImport: (type: ImportType) => void;
|
onImport: (type: ImportType) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
|
const featureFlagService = useService(FeatureFlagService);
|
||||||
|
const enableSnapshotImportExport = useLiveData(
|
||||||
|
featureFlagService.flags.enable_snapshot_import_export.$
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={style.importModalTitle}>{t['Import']()}</div>
|
<div className={style.importModalTitle}>{t['Import']()}</div>
|
||||||
<div className={style.importModalContent}>
|
<div className={style.importModalContent}>
|
||||||
{importOptions.map(
|
{importOptions.map(
|
||||||
({ label, prefixIcon, suffixIcon, suffixTooltip, testId, type }) => (
|
({
|
||||||
|
key,
|
||||||
|
label,
|
||||||
|
prefixIcon,
|
||||||
|
suffixIcon,
|
||||||
|
suffixTooltip,
|
||||||
|
testId,
|
||||||
|
type,
|
||||||
|
}) => (
|
||||||
<ImportOptionItem
|
<ImportOptionItem
|
||||||
key={testId}
|
key={key}
|
||||||
prefixIcon={prefixIcon}
|
prefixIcon={prefixIcon}
|
||||||
suffixIcon={suffixIcon}
|
suffixIcon={suffixIcon}
|
||||||
suffixTooltip={suffixTooltip}
|
suffixTooltip={suffixTooltip}
|
||||||
@@ -195,6 +232,14 @@ const ImportOptions = ({
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{enableSnapshotImportExport && (
|
||||||
|
<div className={style.importModalTip}>
|
||||||
|
{t['Import']()}{' '}
|
||||||
|
<span className={style.link} onClick={() => onImport('snapshot')}>
|
||||||
|
{t['Snapshot']()}.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className={style.importModalTip}>
|
<div className={style.importModalTip}>
|
||||||
{t['com.affine.import.modal.tip']()}{' '}
|
{t['com.affine.import.modal.tip']()}{' '}
|
||||||
<a
|
<a
|
||||||
@@ -204,7 +249,7 @@ const ImportOptions = ({
|
|||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
Discord
|
Discord
|
||||||
</a>{' '}
|
</a>
|
||||||
.
|
.
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -522,6 +522,7 @@
|
|||||||
"com.affine.import.modal.tip": "If you'd like to request support for additional file types, feel free to let us know on",
|
"com.affine.import.modal.tip": "If you'd like to request support for additional file types, feel free to let us know on",
|
||||||
"com.affine.import.notion": "Notion",
|
"com.affine.import.notion": "Notion",
|
||||||
"com.affine.import.notion.tooltip": "Import your Notion data. Supported import formats: HTML with subpages.",
|
"com.affine.import.notion.tooltip": "Import your Notion data. Supported import formats: HTML with subpages.",
|
||||||
|
"com.affine.import.snapshot": "Snapshot",
|
||||||
"com.affine.import.status.failed.message": "Import failed, please try again.",
|
"com.affine.import.status.failed.message": "Import failed, please try again.",
|
||||||
"com.affine.import.status.failed.message.no-file-selected": "No file selected",
|
"com.affine.import.status.failed.message.no-file-selected": "No file selected",
|
||||||
"com.affine.import.status.failed.title": "Import failure",
|
"com.affine.import.status.failed.title": "Import failure",
|
||||||
|
|||||||
@@ -517,6 +517,7 @@
|
|||||||
"com.affine.import.markdown-with-media-files": "Markdown 文件(带媒体文件) (.zip)",
|
"com.affine.import.markdown-with-media-files": "Markdown 文件(带媒体文件) (.zip)",
|
||||||
"com.affine.import.modal.tip": "如果您希望请求支持其他文件类型,请随时告诉我们",
|
"com.affine.import.modal.tip": "如果您希望请求支持其他文件类型,请随时告诉我们",
|
||||||
"com.affine.import.notion": "Notion",
|
"com.affine.import.notion": "Notion",
|
||||||
|
"com.affine.import.snapshot": "快照",
|
||||||
"com.affine.import.notion.tooltip": "导入您的 Notion 数据。支持导入格式:HTML 带子页面。",
|
"com.affine.import.notion.tooltip": "导入您的 Notion 数据。支持导入格式:HTML 带子页面。",
|
||||||
"com.affine.import.status.failed.message": "导入失败,请重试。",
|
"com.affine.import.status.failed.message": "导入失败,请重试。",
|
||||||
"com.affine.import.status.failed.message.no-file-selected": "未选择文件",
|
"com.affine.import.status.failed.message.no-file-selected": "未选择文件",
|
||||||
|
|||||||
@@ -514,6 +514,7 @@
|
|||||||
"com.affine.import.markdown-with-media-files": "Markdown 文件(帶媒體文件) (.zip)",
|
"com.affine.import.markdown-with-media-files": "Markdown 文件(帶媒體文件) (.zip)",
|
||||||
"com.affine.import.modal.tip": "如果您希望請求支持其他文件類型,請隨時告訴我們",
|
"com.affine.import.modal.tip": "如果您希望請求支持其他文件類型,請隨時告訴我們",
|
||||||
"com.affine.import.notion": "Notion",
|
"com.affine.import.notion": "Notion",
|
||||||
|
"com.affine.import.snapshot": "快照",
|
||||||
"com.affine.import.notion.tooltip": "導入您的 Notion 數據。支持導入格式:HTML 帶子頁面。",
|
"com.affine.import.notion.tooltip": "導入您的 Notion 數據。支持導入格式:HTML 帶子頁面。",
|
||||||
"com.affine.import.status.failed.message": "導入失敗,請重試。",
|
"com.affine.import.status.failed.message": "導入失敗,請重試。",
|
||||||
"com.affine.import.status.failed.message.no-file-selected": "未選擇文件",
|
"com.affine.import.status.failed.message.no-file-selected": "未選擇文件",
|
||||||
|
|||||||
Reference in New Issue
Block a user