diff --git a/.github/deployment/Dockerfile-affine b/.github/deployment/Dockerfile-affine index 5cf4243eab..9d54eb0cf4 100644 --- a/.github/deployment/Dockerfile-affine +++ b/.github/deployment/Dockerfile-affine @@ -1,8 +1,9 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . -RUN apk add g++ make python3 git libpng-dev -RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build:local --skip-nx-cache +# RUN apk add g++ make python3 git libpng-dev +RUN apk add git +RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build:local --skip-nx-cache FROM node:16-alpine as relocate WORKDIR /app diff --git a/.github/deployment/Dockerfile-lisa b/.github/deployment/Dockerfile-lisa index 471e4d0d48..f469a7fce8 100644 --- a/.github/deployment/Dockerfile-lisa +++ b/.github/deployment/Dockerfile-lisa @@ -1,8 +1,9 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . -RUN apk add g++ make python3 git libpng-dev -RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build +# RUN apk add g++ make python3 git libpng-dev +RUN apk add git +RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build FROM node:16-alpine as relocate WORKDIR /app diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 4e99d6bbb0..af9e8982fe 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -6,8 +6,8 @@ import { deepCopy, TldrawApp } from '@toeverything/components/board-state'; import { tools } from '@toeverything/components/board-tools'; import { TDShapeType } from '@toeverything/components/board-types'; import { - RecastBlockProvider, getClipDataOfBlocksById, + RecastBlockProvider, } from '@toeverything/components/editor-core'; import { services } from '@toeverything/datasource/db-service'; import { AsyncBlock, BlockEditor } from '@toeverything/framework/virgo'; @@ -25,7 +25,6 @@ const AffineBoard = ({ editor, }: AffineBoardProps & { editor: BlockEditor }) => { const [app, set_app] = useState(); - const [document] = useState(() => { return { ...deepCopy(TldrawApp.default_document), @@ -52,10 +51,10 @@ const AffineBoard = ({ }; }); - const shapes = useShapes(workspace, rootBlockId); + const { shapes, bindings } = useShapes(workspace, rootBlockId); useEffect(() => { if (app) { - app.replacePageContent(shapes || {}, {}, {}); + app.replacePageContent(shapes || {}, bindings, {}); } }, [app, shapes]); @@ -69,6 +68,7 @@ const AffineBoard = ({ onMount(app) { set_app(app); }, + async onCopy(e, groupIds) { const clip = await getClipDataOfBlocksById( editor, @@ -80,7 +80,7 @@ const AffineBoard = ({ clip.getData() ); }, - onChangePage(app, shapes, bindings, assets) { + async onChangePage(app, shapes, bindings, assets) { Promise.all( Object.entries(shapes).map(async ([id, shape]) => { if (shape === undefined) { @@ -109,7 +109,20 @@ const AffineBoard = ({ }); } shape.affineId = block.id; - return services.api.editorBlock.update({ + + Object.keys(bindings).forEach(bilingKey => { + if ( + bindings[bilingKey]?.fromId === shape.id + ) { + bindings[bilingKey].fromId = block.id; + } + if ( + bindings[bilingKey]?.toId === shape.id + ) { + bindings[bilingKey].toId = block.id; + } + }); + return await services.api.editorBlock.update({ workspace: shape.workspace, id: block.id, properties: { @@ -121,6 +134,32 @@ const AffineBoard = ({ } }) ); + let pageBindingsString = ( + await services.api.editorBlock.get({ + workspace: workspace, + ids: [rootBlockId], + }) + )?.[0].properties.bindings?.value; + console.log(123123123); + let pageBindings = JSON.parse(pageBindingsString ?? '{}'); + console.log(pageBindings, 3333, bindings); + Object.keys(bindings).forEach(bindingsKey => { + console.log(345345345345345); + if (!bindings[bindingsKey]) { + delete pageBindings[bindingsKey]; + } else { + Object.assign(pageBindings, bindings); + } + }); + services.api.editorBlock.update({ + workspace: workspace, + id: rootBlockId, + properties: { + bindings: { + value: JSON.stringify(pageBindings), + }, + }, + }); }, }} /> diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index 7d07a25957..beb8c50efa 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -5,32 +5,56 @@ import { services } from '@toeverything/datasource/db-service'; import { usePageClientWidth } from '@toeverything/datasource/state'; import { useEffect, useState } from 'react'; +const getBindings = (workspace: string, rootBlockId: string) => { + return services.api.editorBlock + .get({ + workspace: workspace, + ids: [rootBlockId], + }) + .then(blcoks => { + return blcoks[0].properties.bindings?.value; + }); +}; + export const useShapes = (workspace: string, rootBlockId: string) => { const { pageClientWidth } = usePageClientWidth(); // page padding left and right total 300px const editorShapeInitSize = pageClientWidth - 300; - const [blocks, setBlocks] = useState(); + const [blocks, setBlocks] = useState<{ + shapes: [ReturnEditorBlock[]]; + bindings: string; + }>(); useEffect(() => { - services.api.editorBlock - .get({ workspace, ids: [rootBlockId] }) - .then(async blockData => { - const shapes = await Promise.all( - (blockData?.[0]?.children || []).map(async childId => { - const childBlock = ( - await services.api.editorBlock.get({ - workspace, - ids: [childId], - }) - )?.[0]; - return childBlock; - }) - ); - setBlocks(shapes); + Promise.all([ + services.api.editorBlock + .get({ workspace, ids: [rootBlockId] }) + .then(async blockData => { + const shapes = await Promise.all( + (blockData?.[0]?.children || []).map(async childId => { + const childBlock = ( + await services.api.editorBlock.get({ + workspace, + ids: [childId], + }) + )?.[0]; + return childBlock; + }) + ); + return shapes; + }), + ]).then(shapes => { + getBindings(workspace, rootBlockId).then(bindings => { + setBlocks({ + shapes, + bindings: bindings, + }); }); + }); + let unobserve: () => void; services.api.editorBlock .observe({ workspace, id: rootBlockId }, async blockData => { - const shapes = await Promise.all( + Promise.all( (blockData?.children || []).map(async childId => { const childBlock = ( await services.api.editorBlock.get({ @@ -40,8 +64,14 @@ export const useShapes = (workspace: string, rootBlockId: string) => { )?.[0]; return childBlock; }) - ); - setBlocks(shapes); + ).then(shapes => { + getBindings(workspace, rootBlockId).then(bindings => { + setBlocks({ + shapes: [shapes], + bindings: bindings, + }); + }); + }); }) .then(cb => { unobserve = cb; @@ -53,8 +83,7 @@ export const useShapes = (workspace: string, rootBlockId: string) => { }, [workspace, rootBlockId]); let groupCount = 0; - - return blocks?.reduce((acc, block) => { + let blocksShapes = blocks?.shapes[0]?.reduce((acc, block) => { const shapeProps = block.properties.shapeProps?.value ? JSON.parse(block.properties.shapeProps.value) : {}; @@ -75,4 +104,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return acc; }, {} as Record); + return { + shapes: blocksShapes, + bindings: JSON.parse(blocks?.bindings ?? '{}'), + }; }; diff --git a/libs/components/board-draw/src/TlDraw.tsx b/libs/components/board-draw/src/TlDraw.tsx index 338fffeeaf..1961367235 100644 --- a/libs/components/board-draw/src/TlDraw.tsx +++ b/libs/components/board-draw/src/TlDraw.tsx @@ -13,6 +13,8 @@ import { TDStatus, } from '@toeverything/components/board-types'; import { styled } from '@toeverything/components/ui'; +// import { FocusButton } from '~components/FocusButton'; +import { usePageClientWidth } from '@toeverything/datasource/state'; import { memo, useEffect, @@ -22,22 +24,20 @@ import { useState, type RefObject, } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import { CommandPanel } from './components/command-panel'; +// import { TopPanel } from '~components/TopPanel'; +import { ContextMenu } from './components/context-menu'; +import { ErrorFallback } from './components/error-fallback'; +import { Loading } from './components/loading'; import { ToolsPanel } from './components/tools-panel'; +import { ZoomBar } from './components/zoom-bar'; import { TldrawContext, useKeyboardShortcuts, useStylesheet, useTldrawApp, } from './hooks'; -// import { TopPanel } from '~components/TopPanel'; -import { ContextMenu } from './components/context-menu'; -// import { FocusButton } from '~components/FocusButton'; -import { usePageClientWidth } from '@toeverything/datasource/state'; -import { ErrorBoundary } from 'react-error-boundary'; -import { CommandPanel } from './components/command-panel'; -import { ErrorFallback } from './components/error-fallback'; -import { Loading } from './components/loading'; -import { ZoomBar } from './components/zoom-bar'; export interface TldrawProps extends TldrawAppCtorProps { /** @@ -295,7 +295,6 @@ const InnerTldraw = memo(function InnerTldraw({ const pageState = document.pageStates[page.id]; const assets = document.assets; const { selectedIds } = pageState; - const isHideBoundsShape = selectedIds.length === 1 && page.shapes[selectedIds[0]] && diff --git a/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx new file mode 100644 index 0000000000..21f37a9fbc --- /dev/null +++ b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx @@ -0,0 +1,78 @@ +import type { TldrawApp } from '@toeverything/components/board-state'; +import type { + ArrowBinding, + TDShape, +} from '@toeverything/components/board-types'; +import { ConnectorIcon } from '@toeverything/components/icons'; +import { IconButton, Popover, Tooltip } from '@toeverything/components/ui'; +import { useEffect, useState } from 'react'; +import { ListItemContainer, ListItemTitle } from './FontSizeConfig'; + +interface GroupAndUnGroupProps { + app: TldrawApp; + shapes: TDShape[]; +} + +export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => { + const [arrowToArr, setarrowToArr] = useState([]); + useEffect(() => { + let allShape = app.shapes; + let bindings = app.page.bindings; + let activeShape = shapes[0]; + let toNextShapBindings: ArrowBinding[] = []; + let bindingId = ''; + Object.keys(bindings).forEach(key => { + if (bindings[key].toId === activeShape.id) { + bindingId = bindings[key].fromId; + } + }); + Object.keys(bindings).forEach(key => { + if (bindings[key].fromId === bindingId) { + toNextShapBindings.push(bindings[key]); + } + }); + let ArrowToArr: TDShape[] = []; + toNextShapBindings.forEach(binding => { + if (binding.toId !== activeShape.id) { + allShape.forEach(item => { + console.log(item); + if (item.id === binding.toId) { + ArrowToArr.push(item); + } + }); + } + }); + setarrowToArr(ArrowToArr); + return () => {}; + }, [app.page.bindings, app.shapes]); + const jumpToNextShap = (shape: TDShape) => { + app.zoomToShapes([shape]); + }; + + return ( + + {arrowToArr.map((arrow: any) => { + return ( + jumpToNextShap(arrow)} + > + {arrow.name} + + ); + })} + + } + > + + + + + + + ); +}; diff --git a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx index c07bfa88b4..94e28bdc2f 100644 --- a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx +++ b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx @@ -2,6 +2,7 @@ import { TLDR, TldrawApp } from '@toeverything/components/board-state'; import { Divider, Popover, styled } from '@toeverything/components/ui'; import { Fragment } from 'react'; import { AlignOperation } from './AlignOperation'; +import { ArrowTo } from './ArrowTo'; import { BorderColorConfig } from './BorderColorConfig'; import { DeleteShapes } from './DeleteOperation'; import { FillColorConfig } from './FillColorConfig'; @@ -106,6 +107,12 @@ export const CommandPanel = ({ app }: { app: TldrawApp }) => { shapes={config.deleteShapes.selectedShapes} > ) : null, + toNextShap: ( + + ), }; const nodes = Object.entries(configNodes).filter(([key, node]) => !!node); diff --git a/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx b/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx index c35226911c..38fbbfae22 100644 --- a/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx +++ b/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx @@ -86,7 +86,7 @@ export const FontSizeConfig = ({ app, shapes }: FontSizeConfigProps) => { ); }; -const ListItemContainer = styled('div')(({ theme }) => ({ +export const ListItemContainer = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', cursor: 'pointer', @@ -100,7 +100,7 @@ const ListItemContainer = styled('div')(({ theme }) => ({ }, })); -const ListItemTitle = styled('span')(({ theme }) => ({ +export const ListItemTitle = styled('span')(({ theme }) => ({ marginLeft: '12px', color: theme.affine.palette.primaryText, })); diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index 896669029b..34a392db72 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -444,7 +444,6 @@ export class TldrawApp extends StateManager { if (visitedShapes.has(fromShape)) { return; } - // We only need to update the binding's "from" shape (an arrow) const fromDelta = TLDR.update_arrow_bindings( page, @@ -860,7 +859,6 @@ export class TldrawApp extends StateManager { if (!page.bindings[binding.id]) { return; } - const fromShape = page.shapes[binding.fromId] as ArrowShape; if (visitedShapes.has(fromShape)) { @@ -868,6 +866,7 @@ export class TldrawApp extends StateManager { } // We only need to update the binding's "from" shape (an arrow) + const fromDelta = TLDR.update_arrow_bindings(page, fromShape); visitedShapes.add(fromShape); diff --git a/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts b/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts index f2d1c861b6..ca51be0f8c 100644 --- a/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts +++ b/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts @@ -53,6 +53,7 @@ export type DefaultColumnsValue = { filterConstraint: FilterConstraint; filterWeakSqlConstraint: string; sorterConstraint: SorterConstraint; + bindings: StringColumnValue; }; export const DEFAULT_COLUMN_KEYS = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb9b238428..802d964374 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -288,7 +288,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -299,7 +299,7 @@ importers: '@tldraw/vec': ^1.7.0 perfect-freehand: ^1.0.16 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 perfect-freehand: 1.1.0 @@ -312,7 +312,7 @@ importers: idb-keyval: ^6.2.0 zustand: ^3.7.2 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 idb-keyval: 6.2.0 @@ -324,7 +324,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -334,7 +334,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -6200,6 +6200,28 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true + /@tldraw/core/1.14.1: + resolution: {integrity: sha512-FAiX/TD/tl5eMvTk0IHhFUSmldCe/UTTOnLL5aWQHqhicF/iTP5m3H12L6kyjN60yfssN8U9g4E/7y70TY7JxA==} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + '@tldraw/intersect': 1.7.1 + '@tldraw/vec': 1.7.1 + '@use-gesture/react': 10.2.16 + mobx-react-lite: 3.4.0 + perfect-freehand: 1.1.0 + resize-observer-polyfill: 1.5.1 + transitivePeerDependencies: + - mobx + - react-native + dev: false + /@tldraw/core/1.14.1_mobx@6.6.1: resolution: {integrity: sha512-FAiX/TD/tl5eMvTk0IHhFUSmldCe/UTTOnLL5aWQHqhicF/iTP5m3H12L6kyjN60yfssN8U9g4E/7y70TY7JxA==} peerDependencies: @@ -13810,6 +13832,22 @@ packages: hasBin: true dev: true + /mobx-react-lite/3.4.0: + resolution: {integrity: sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ==} + peerDependencies: + mobx: ^6.1.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + react-native: + optional: true + dev: false + /mobx-react-lite/3.4.0_mobx@6.6.1: resolution: {integrity: sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ==} peerDependencies: