From 8257557a002303183c3bdad159c3dd6c82d079b0 Mon Sep 17 00:00:00 2001 From: davy-c Date: Tue, 7 Sep 2021 09:20:35 +0900 Subject: [PATCH 1/9] fix new doc button --- src/cloud/components/buttons/NewDocButton.tsx | 2 +- src/cloud/interfaces/db/team.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cloud/components/buttons/NewDocButton.tsx b/src/cloud/components/buttons/NewDocButton.tsx index 5970aa6122..04002977b3 100644 --- a/src/cloud/components/buttons/NewDocButton.tsx +++ b/src/cloud/components/buttons/NewDocButton.tsx @@ -85,7 +85,7 @@ const NewDocButton = ({ team }: { team: SerializedTeam }) => { icon={mdiPencilBoxOutline} id='sidebar-newdoc-btn' label={translate(lngKeys.CreateNewDoc)} - labelClick={openDocTypeSelect} + labelClick={team.state.blocksBeta ? openDocTypeSelect : openNewDocModal} contextControls={[ { icon: mdiPencilBoxMultipleOutline, diff --git a/src/cloud/interfaces/db/team.ts b/src/cloud/interfaces/db/team.ts index 3a211382d6..405c1094b3 100644 --- a/src/cloud/interfaces/db/team.ts +++ b/src/cloud/interfaces/db/team.ts @@ -27,4 +27,5 @@ export type SerializedTeam = SerializedUnserializableTeamProps & export interface TeamOnboardingState { import?: boolean settings?: boolean + blocksBeta?: boolean } From 6c325292339d8342b212170ad5d9505d39cd8cdf Mon Sep 17 00:00:00 2001 From: davy-c Date: Tue, 7 Sep 2021 09:29:18 +0900 Subject: [PATCH 2/9] fix application error page and block tables --- src/cloud/components/Blocks/views/Table/index.tsx | 2 +- src/cloud/components/Router.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cloud/components/Blocks/views/Table/index.tsx b/src/cloud/components/Blocks/views/Table/index.tsx index 92847c3e29..4144f90551 100644 --- a/src/cloud/components/Blocks/views/Table/index.tsx +++ b/src/cloud/components/Blocks/views/Table/index.tsx @@ -498,7 +498,7 @@ const StyledTableView = styled.div` & td { min-width: 130px; min-height: 20px; - height: 1px; + height: auto; } td, diff --git a/src/cloud/components/Router.tsx b/src/cloud/components/Router.tsx index 83cf3430b4..df79781369 100644 --- a/src/cloud/components/Router.tsx +++ b/src/cloud/components/Router.tsx @@ -92,6 +92,7 @@ const V2CombinedProvider = combineProviders( interface PageInfo { Component: React.ComponentType pageProps: any + isError?: boolean } interface PageSpec { @@ -205,6 +206,7 @@ const Router = () => { } setPageInfo({ + isError: true, Component: ErrorPage, pageProps: { error, @@ -258,7 +260,7 @@ const Router = () => { - {isApplicationPagePathname(pathname) ? ( + {isApplicationPagePathname(pathname) && !pageInfo.isError ? ( From a6407b4c1fb8360b2ee6e5f93e23a35aebf6992c Mon Sep 17 00:00:00 2001 From: davy-c Date: Tue, 7 Sep 2021 12:02:09 +0900 Subject: [PATCH 3/9] sending map and api changes --- src/cloud/components/Blocks/BlockContent.tsx | 32 +++++- src/cloud/components/Blocks/BlockLayout.tsx | 1 + src/cloud/components/Blocks/BlockTree.tsx | 15 ++- .../components/Blocks/views/Container.tsx | 49 ++++++---- .../components/Blocks/views/GithubIssue.tsx | 35 ++++--- .../components/Blocks/views/Markdown.tsx | 2 +- .../components/Blocks/views/Table/index.tsx | 28 ++++++ src/cloud/components/Blocks/views/index.tsx | 7 ++ src/cloud/lib/hooks/useBlocksApi.ts | 97 +++++++++++++++++++ src/cloud/lib/hooks/useDocBlocks.ts | 42 ++++++-- src/cloud/lib/stores/blocks/index.ts | 40 +------- src/cloud/lib/utils/events.ts | 8 ++ .../molecules/Navigation/NavigationItem.tsx | 5 +- src/design/lib/hooks/useBulkApi.ts | 9 +- src/design/lib/types.ts | 1 + 15 files changed, 282 insertions(+), 89 deletions(-) create mode 100644 src/cloud/lib/hooks/useBlocksApi.ts diff --git a/src/cloud/components/Blocks/BlockContent.tsx b/src/cloud/components/Blocks/BlockContent.tsx index fdeab9a464..6712c0ada4 100644 --- a/src/cloud/components/Blocks/BlockContent.tsx +++ b/src/cloud/components/Blocks/BlockContent.tsx @@ -28,6 +28,11 @@ import { useSidebarCollapse, } from '../../lib/stores/sidebarCollapse' import { FoldingProps } from '../../../design/components/atoms/FoldingWrapper' +import { + markdownBlockEventEmitter, + tableBlockEventEmitter, +} from '../../lib/utils/events' +import { sleep } from '../../../lib/sleep' export interface Canvas extends SerializedDocWithBookmark { rootBlock: ContainerBlock @@ -43,7 +48,7 @@ interface BlockContentProps { const BlockContent = ({ doc }: BlockContentProps) => { const { currentUserIsCoreMember } = usePage() - const { state, actions } = useDocBlocks(doc.rootBlock.id) + const { state, actions, sendingMap } = useDocBlocks(doc.rootBlock.id) const { openModal, closeAllModals } = useModal() const [currentBlock, setCurrentBlock] = useState(null) const [provider] = useRealtime({ @@ -65,9 +70,28 @@ const BlockContent = ({ doc }: BlockContentProps) => { const createBlock = useCallback( async (block: BlockCreateRequestBody) => { try { - const newBlock = await actions.create(block, doc.rootBlock) + const res = await actions.create(block, doc.rootBlock, { + afterSuccess: (block) => { + setCurrentBlock(block) + }, + }) + if (!res.err) { + const block = res.data + if (block.type === 'markdown') { + await sleep(100) //rendering delay + markdownBlockEventEmitter.dispatch({ + type: 'edit', + id: block.id, + }) + } else if (block.type === 'table') { + await sleep(100) //rendering delay + tableBlockEventEmitter.dispatch({ + type: 'focus-title', + id: block.id, + }) + } + } closeAllModals() - setCurrentBlock(newBlock) } catch (error) { pushApiErrorMessage(error) } @@ -171,6 +195,7 @@ const BlockContent = ({ doc }: BlockContentProps) => { onDelete={actions.remove} idPrefix='nav' showFoldEvents={true} + sendingMap={sendingMap} /> ))} @@ -264,6 +289,7 @@ const BlockContent = ({ doc }: BlockContentProps) => { setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} />
diff --git a/src/cloud/components/Blocks/BlockLayout.tsx b/src/cloud/components/Blocks/BlockLayout.tsx index 89e7dd336d..e9190a0764 100644 --- a/src/cloud/components/Blocks/BlockLayout.tsx +++ b/src/cloud/components/Blocks/BlockLayout.tsx @@ -76,6 +76,7 @@ function hexToRgb(hex: string) { const BlockLayoutContainer = styled.div` width: 100%; position: relative; + z-index: 0; transition: all 0.3s ease-in-out; background: ${({ theme }) => theme.colors.background.primary}; padding: ${({ theme }) => theme.sizes.spaces.md}px diff --git a/src/cloud/components/Blocks/BlockTree.tsx b/src/cloud/components/Blocks/BlockTree.tsx index 2a47676b52..fcdbccacc4 100644 --- a/src/cloud/components/Blocks/BlockTree.tsx +++ b/src/cloud/components/Blocks/BlockTree.tsx @@ -8,16 +8,18 @@ import { min } from 'ramda' import cc from 'classcat' import { FoldingProps } from '../../../design/components/atoms/FoldingWrapper' import { blockTitle } from '../../lib/utils/blocks' +import { BlockActionRemove } from '../../lib/hooks/useDocBlocks' interface BlockTreeProps { idPrefix?: string root: Block & { folding?: FoldingProps; folded?: boolean } onSelect: (block: Block) => void - onDelete?: (block: Block) => void + onDelete?: BlockActionRemove active?: Block depth?: number className?: string showFoldEvents?: boolean + sendingMap: Map } const BlockTree = ({ @@ -29,6 +31,7 @@ const BlockTree = ({ active, className, showFoldEvents, + sendingMap, }: BlockTreeProps) => { const parentDepth = min(depth || 1, 6) return ( @@ -53,7 +56,14 @@ const BlockTree = ({ controls={ onDelete == null || depth === 0 ? [] - : [{ icon: mdiTrashCan, onClick: () => onDelete(root) }] + : [ + { + icon: mdiTrashCan, + onClick: () => onDelete(root), + disabled: sendingMap.has(root.id), + spinning: sendingMap.get(root.id) === 'delete-block', + }, + ] } /> {(!showFoldEvents || !root.folded) && @@ -68,6 +78,7 @@ const BlockTree = ({ active={active} depth={parentDepth + 1} showFoldEvents={showFoldEvents} + sendingMap={sendingMap} /> ))} diff --git a/src/cloud/components/Blocks/views/Container.tsx b/src/cloud/components/Blocks/views/Container.tsx index 39e724a54d..d9c837bbf3 100644 --- a/src/cloud/components/Blocks/views/Container.tsx +++ b/src/cloud/components/Blocks/views/Container.tsx @@ -13,8 +13,11 @@ import { useModal } from '../../../../design/lib/stores/modal' import BlockCreationModal from '../BlockCreationModal' import BlockToolbar from '../BlockToolbar' import BlockLayout from '../BlockLayout' -import { getTableBlockInputId } from './Table' -import { markdownBlockEventEmitter } from '../../../lib/utils/events' +import { + markdownBlockEventEmitter, + tableBlockEventEmitter, +} from '../../../lib/utils/events' +import { sleep } from '../../../../lib/sleep' interface ContainerViewProps extends ViewProps { setCurrentBlock: React.Dispatch> @@ -28,42 +31,51 @@ const ContainerView = ({ isChild, realtime, currentUserIsCoreMember, + sendingMap, scrollToElement, setCurrentBlock, }: ContainerViewProps) => { const { openModal, closeAllModals } = useModal() - const createBlock = useCallback( - async (newBlock: BlockCreateRequestBody) => { - const createdBlock = await actions.create(newBlock, block) - closeAllModals() - - if (canvas.rootBlock.id === block.id) { - setCurrentBlock(createdBlock) - return - } + const domBlockCreationHandler = useCallback( + async (createdBlock: Block) => { + await sleep(100) //rendering delay const blockElem = document.getElementById(getBlockDomId(createdBlock)) scrollToElement(blockElem) - if (createdBlock.type === 'table') { - const titleElement = document.getElementById( - getTableBlockInputId(createdBlock) - ) - if (titleElement != null) titleElement.focus() - } else if (newBlock.type === 'markdown') { + tableBlockEventEmitter.dispatch({ + type: 'focus-title', + id: createdBlock.id, + }) + } else if (createdBlock.type === 'markdown') { markdownBlockEventEmitter.dispatch({ type: 'edit', id: createdBlock.id, }) } }, + [scrollToElement] + ) + + const createBlock = useCallback( + async (newBlock: BlockCreateRequestBody) => { + await actions.create(newBlock, block, { + afterSuccess: (createdBlock) => { + if (canvas.rootBlock.id === block.id) { + setCurrentBlock(createdBlock) + } + domBlockCreationHandler(createdBlock) + }, + }) + closeAllModals() + }, [ block, actions, closeAllModals, - scrollToElement, canvas.rootBlock.id, setCurrentBlock, + domBlockCreationHandler, ] ) @@ -135,6 +147,7 @@ const ContainerView = ({ scrollToElement={scrollToElement} setCurrentBlock={setCurrentBlock} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) })} diff --git a/src/cloud/components/Blocks/views/GithubIssue.tsx b/src/cloud/components/Blocks/views/GithubIssue.tsx index 69324a3caf..18613c6e9b 100644 --- a/src/cloud/components/Blocks/views/GithubIssue.tsx +++ b/src/cloud/components/Blocks/views/GithubIssue.tsx @@ -40,6 +40,7 @@ const GithubIssueView = ({ actions: blockActions, canvas, currentUserIsCoreMember, + sendingMap, scrollToElement, setCurrentBlock, }: ViewProps) => { @@ -114,22 +115,25 @@ const GithubIssueView = ({ const createBlock = useCallback( async (newBlock: BlockCreateRequestBody) => { - const createdBlock = await blockActions.create(newBlock, block) - closeAllModals() - const blockElem = document.getElementById(getBlockDomId(createdBlock)) - scrollToElement(blockElem) + await blockActions.create(newBlock, block, { + afterSuccess: (createdBlock) => { + const blockElem = document.getElementById(getBlockDomId(createdBlock)) + scrollToElement(blockElem) - if (createdBlock.type === 'table') { - const titleElement = document.getElementById( - getTableBlockInputId(createdBlock) - ) - if (titleElement != null) titleElement.focus() - } else if (newBlock.type === 'markdown') { - markdownBlockEventEmitter.dispatch({ - type: 'edit', - id: createdBlock.id, - }) - } + if (createdBlock.type === 'table') { + const titleElement = document.getElementById( + getTableBlockInputId(createdBlock) + ) + if (titleElement != null) titleElement.focus() + } else if (newBlock.type === 'markdown') { + markdownBlockEventEmitter.dispatch({ + type: 'edit', + id: createdBlock.id, + }) + } + }, + }) + closeAllModals() }, [blockActions, block, closeAllModals, scrollToElement] ) @@ -233,6 +237,7 @@ const GithubIssueView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) })} diff --git a/src/cloud/components/Blocks/views/Markdown.tsx b/src/cloud/components/Blocks/views/Markdown.tsx index c6807590f3..32990f856d 100644 --- a/src/cloud/components/Blocks/views/Markdown.tsx +++ b/src/cloud/components/Blocks/views/Markdown.tsx @@ -96,6 +96,7 @@ const MarkdownView = ({ if (detail.id !== block.id) { return } + console.log('got event') switch (detail.type) { case 'edit': @@ -135,7 +136,6 @@ const MarkdownView = ({ : `block__markdown--mode-${mode}`, ])} id={getBlockDomId(block)} - onEv onFocus={() => setMode('editor')} > {!synced ? ( diff --git a/src/cloud/components/Blocks/views/Table/index.tsx b/src/cloud/components/Blocks/views/Table/index.tsx index 4144f90551..cc51c72ccb 100644 --- a/src/cloud/components/Blocks/views/Table/index.tsx +++ b/src/cloud/components/Blocks/views/Table/index.tsx @@ -38,6 +38,10 @@ import { useDebounce } from 'react-use' import { blockTitle } from '../../../../lib/utils/blocks' import BlockIcon from '../../BlockIcon' import NavigationItem from '../../../../../design/components/molecules/Navigation/NavigationItem' +import { + TableBlockEventDetails, + tableBlockEventEmitter, +} from '../../../../lib/utils/events' type GithubCellProps = BlockDataProps interface TableViewProps extends ViewProps { @@ -49,12 +53,14 @@ const TableView = ({ actions, realtime, currentUserIsCoreMember, + sendingMap, setCurrentBlock, }: TableViewProps) => { const { openModal, openContextModal, closeAllModals } = useModal() const { state, actions: tableActions } = useBlockTable(block, realtime.doc) const [tableTitle, setTableTitle] = useState(block.name || '') const tableRef = useRef(block.id) + const titleInputRef = useRef(null) const subscriptionsRef = useRef void>>(new Set()) useEffect(() => { @@ -177,6 +183,24 @@ const TableView = ({ } }, [block]) + useEffect(() => { + const handler = ({ detail }: CustomEvent) => { + if (detail.id !== block.id) { + return + } + + switch (detail.type) { + case 'focus-title': + titleInputRef.current?.focus() + return + default: + return + } + } + tableBlockEventEmitter.listen(handler) + return () => tableBlockEventEmitter.unlisten(handler) + }, [block]) + const anchorId = `block__${block.id}__table` return (
@@ -249,6 +274,9 @@ const TableView = ({ { icon: mdiTrashCan, onClick: () => actions.remove(child), + disabled: sendingMap.has(child.id), + spinning: + sendingMap.get(child.id) === 'delete-block', }, ]} className='table__title__tree' diff --git a/src/cloud/components/Blocks/views/index.tsx b/src/cloud/components/Blocks/views/index.tsx index 2a93817543..cf89ea24c4 100644 --- a/src/cloud/components/Blocks/views/index.tsx +++ b/src/cloud/components/Blocks/views/index.tsx @@ -19,6 +19,7 @@ export interface ViewProps { setCurrentBlock: React.Dispatch> scrollToElement: (elem: HTMLElement | null) => void currentUserIsCoreMember: boolean + sendingMap: Map } export const BlockView = ({ isRootBlock, @@ -28,6 +29,7 @@ export const BlockView = ({ realtime, isChild, currentUserIsCoreMember, + sendingMap, scrollToElement, setCurrentBlock, }: ViewProps) => { @@ -44,6 +46,7 @@ export const BlockView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) case 'embed': @@ -57,6 +60,7 @@ export const BlockView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) case 'markdown': @@ -70,6 +74,7 @@ export const BlockView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) case 'table': @@ -83,6 +88,7 @@ export const BlockView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) case 'github.issue': @@ -96,6 +102,7 @@ export const BlockView = ({ setCurrentBlock={setCurrentBlock} scrollToElement={scrollToElement} currentUserIsCoreMember={currentUserIsCoreMember} + sendingMap={sendingMap} /> ) default: diff --git a/src/cloud/lib/hooks/useBlocksApi.ts b/src/cloud/lib/hooks/useBlocksApi.ts new file mode 100644 index 0000000000..3cf687207d --- /dev/null +++ b/src/cloud/lib/hooks/useBlocksApi.ts @@ -0,0 +1,97 @@ +import { useCallback } from 'react' +import shortid from 'shortid' +import useBulkApi from '../../../design/lib/hooks/useBulkApi' +import { + Block, + BlockCreateRequestBody, + BlockUpdateRequestBody, + createBlock, + deleteBlock, + updateBlock, +} from '../../api/blocks' +import { useBlocks } from '../stores/blocks' + +export interface CreateBlockApiOptions { + afterSuccess?: (block: Block) => void +} +export interface UpdateBlockApiOptions { + afterSuccess?: (block: Block) => void +} + +export interface DeleteBlockApiOptions { + afterSuccess?: () => void +} + +export function useBlocksApi() { + const { sendingMap, send } = useBulkApi() + const { getBlocks } = useBlocks() + + const createBlockApi = useCallback( + async ( + body: BlockCreateRequestBody, + parent: Block, + options: CreateBlockApiOptions, + root: string + ) => { + return send(shortid.generate(), 'create-block', { + api: () => createBlock(body, parent.id), + cb: async (block: Block) => { + await getBlocks(root) + if (options.afterSuccess != null) { + options.afterSuccess(block) + } + }, + }) + }, + [getBlocks, send] + ) + + const deleteBlockApi = useCallback( + async ( + block: Block, + options: { + afterSuccess?: () => void + }, + root: string + ) => { + return send(block.id, 'delete-block', { + api: () => deleteBlock(block.id), + cb: async () => { + await getBlocks(root) + if (options.afterSuccess != null) { + options.afterSuccess() + } + }, + }) + }, + [getBlocks, send] + ) + + const updateBlockApi = useCallback( + async ( + block: BlockUpdateRequestBody, + options: UpdateBlockApiOptions, + root: string + ) => { + const res = await send(block.id, 'update-block', { + api: () => updateBlock(block), + cb: async (block: Block) => { + await getBlocks(root) + if (options.afterSuccess != null) { + options.afterSuccess(block) + } + }, + }) + return res + }, + [getBlocks, send] + ) + + return { + send, + sendingMap, + createBlock: createBlockApi, + deleteBlock: deleteBlockApi, + updateBlock: updateBlockApi, + } +} diff --git a/src/cloud/lib/hooks/useDocBlocks.ts b/src/cloud/lib/hooks/useDocBlocks.ts index e6723b0adc..26ddd5274d 100644 --- a/src/cloud/lib/hooks/useDocBlocks.ts +++ b/src/cloud/lib/hooks/useDocBlocks.ts @@ -5,17 +5,41 @@ import { BlockCreateRequestBody, BlockUpdateRequestBody, } from '../../api/blocks' +import { + CreateBlockApiOptions, + DeleteBlockApiOptions, + UpdateBlockApiOptions, + useBlocksApi, +} from './useBlocksApi' +import { BulkApiActionRes } from '../../../design/lib/hooks/useBulkApi' type BlockState = { type: 'loading' } | { type: 'loaded'; block: Block } +export type BlockActionCreate = ( + block: BlockCreateRequestBody, + parent: Block, + options?: CreateBlockApiOptions +) => Promise + +export type BlockActionUpdate = ( + block: BlockUpdateRequestBody, + options?: UpdateBlockApiOptions +) => Promise + +export type BlockActionRemove = ( + block: Block, + options?: DeleteBlockApiOptions +) => Promise + export interface BlockActions { - create: (block: BlockCreateRequestBody, parent: Block) => Promise - update: (block: BlockUpdateRequestBody) => Promise - remove: (block: Block) => Promise + create: BlockActionCreate + update: BlockActionUpdate + remove: BlockActionRemove } export function useDocBlocks(id: string) { - const { observeDocBlocks, create, update, remove } = useBlocks() + const { observeDocBlocks } = useBlocks() + const { createBlock, updateBlock, deleteBlock, sendingMap } = useBlocksApi() const [state, setState] = useState({ type: 'loading' }) useEffect(() => { @@ -30,14 +54,16 @@ export function useDocBlocks(id: string) { const actions: BlockActions = useMemo(() => { return { - create: (block, parent) => create(block, parent, id), - update: (block) => update(block, id), - remove: (block) => remove(block, id), + create: (block, parent, options) => + createBlock(block, parent, options || {}, id), + update: (block, options) => updateBlock(block, options || {}, id), + remove: (block, options) => deleteBlock(block, options || {}, id), } - }, [id, create, update, remove]) + }, [id, createBlock, updateBlock, deleteBlock]) return { state, actions, + sendingMap, } } diff --git a/src/cloud/lib/stores/blocks/index.ts b/src/cloud/lib/stores/blocks/index.ts index 4e15e619e8..3cf5bad8fd 100644 --- a/src/cloud/lib/stores/blocks/index.ts +++ b/src/cloud/lib/stores/blocks/index.ts @@ -1,14 +1,6 @@ import { createStoreContext } from '../../utils/context' import { useRef, useCallback } from 'react' -import { - Block, - getBlockTree, - deleteBlock, - updateBlock, - createBlock, - BlockUpdateRequestBody, - BlockCreateRequestBody, -} from '../../../api/blocks' +import { Block, getBlockTree } from '../../../api/blocks' import { useToast } from '../../../../design/lib/stores/toast' type BlocksObserver = (blocks: Block) => void @@ -54,37 +46,9 @@ function useBlocksStore() { [getBlocks] ) - const create = useCallback( - async (body: BlockCreateRequestBody, parent: Block, root: string) => { - const block = await createBlock(body, parent.id) - await getBlocks(root) - return block - }, - [getBlocks] - ) - - const remove = useCallback( - async (block: Block, root: string) => { - await deleteBlock(block.id) - await getBlocks(root) - }, - [getBlocks] - ) - - const update = useCallback( - async (block: BlockUpdateRequestBody, root: string) => { - const updated = await updateBlock(block) - await getBlocks(root) - return updated - }, - [getBlocks] - ) - return { observeDocBlocks, - create, - remove, - update, + getBlocks, } } diff --git a/src/cloud/lib/utils/events.ts b/src/cloud/lib/utils/events.ts index d7f261e102..dbbc4170ab 100644 --- a/src/cloud/lib/utils/events.ts +++ b/src/cloud/lib/utils/events.ts @@ -88,3 +88,11 @@ export type MarkdownBlockEventDetails = { export const markdownBlockEventEmitter = createCustomEventEmitter< MarkdownBlockEventDetails >('blocks-markdown') + +export type TableBlockEventDetails = { + type: string + id: string +} +export const tableBlockEventEmitter = createCustomEventEmitter< + TableBlockEventDetails +>('blocks-table') diff --git a/src/design/components/molecules/Navigation/NavigationItem.tsx b/src/design/components/molecules/Navigation/NavigationItem.tsx index 1c8e7b7a30..d965e5d19a 100644 --- a/src/design/components/molecules/Navigation/NavigationItem.tsx +++ b/src/design/components/molecules/Navigation/NavigationItem.tsx @@ -3,7 +3,7 @@ import styled from '../../../lib/styled' import { AppComponent, ControlButtonProps } from '../../../lib/types' import cc from 'classcat' import FoldingWrapper, { FoldingProps } from '../../atoms/FoldingWrapper' -import Button from '../../atoms/Button' +import Button, { LoadingButton } from '../../atoms/Button' import { mdiChevronDown, mdiChevronRight } from '@mdi/js' import { Emoji } from 'emoji-mart' import Icon from '../../atoms/Icon' @@ -135,7 +135,8 @@ const NavItem: AppComponent< {controls != null && controls.length > 0 && (
{(controls || []).map((control, i) => ( -