feat: add import snapshot option to import dialog (#8778)

This commit is contained in:
donteatfriedrice
2024-11-12 02:40:57 +00:00
parent 81fc9e1aa1
commit 713551fbf1
4 changed files with 53 additions and 5 deletions

View File

@@ -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>
</> </>

View File

@@ -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",

View File

@@ -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": "未选择文件",

View File

@@ -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": "未選擇文件",