diff --git a/.all-contributorsrc b/.all-contributorsrc
index 899398450..4b1cc3587 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -12,6 +12,16 @@
"contributorsPerLine": 7,
"badgeTemplate": "\n[all-contributors-badge]: https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat-square\n",
"contributors": [
+ {
+ "login": "doodlewind",
+ "name": "Yifeng Wang",
+ "avatar_url": "https://avatars.githubusercontent.com/u/7312949?v=4",
+ "profile": "https://github.com/doodlewind",
+ "contributions": [
+ "code",
+ "doc"
+ ]
+ },
{
"login": "darkskygit",
"name": "DarkSky",
@@ -303,6 +313,15 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "felixonmars",
+ "name": "Felix Yan",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1006477?v=4",
+ "profile": "https://felixc.at/",
+ "contributions": [
+ "code"
+ ]
}
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index e69da8bc9..18f956c61 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,6 +5,7 @@
"editor.codeActionsOnSave": ["source.fixAll", "source.organizeImports"],
"prettier.prettierPath": "./node_modules/prettier",
"cSpell.words": [
+ "aboutus",
"AUTOINCREMENT",
"Backlinks",
"blockdb",
diff --git a/README.md b/README.md
index b2507efa5..d4f92bc51 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066
-->
-[all-contributors-badge]: https://img.shields.io/badge/all_contributors-31-orange.svg?style=flat-square
+[all-contributors-badge]: https://img.shields.io/badge/all_contributors-33-orange.svg?style=flat-square
@@ -58,9 +58,8 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066
[](https://affine.pro) No installation or registration required! Head over to our website and try it out now.
-Want to deploy it yourself? AFFiNE can run just about anywhere. Check our
-[documentation](#documentation)
-for more information.
+Want to deploy it yourself? AFFiNE can run just about anywhere.
+You can refer to our documentation which can be found from the [useful links](#useful-links) section - where you will also find ways to help contribute to the project and join our communities.
⚠️ Please note that AFFiNE is still under active development and is not yet ready for production use. ⚠️
@@ -119,7 +118,7 @@ That's why we are making AFFiNE. Some of the most important features are:
- Data is always stored locally by default
- CRDTs are applied so that peer-to-peer collaboration is possible.
-We appreciate the ideas of Monday, Airtable, and Notion databases. They have inspired us and shaped our product, helping us get it right when it comes to task management. But we also do things differently. We don't like doing things again and again. It's easy to set a todo with Markdown, but then why do you need to repeat and recreate data for a kanban or other databases. This is the power of AFFiNE. With AFFiNE, every block group has infinite views, for you to keep your single source of data, a signle source of truth.
+We appreciate the ideas of Monday, Airtable, and Notion databases. They have inspired us and shaped our product, helping us get it right when it comes to task management. But we also do things differently. We don't like doing things again and again. It's easy to set a todo with Markdown, but then why do you need to repeat and recreate data for a kanban or other databases. This is the power of AFFiNE. With AFFiNE, every block group has infinite views, for you to keep your single source of data, a single source of truth.
We would like to give special thanks to the innovators and pioneers who greatly inspired us:
@@ -148,45 +147,47 @@ Thanks a lot to the community for providing such powerful and simple libraries,
${text}`;
+ }
+ if (textValue.strikethrough) {
+ return `${content}`;
+ override async block2html(props: Block2HtmlProps) {
+ return `${await commonBlock2HtmlContent(props)}`;
}
}
diff --git a/libs/components/editor-blocks/src/blocks/divider/index.ts b/libs/components/editor-blocks/src/blocks/divider/index.ts
index 6d67611cd..f77722838 100644
--- a/libs/components/editor-blocks/src/blocks/divider/index.ts
+++ b/libs/components/editor-blocks/src/blocks/divider/index.ts
@@ -1,39 +1,35 @@
import {
AsyncBlock,
BaseView,
+ BlockEditor,
+ HTML2BlockResult,
SelectBlock,
} from '@toeverything/framework/virgo';
import { Protocol } from '@toeverything/datasource/db-service';
import { DividerView } from './divider-view';
+import { Block2HtmlProps, commonHTML2block } from '../../utils/commonBlockClip';
export class DividerBlock extends BaseView {
type = Protocol.Block.Type.divider;
View = DividerView;
- override html2block(
- el: Element,
- parseEl: (el: Element) => any[]
- ): any[] | null {
- const tag_name = el.tagName;
- if (tag_name === 'HR') {
- return [
- {
- type: this.type,
- properties: {
- text: {},
- },
- children: [],
- },
- ];
- }
- return null;
+ override async html2block({
+ element,
+ editor,
+ }: {
+ element: Element;
+ editor: BlockEditor;
+ }): Promise {
+ return commonHTML2block({
+ element,
+ editor,
+ type: this.type,
+ tagName: 'HR',
+ ignoreEmptyElement: false,
+ });
}
- override async block2html(
- block: AsyncBlock,
- children: SelectBlock[],
- generateHtml: (el: any[]) => Promise
- ): Promise {
- return `
`;
+ override async block2html(props: Block2HtmlProps) {
+ return `
`;
}
}
diff --git a/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx b/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx
index 86b43908d..c3e7199c2 100644
--- a/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx
+++ b/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx
@@ -33,7 +33,7 @@ export const EmbedLinkView = (props: EmbedLinkView) => {
};
return (
-
+
{embedLinkUrl ? (
any[]
- ): any[] | null {
- const tag_name = el.tagName;
- if (tag_name === 'A' && el.parentElement?.childElementCount === 1) {
- return [
- {
- type: this.type,
- properties: {
- // TODO: Not sure what value to fill for name
- embedLink: {
- name: this.type,
- value: el.getAttribute('href'),
- },
- },
- children: [],
- },
- ];
- }
-
- return null;
- }
-
- override async block2html(
- block: AsyncBlock,
- children: SelectBlock[],
- generateHtml: (el: any[]) => Promise
- ): Promise {
- const figma_url = block.getProperty('embedLink')?.value;
- return ``;
+ override async block2html({ block }: Block2HtmlProps) {
+ const url = block.getProperty('embedLink')?.value;
+ return ``;
}
}
diff --git a/libs/components/editor-blocks/src/blocks/figma/FigmaView.tsx b/libs/components/editor-blocks/src/blocks/figma/FigmaView.tsx
index 7375546da..694928064 100644
--- a/libs/components/editor-blocks/src/blocks/figma/FigmaView.tsx
+++ b/libs/components/editor-blocks/src/blocks/figma/FigmaView.tsx
@@ -1,13 +1,12 @@
-import { useState } from 'react';
-import { CreateView } from '@toeverything/framework/virgo';
import {
- useOnSelect,
BlockPendantProvider,
+ useOnSelect,
} from '@toeverything/components/editor-core';
-import { Upload } from '../../components/upload/upload';
+import { CreateView } from '@toeverything/framework/virgo';
+import { useState } from 'react';
import { SourceView } from '../../components/source-view';
-import { styled } from '@toeverything/components/ui';
import { LinkContainer } from '../../components/style-container';
+import { Upload } from '../../components/upload/upload';
const MESSAGES = {
ADD_FIGMA_LINK: 'Add figma link',
@@ -30,7 +29,7 @@ export const FigmaView = ({ block, editor }: FigmaView) => {
setIsSelect(isSelect);
});
return (
-
+
{figmaUrl ? (
any[]
- ): any[] | null {
- const tag_name = el.tagName;
- if (tag_name === 'A' && el.parentElement?.childElementCount === 1) {
- const href = el.getAttribute('href');
- const allowedHosts = ['www.figma.com'];
- const host = new URL(href).host;
-
- if (allowedHosts.includes(host)) {
- return [
- {
- type: this.type,
- properties: {
- // TODO: Not sure what value to fill for name
- embedLink: {
- name: this.type,
- value: el.getAttribute('href'),
- },
- },
- children: [],
- },
- ];
- }
- }
-
- return null;
- }
-
- override async block2html(
- block: AsyncBlock,
- children: SelectBlock[],
- generateHtml: (el: any[]) => Promise
- ): Promise {
- const figma_url = block.getProperty('embedLink')?.value;
- return ``;
+ override async block2html({ block }: Block2HtmlProps) {
+ const figmaUrl = block.getProperty('embedLink')?.value;
+ return ``;
}
}
diff --git a/libs/components/editor-blocks/src/blocks/file/index.ts b/libs/components/editor-blocks/src/blocks/file/index.ts
index e3119e9a1..c2f12c0c6 100644
--- a/libs/components/editor-blocks/src/blocks/file/index.ts
+++ b/libs/components/editor-blocks/src/blocks/file/index.ts
@@ -9,25 +9,22 @@ import {
services,
} from '@toeverything/datasource/db-service';
import { FileView } from './FileView';
+import { Block2HtmlProps } from '../../utils/commonBlockClip';
export class FileBlock extends BaseView {
public override selectable = true;
public override editable = false;
type = Protocol.Block.Type.file;
View = FileView;
+ override async block2html({ block }: Block2HtmlProps) {
+ const fileProperty = block.getProperty('file');
+ const fileId = fileProperty?.value;
+ const fileInfo = fileId
+ ? await services.api.file.get(fileId, block.workspace)
+ : null;
- override async block2html(
- block: AsyncBlock,
- children: SelectBlock[],
- generateHtml: (el: any[]) => Promise
- ): Promise {
- const file_property =
- block.getProperty('file') || ({} as FileColumnValue);
- const file_id = file_property.value;
- let file_info = null;
- if (file_id) {
- file_info = await services.api.file.get(file_id, block.workspace);
- }
- return ``;
+ return fileInfo
+ ? ``
+ : '';
}
}
diff --git a/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx b/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx
index 3a598b314..620a25dba 100644
--- a/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx
+++ b/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx
@@ -1,4 +1,4 @@
-import { RenderBlock } from '@toeverything/components/editor-core';
+import { RenderBlockChildren } from '@toeverything/components/editor-core';
import { ChildrenView, CreateView } from '@toeverything/framework/virgo';
export const GridItemRender = function (
@@ -6,13 +6,7 @@ export const GridItemRender = function (
) {
const GridItem = function (props: CreateView) {
const { block } = props;
- const children = (
- <>
- {block.childrenIds.map(id => {
- return ;
- })}
- >
- );
+ const children = ;
return <>{creator({ ...props, children })}>;
};
return GridItem;
diff --git a/libs/components/editor-blocks/src/blocks/grid/Grid.tsx b/libs/components/editor-blocks/src/blocks/grid/Grid.tsx
index 4ecf47f3b..a8e69125d 100644
--- a/libs/components/editor-blocks/src/blocks/grid/Grid.tsx
+++ b/libs/components/editor-blocks/src/blocks/grid/Grid.tsx
@@ -1,16 +1,16 @@
-import { RenderBlock } from '@toeverything/components/editor-core';
-import { CreateView } from '@toeverything/framework/virgo';
-import React, { useEffect, useRef, useState } from 'react';
-import { GridHandle } from './GirdHandle';
+import { BlockRender } from '@toeverything/components/editor-core';
import { styled } from '@toeverything/components/ui';
+import { Protocol } from '@toeverything/datasource/db-service';
+import { CreateView } from '@toeverything/framework/virgo';
+import { debounce, domToRect, Point } from '@toeverything/utils';
+import clsx from 'clsx';
+import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import {
GRID_ITEM_CLASS_NAME,
GRID_ITEM_CONTENT_CLASS_NAME,
} from '../grid-item/GridItem';
-import { debounce, domToRect, Point } from '@toeverything/utils';
-import clsx from 'clsx';
-import { Protocol } from '@toeverything/datasource/db-service';
+import { GridHandle } from './GirdHandle';
const DB_UPDATE_DELAY = 50;
const GRID_ON_DRAG_CLASS = 'grid-layout-on-drag';
@@ -226,7 +226,7 @@ export const Grid = function (props: CreateView) {
key={id}
className={GRID_ITEM_CLASS_NAME}
>
-
+
handleDragGrid(event, i)}
editor={editor}
diff --git a/libs/components/editor-blocks/src/blocks/group/Group.tsx b/libs/components/editor-blocks/src/blocks/group/Group.tsx
index 787c537f1..ea27bbbd3 100644
--- a/libs/components/editor-blocks/src/blocks/group/Group.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/Group.tsx
@@ -6,6 +6,10 @@ import {
SelectBlock,
} from '@toeverything/framework/virgo';
import { GroupView } from './GroupView';
+import {
+ Block2HtmlProps,
+ commonBlock2HtmlContent,
+} from '../../utils/commonBlockClip';
export class Group extends BaseView {
public override selectable = true;
@@ -25,13 +29,12 @@ export class Group extends BaseView {
override async onCreate(block: AsyncBlock): Promise {
return block;
}
-
- override async block2html(
- block: AsyncBlock,
- children: SelectBlock[],
- generateHtml: (el: any[]) => Promise
- ): Promise {
- const content = await generateHtml(children);
- return `${content}`;
+ override async block2html({ editor, selectInfo, block }: Block2HtmlProps) {
+ const childrenHtml =
+ await editor.clipboard.clipboardUtils.convertBlock2HtmlBySelectInfos(
+ block,
+ selectInfo?.children
+ );
+ return `${childrenHtml}`;
}
}
diff --git a/libs/components/editor-blocks/src/blocks/group/GroupView.tsx b/libs/components/editor-blocks/src/blocks/group/GroupView.tsx
index 791059e36..f0d6e56cc 100644
--- a/libs/components/editor-blocks/src/blocks/group/GroupView.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/GroupView.tsx
@@ -21,19 +21,6 @@ const SceneMap: Record> = {
kanban: SceneKanban,
} as const;
-const GroupBox = styled('div')(({ theme }) => {
- return {
- '&:hover': {
- // Workaround referring to other components
- // See https://emotion.sh/docs/styled#targeting-another-emotion-component
- // [GroupActionWrapper.toString()]: {},
- '& > *': {
- visibility: 'visible',
- },
- },
- };
-});
-
const GroupActionWrapper = styled('div')(({ theme }) => ({
height: '30px',
display: 'flex',
@@ -59,6 +46,14 @@ const GroupActionWrapper = styled('div')(({ theme }) => ({
},
}));
+const GroupBox = styled('div')({
+ '&:hover': {
+ [GroupActionWrapper.toString()]: {
+ visibility: 'visible',
+ },
+ },
+});
+
const GroupContainer = styled('div')<{ isSelect?: boolean }>(
({ isSelect, theme }) => ({
background: theme.affine.palette.white,
diff --git a/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx b/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx
index 6145bec11..739927626 100644
--- a/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx
@@ -2,5 +2,5 @@ import { RenderBlockChildren } from '@toeverything/components/editor-core';
import type { CreateView } from '@toeverything/framework/virgo';
export const ScenePage = ({ block }: CreateView) => {
- return ;
+ return ;
};
diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx
index a376785b5..e1cee48f3 100644
--- a/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx
@@ -41,7 +41,7 @@ export const AddViewMenu = () => {
onClick={() => setActivePanel(!activePanel)}
>
- Add View
+ Add View
{activePanel && (
@@ -66,10 +66,10 @@ export const AddViewMenu = () => {
key={name}
active={viewType === scene}
onClick={() => {
- if (scene === RecastScene.Table) {
- // The table view is under progress
- return;
- }
+ // if (scene === RecastScene.Table) {
+ // // The table view is under progress
+ // return;
+ // }
setViewType(scene);
}}
style={{ textTransform: 'uppercase' }}
diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx
index 92aa53566..43b819aab 100644
--- a/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx
@@ -82,7 +82,7 @@ const GroupMenuWrapper = ({
content={
-
+ {/* */}
{
// // Closed beta period temporarily
// filterSorterFlag && (
diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx
index 1fee99465..273911a94 100644
--- a/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx
@@ -20,7 +20,7 @@ export const ViewsMenu = () => {
useRecastView();
const handleChange = (e: ChangeEvent) => {
- setViewName(e.target.value.trim());
+ setViewName(e.target.value);
};
const handleKeyDown = (event: KeyboardEvent) => {
@@ -36,7 +36,7 @@ export const ViewsMenu = () => {
}
await updateView({
...activeView,
- name: viewName,
+ name: viewName.trim(),
type: viewType,
});
setActiveView(null);
@@ -99,10 +99,10 @@ export const ViewsMenu = () => {
key={name}
active={viewType === scene}
onClick={() => {
- if (scene === RecastScene.Table) {
- // The table view is under progress
- return;
- }
+ // if (scene === RecastScene.Table) {
+ // // The table view is under progress
+ // return;
+ // }
setViewType(scene);
}}
style={{ textTransform: 'uppercase' }}
diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx
index 0f2a1887d..7a057eccb 100644
--- a/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx
@@ -1,9 +1,5 @@
import { RecastScene } from '@toeverything/components/editor-core';
-import {
- KanBanIcon,
- TableIcon,
- TodoListIcon,
-} from '@toeverything/components/icons';
+import { KanBanIcon, TodoListIcon } from '@toeverything/components/icons';
export const VIEW_LIST = [
{
@@ -16,9 +12,9 @@ export const VIEW_LIST = [
scene: RecastScene.Kanban,
icon: ,
},
- {
- name: 'Table',
- scene: RecastScene.Table,
- icon: ,
- },
+ // {
+ // name: 'Table',
+ // scene: RecastScene.Table,
+ // icon: ,
+ // },
] as const;
diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardContext.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardContext.tsx
index 13fcaa45e..74afbe087 100644
--- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardContext.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardContext.tsx
@@ -1,12 +1,12 @@
-import { useCallback } from 'react';
-import { CardItem } from './CardItem';
-import { styled } from '@toeverything/components/ui';
-import { useKanban } from '@toeverything/components/editor-core';
-import { CardItemPanelWrapper } from './dndable/wrapper/CardItemPanelWrapper';
import type {
KanbanCard,
KanbanGroup,
} from '@toeverything/components/editor-core';
+import { useKanban } from '@toeverything/components/editor-core';
+import { styled } from '@toeverything/components/ui';
+import { useCallback } from 'react';
+import { CardItem } from './CardItem';
+import { CardItemPanelWrapper } from './dndable/wrapper/CardItemPanelWrapper';
const AddCardWrapper = styled('div')({
display: 'flex',
@@ -48,7 +48,7 @@ export const CardContext = (props: Props) => {
item={item}
active={activeId === id}
>
-
+
);
diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx
index 837772bed..b52771121 100644
--- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx
@@ -1,6 +1,6 @@
import {
+ KanbanBlockRender,
KanbanCard,
- RenderBlock,
useEditor,
useKanban,
} from '@toeverything/components/editor-core';
@@ -10,7 +10,6 @@ import {
MuiClickAwayListener,
styled,
} from '@toeverything/components/ui';
-import { useFlag } from '@toeverything/datasource/feature-flags';
import { useState, type MouseEvent } from 'react';
import { useRefPage } from './RefPage';
@@ -82,41 +81,37 @@ const Overlay = styled('div')({
},
});
-export const CardItem = ({
- id,
- block,
-}: {
- id: KanbanCard['id'];
- block: KanbanCard['block'];
-}) => {
+export const CardItem = ({ block }: { block: KanbanCard['block'] }) => {
const { addSubItem } = useKanban();
const { openSubPage } = useRefPage();
- const [editable, setEditable] = useState(false);
- const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false);
+ const [editableBlock, setEditableBlock] = useState(null);
const { editor } = useEditor();
const onAddItem = async () => {
- setEditable(true);
- await addSubItem(block);
+ const newItem = await addSubItem(block);
+ setEditableBlock(newItem.id);
};
const onClickCard = async () => {
- openSubPage(id);
+ openSubPage(block.id);
};
const onClickPen = (e: MouseEvent) => {
e.stopPropagation();
- setEditable(true);
+ setEditableBlock(block.id);
editor.selectionManager.activeNodeByNodeId(block.id);
};
return (
- setEditable(false)}>
+ setEditableBlock(null)}>
-
+
- {showKanbanRefPageFlag && !editable && (
+ {!editableBlock && (
diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx
index 3d223d121..34d6dbb58 100644
--- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx
+++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx
@@ -21,13 +21,17 @@ const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => {
return createPortal(
void }) => {
+ // Prevent trigger the bottom editor's selection
+ e.stopPropagation();
+ }}
+ onClick={closeSubPage}
style={{
display: 'flex',
flexDirection: 'column',
background: 'rgba(58, 76, 92, 0.4)',
zIndex: theme.affine.zIndex.popover,
}}
- onClick={closeSubPage}
>