Merge branch 'master' into develop

This commit is contained in:
DarkSky
2022-08-07 22:33:30 +08:00
committed by GitHub
21 changed files with 230 additions and 219 deletions

View File

@@ -3,8 +3,8 @@ name: Build AFFiNE-Local
on: on:
push: push:
branches: [master] branches: [master]
pull_request: # pull_request:
branches: [master] # branches: [master]
# Cancels all previous workflow runs for pull requests that have not completed. # Cancels all previous workflow runs for pull requests that have not completed.
# See https://docs.github.com/en/actions/using-jobs/using-concurrency # See https://docs.github.com/en/actions/using-jobs/using-concurrency

28
.github/workflows/check.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: standard check
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
main:
name: Nx Cloud - Main Job
uses: nrwl/ci/.github/workflows/nx-cloud-main.yml@v0.6
secrets: inherit
with:
main-branch-name: master
number-of-agents: 3
parallel-commands: |
pnpm exec nx-cloud record -- pnpm exec nx format:check
parallel-commands-on-agents: |
pnpm exec nx affected --target=lint --parallel=3 --exclude=components-common,keck,theme
pnpm exec nx affected --target=build --parallel=3
agents:
name: Nx Cloud - Agents
uses: nrwl/ci/.github/workflows/nx-cloud-agents.yml@v0.6
secrets: inherit
with:
number-of-agents: 3

View File

@@ -8,12 +8,12 @@ on:
- 'apps/keck/**' - 'apps/keck/**'
- '.github/deployment' - '.github/deployment'
- '.github/workflows/keck.yml' - '.github/workflows/keck.yml'
pull_request: # pull_request:
branches: [master] # branches: [master]
paths: # paths:
- 'apps/keck/**' # - 'apps/keck/**'
- '.github/deployment' # - '.github/deployment'
- '.github/workflows/keck.yml' # - '.github/workflows/keck.yml'
# Cancels all previous workflow runs for pull requests that have not completed. # Cancels all previous workflow runs for pull requests that have not completed.
# See https://docs.github.com/en/actions/using-jobs/using-concurrency # See https://docs.github.com/en/actions/using-jobs/using-concurrency

View File

@@ -3,8 +3,8 @@ name: Lint
on: on:
push: push:
branches: [master] branches: [master]
pull_request: # pull_request:
branches: [master] # branches: [master]
# Cancels all previous workflow runs for pull requests that have not completed. # Cancels all previous workflow runs for pull requests that have not completed.
# See https://docs.github.com/en/actions/using-jobs/using-concurrency # See https://docs.github.com/en/actions/using-jobs/using-concurrency

View File

@@ -3,8 +3,8 @@ name: Build Lisa
on: on:
push: push:
branches: [master] branches: [master]
pull_request: # pull_request:
branches: [master] # branches: [master]
# Cancels all previous workflow runs for pull requests that have not completed. # Cancels all previous workflow runs for pull requests that have not completed.
# See https://docs.github.com/en/actions/using-jobs/using-concurrency # See https://docs.github.com/en/actions/using-jobs/using-concurrency

View File

@@ -7,11 +7,11 @@ on:
- 'apps/venus/**' - 'apps/venus/**'
- '.github/deployment' - '.github/deployment'
- '.github/workflows/venus.yml' - '.github/workflows/venus.yml'
pull_request: # pull_request:
branches: [master] # branches: [master]
paths: # paths:
- 'apps/venus/**' # - 'apps/venus/**'
- '.github/workflows/venus.yml' # - '.github/workflows/venus.yml'
# Cancels all previous workflow runs for pull requests that have not completed. # Cancels all previous workflow runs for pull requests that have not completed.
# See https://docs.github.com/en/actions/using-jobs/using-concurrency # See https://docs.github.com/en/actions/using-jobs/using-concurrency

View File

@@ -34,34 +34,31 @@ const _checkAuth = async (
response: http.ServerResponse, response: http.ServerResponse,
callback: (response: http.OutgoingMessage, workspace: string) => boolean callback: (response: http.OutgoingMessage, workspace: string) => boolean
) => { ) => {
const url = new URL(request.url, `http://${request.headers.host}`);
const workspace = _getWorkspace(url.pathname);
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
const url = new URL(request.url, `http://${request.headers.host}`);
const workspace = _getWorkspace(url.pathname);
if (workspace) return callback(response, workspace); if (workspace) return callback(response, workspace);
return false; return false;
} else {
try {
const decodedToken = await firebaseAuth
.getAuth()
.verifyIdToken(request.headers.token as string);
const allowWorkspace = [AFFINE_COMMON_WORKSPACE, decodedToken.uid];
const url = new URL(request.url, `http://${request.headers.host}`);
const workspace = _getWorkspace(url.pathname);
if (allowWorkspace.includes(workspace)) {
return callback(response, workspace);
}
} catch (error) {
console.log(error);
}
return false;
} }
try {
const decodedToken = await firebaseAuth
.getAuth()
.verifyIdToken(request.headers.token as string);
const allowWorkspace = [AFFINE_COMMON_WORKSPACE, decodedToken.uid];
if (allowWorkspace.includes(workspace)) {
return callback(response, workspace);
}
} catch (error) {
console.log(error);
}
return false;
}; };
const HOST = process.env.HOST || 'localhost'; const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
const _tokens = new LRUCache<string, string>({ const _tokens = new LRUCache<string, string>({
max: 10240, max: 1024 * 10,
ttl: 1000 * 60 * 5, ttl: 1000 * 60 * 5,
}); });

View File

@@ -10,16 +10,13 @@ export function WorkspaceHome() {
useEffect(() => { useEffect(() => {
const navigate_to_user_initial_page = async () => { const navigate_to_user_initial_page = async () => {
const recent_pages = await services.api.userConfig.getRecentPages( const [recent_pages, user_initial_page_id] = await Promise.all([
workspace_id, services.api.userConfig.getRecentPages(workspace_id, user.id),
user.id services.api.userConfig.getUserInitialPage(
);
const user_initial_page_id =
await services.api.userConfig.getUserInitialPage(
workspace_id, workspace_id,
user.id user.id
); ),
]);
if (recent_pages.length === 0) { if (recent_pages.length === 0) {
await services.api.editorBlock.copyTemplateToPage( await services.api.editorBlock.copyTemplateToPage(
workspace_id, workspace_id,

View File

@@ -93,43 +93,29 @@ const EditorContainer = ({
workspace: string; workspace: string;
}) => { }) => {
const [lockScroll, setLockScroll] = useState(false); const [lockScroll, setLockScroll] = useState(false);
const scrollContainerRef = useRef<HTMLDivElement>(); const [scrollContainer, setScrollContainer] = useState<HTMLElement>();
const editorRef = useRef<BlockEditor>(); const editorRef = useRef<BlockEditor>();
const onScroll = (event: UIEvent) => { const onScroll = (event: UIEvent) => {
editorRef.current.getHooks().onRootNodeScroll(event); editorRef.current.getHooks().onRootNodeScroll(event);
editorRef.current.scrollManager.emitScrollEvent(event); editorRef.current.scrollManager.emitScrollEvent(event);
}; };
useEffect(() => {
editorRef.current.scrollManager.scrollContainer =
scrollContainerRef.current;
editorRef.current.scrollManager.scrollController = {
lockScroll: () => setLockScroll(true),
unLockScroll: () => setLockScroll(false),
};
}, []);
const { setPageClientWidth } = usePageClientWidth(); const { setPageClientWidth } = usePageClientWidth();
useEffect(() => { useEffect(() => {
if (scrollContainerRef.current) { if (scrollContainer) {
const obv = new ResizeObserver(e => { const obv = new ResizeObserver(e => {
setPageClientWidth(e[0].contentRect.width); setPageClientWidth(e[0].contentRect.width);
}); });
obv.observe(scrollContainerRef.current); obv.observe(scrollContainer);
return () => obv.disconnect(); return () => obv.disconnect();
} }
}, [setPageClientWidth]); }, [setPageClientWidth, scrollContainer]);
return ( return (
<StyledEditorContainer <StyledEditorContainer
lockScroll={lockScroll} lockScroll={lockScroll}
ref={ref => { ref={ref => setScrollContainer(ref)}
scrollContainerRef.current = ref;
if (editorRef.current?.scrollManager) {
editorRef.current.scrollManager.scrollContainer = ref;
}
}}
onScroll={onScroll} onScroll={onScroll}
> >
{pageId ? ( {pageId ? (
@@ -137,6 +123,11 @@ const EditorContainer = ({
workspace={workspace} workspace={workspace}
rootBlockId={pageId} rootBlockId={pageId}
ref={editorRef} ref={editorRef}
scrollContainer={scrollContainer}
scrollController={{
lockScroll: () => setLockScroll(true),
unLockScroll: () => setLockScroll(false),
}}
/> />
) : ( ) : (
<Box <Box

View File

@@ -9,8 +9,8 @@ export const Logo = ({ color, style, ...props }) => {
> >
<rect width="52" height="52" rx="10" fill="#3E6FDB" /> <rect width="52" height="52" rx="10" fill="#3E6FDB" />
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="evenodd"
d="M24.2189 11.4392L14.6321 38.7943H20.2472L26.3453 19.8747L32.4461 38.7943H38.0423L28.454 11.4392H24.2189Z" d="M24.2189 11.4392L14.6321 38.7943H20.2472L26.3453 19.8747L32.4461 38.7943H38.0423L28.454 11.4392H24.2189Z"
fill="white" fill="white"
/> />

View File

@@ -11,15 +11,15 @@ const StyledTabs = styled('div')({
cursor: 'pointer', cursor: 'pointer',
}); });
const StyledDivider = styled(Divider)<{ isActive?: boolean }>( const StyledDivider = styled(Divider, {
({ isActive }) => { shouldForwardProp: (prop: string) => !['isActive'].includes(prop),
return { })<{ isActive?: boolean }>(({ isActive }) => {
flex: 1, return {
backgroundColor: isActive ? '#3E6FDB' : '#ECF1FB', flex: 1,
borderWidth: '2px', backgroundColor: isActive ? '#3E6FDB' : '#ECF1FB',
}; borderWidth: '2px',
} };
); });
const TAB_TITLE = { const TAB_TITLE = {
PAGES: 'pages', PAGES: 'pages',

View File

@@ -95,15 +95,11 @@ export const WorkspaceName = () => {
if (!currentSpaceId) { if (!currentSpaceId) {
return; return;
} }
const [name, workspaceId] = await Promise.all([
const name = await services.api.userConfig.getWorkspaceName( services.api.userConfig.getWorkspaceName(currentSpaceId),
currentSpaceId services.api.userConfig.getWorkspaceId(currentSpaceId),
); ]);
setWorkspaceName(name); setWorkspaceName(name);
const workspaceId = await services.api.userConfig.getWorkspaceId(
currentSpaceId
);
setWorkspaceId(workspaceId); setWorkspaceId(workspaceId);
}, [currentSpaceId]); }, [currentSpaceId]);

View File

@@ -34,11 +34,6 @@ module.exports = function (webpackConfig) {
if (isProd) { if (isProd) {
config.module.rules.unshift(style9); config.module.rules.unshift(style9);
} else {
config.module.rules.push(style9);
}
if (isProd) {
config.entry = { config.entry = {
main: [...config.entry.main, ...config.entry.polyfills], main: [...config.entry.main, ...config.entry.polyfills],
}; };
@@ -133,6 +128,7 @@ module.exports = function (webpackConfig) {
}); });
config.module.rules.splice(6); config.module.rules.splice(6);
} else { } else {
config.module.rules.push(style9);
config.output = { config.output = {
...config.output, ...config.output,
publicPath: '/', publicPath: '/',

View File

@@ -35,11 +35,6 @@ module.exports = function (webpackConfig) {
if (isProd) { if (isProd) {
config.module.rules.unshift(style9); config.module.rules.unshift(style9);
} else {
config.module.rules.push(style9);
}
if (isProd) {
config.entry = { config.entry = {
main: [...config.entry.main, ...config.entry.polyfills], main: [...config.entry.main, ...config.entry.polyfills],
}; };
@@ -124,6 +119,7 @@ module.exports = function (webpackConfig) {
}); });
config.module.rules.splice(6); config.module.rules.splice(6);
} else { } else {
config.module.rules.push(style9);
config.output = { config.output = {
...config.output, ...config.output,
publicPath: '/', publicPath: '/',

View File

@@ -18,6 +18,12 @@ interface AffineEditorProps {
scrollBlank?: boolean; scrollBlank?: boolean;
isWhiteboard?: boolean; isWhiteboard?: boolean;
scrollContainer?: HTMLElement;
scrollController?: {
lockScroll: () => void;
unLockScroll: () => void;
};
} }
function _useConstantWithDispose( function _useConstantWithDispose(
@@ -53,13 +59,32 @@ function _useConstantWithDispose(
} }
export const AffineEditor = forwardRef<BlockEditor, AffineEditorProps>( export const AffineEditor = forwardRef<BlockEditor, AffineEditorProps>(
({ workspace, rootBlockId, scrollBlank = true, isWhiteboard }, ref) => { (
{
workspace,
rootBlockId,
scrollBlank = true,
isWhiteboard,
scrollController,
scrollContainer,
},
ref
) => {
const editor = _useConstantWithDispose( const editor = _useConstantWithDispose(
workspace, workspace,
rootBlockId, rootBlockId,
isWhiteboard isWhiteboard
); );
useEffect(() => {
if (scrollContainer) {
editor.scrollManager.scrollContainer = scrollContainer;
}
if (scrollController) {
editor.scrollManager.scrollController = scrollController;
}
}, [editor, scrollContainer, scrollController]);
useImperativeHandle(ref, () => editor); useImperativeHandle(ref, () => editor);
return ( return (

View File

@@ -31,6 +31,7 @@
"@mui/system": "^5.8.6", "@mui/system": "^5.8.6",
"code-example": "^3.3.6", "code-example": "^3.3.6",
"codemirror": "6.0.1", "codemirror": "6.0.1",
"codemirror-lang-elixir": "^3.0.0",
"keymap": "link:@codemirror/next/keymap", "keymap": "link:@codemirror/next/keymap",
"nanoid": "^4.0.0", "nanoid": "^4.0.0",
"react-resizable": "^3.0.4", "react-resizable": "^3.0.4",

View File

@@ -1,10 +1,9 @@
import { FC, useState, useMemo, useRef, useEffect } from 'react'; import { FC, useState, useRef, useEffect } from 'react';
import { StyleWithAtRules } from 'style9'; import { StyleWithAtRules } from 'style9';
import { CreateView } from '@toeverything/framework/virgo'; import { CreateView } from '@toeverything/framework/virgo';
import CodeMirror from './CodeMirror'; import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror';
import { styled } from '@toeverything/components/ui'; import { styled } from '@toeverything/components/ui';
import DeleteSweepOutlinedIcon from '@mui/icons-material/DeleteSweepOutlined';
import { javascript } from '@codemirror/lang-javascript'; import { javascript } from '@codemirror/lang-javascript';
import { html } from '@codemirror/lang-html'; import { html } from '@codemirror/lang-html';
@@ -32,6 +31,7 @@ import { powerShell } from '@codemirror/legacy-modes/mode/powershell';
import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck'; import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck';
import { stylus } from '@codemirror/legacy-modes/mode/stylus'; import { stylus } from '@codemirror/legacy-modes/mode/stylus';
import { erlang } from '@codemirror/legacy-modes/mode/erlang'; import { erlang } from '@codemirror/legacy-modes/mode/erlang';
import { elixir } from 'codemirror-lang-elixir';
import { nginx } from '@codemirror/legacy-modes/mode/nginx'; import { nginx } from '@codemirror/legacy-modes/mode/nginx';
import { perl } from '@codemirror/legacy-modes/mode/perl'; import { perl } from '@codemirror/legacy-modes/mode/perl';
import { pascal } from '@codemirror/legacy-modes/mode/pascal'; import { pascal } from '@codemirror/legacy-modes/mode/pascal';
@@ -45,7 +45,6 @@ import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile';
import { julia } from '@codemirror/legacy-modes/mode/julia'; import { julia } from '@codemirror/legacy-modes/mode/julia';
import { r } from '@codemirror/legacy-modes/mode/r'; import { r } from '@codemirror/legacy-modes/mode/r';
import { Extension } from '@codemirror/state'; import { Extension } from '@codemirror/state';
// import { Select } from '../../components/select';
import { Option, Select } from '@toeverything/components/ui'; import { Option, Select } from '@toeverything/components/ui';
import { import {
@@ -87,6 +86,7 @@ const langs: Record<string, any> = {
brainfuck: () => StreamLanguage.define(brainfuck), brainfuck: () => StreamLanguage.define(brainfuck),
stylus: () => StreamLanguage.define(stylus), stylus: () => StreamLanguage.define(stylus),
erlang: () => StreamLanguage.define(erlang), erlang: () => StreamLanguage.define(erlang),
elixir: () => StreamLanguage.define(elixir),
nginx: () => StreamLanguage.define(nginx), nginx: () => StreamLanguage.define(nginx),
perl: () => StreamLanguage.define(perl), perl: () => StreamLanguage.define(perl),
ruby: () => StreamLanguage.define(ruby), ruby: () => StreamLanguage.define(ruby),
@@ -100,10 +100,8 @@ const langs: Record<string, any> = {
julia: () => StreamLanguage.define(julia), julia: () => StreamLanguage.define(julia),
dockerfile: () => StreamLanguage.define(dockerFile), dockerfile: () => StreamLanguage.define(dockerFile),
r: () => StreamLanguage.define(r), r: () => StreamLanguage.define(r),
// clike: () => StreamLanguage.define(clike),
// clike: () => clike({ }),
}; };
const DEFAULT_LANG = 'javascript';
const CodeBlock = styled('div')(({ theme }) => ({ const CodeBlock = styled('div')(({ theme }) => ({
backgroundColor: '#F2F5F9', backgroundColor: '#F2F5F9',
padding: '8px 24px', padding: '8px 24px',
@@ -118,7 +116,7 @@ const CodeBlock = styled('div')(({ theme }) => ({
flexWrap: 'wrap', flexWrap: 'wrap',
justifyContent: 'space-between', justifyContent: 'space-between',
}, },
'.delete-block': { '.copy-block': {
padding: '6px 10px', padding: '6px 10px',
backgroundColor: '#fff', backgroundColor: '#fff',
borderRadius: theme.affine.shape.borderRadius, borderRadius: theme.affine.shape.borderRadius,
@@ -130,29 +128,27 @@ const CodeBlock = styled('div')(({ theme }) => ({
})); }));
export const CodeView: FC<CreateCodeView> = ({ block, editor }) => { export const CodeView: FC<CreateCodeView> = ({ block, editor }) => {
const initValue: string = block.getProperty('text')?.value?.[0]?.text; const initValue: string = block.getProperty('text')?.value?.[0]?.text;
const langType: string = block.getProperty('lang')?.value?.[0]?.text; const langType: string = block.getProperty('lang');
const [mode, setMode] = useState('javascript');
const [extensions, setExtensions] = useState<Extension[]>(); const [extensions, setExtensions] = useState<Extension[]>();
const codeMirror = useRef(); const codeMirror = useRef<ReactCodeMirrorRef>();
useOnSelect(block.id, (is_select: boolean) => { useOnSelect(block.id, (_is_select: boolean) => {
if (codeMirror.current) { if (codeMirror.current) {
//@ts-ignore
codeMirror?.current?.view?.focus(); codeMirror?.current?.view?.focus();
} }
}); });
const onChange = (value: any, codeEditor: any) => { const onChange = (value: string) => {
block.setProperty('text', { block.setProperty('text', {
value: [{ text: value }], value: [{ text: value }],
}); });
}; };
useEffect(() => { const handleLangChange = (lang: string) => {
handleLangChange(langType ? langType : 'javascript');
}, []);
function handleLangChange(lang: string) {
block.setProperty('lang', lang); block.setProperty('lang', lang);
setMode(lang);
setExtensions([langs[lang]()]); setExtensions([langs[lang]()]);
} };
useEffect(() => {
handleLangChange(langType ? langType : DEFAULT_LANG);
}, []);
const copyCode = () => { const copyCode = () => {
copyToClipboard(initValue); copyToClipboard(initValue);
}; };
@@ -171,19 +167,12 @@ export const CodeView: FC<CreateCodeView> = ({ block, editor }) => {
> >
<div className="operation"> <div className="operation">
<div className="select"> <div className="select">
{/* <Select
label="Lang"
options={Object.keys(langs)}
value={mode}
onChange={evn => handleLangChange(evn.target.value)}
/> */}
<Select <Select
width={128} width={128}
placeholder="Search for a field type" placeholder="Search for a field type"
value={mode} value={langType || DEFAULT_LANG}
listboxStyle={{ maxHeight: '400px' }} listboxStyle={{ maxHeight: '400px' }}
onChange={(selectedValue: string) => { onChange={(selectedValue: string) => {
// setSelectedOption(selectedValue);
handleLangChange(selectedValue); handleLangChange(selectedValue);
}} }}
> >
@@ -197,17 +186,8 @@ export const CodeView: FC<CreateCodeView> = ({ block, editor }) => {
</Select> </Select>
</div> </div>
<div> <div>
<div className="delete-block" onClick={copyCode}> <div className="copy-block" onClick={copyCode}>
Copy Copy
{/* <DeleteSweepOutlinedIcon
className="delete-icon"
fontSize="small"
sx={{
color: 'rgba(0,0,0,.5)',
cursor: 'pointer',
'&:hover': { color: 'rgba(0,0,0,.9)' },
}}
/> */}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,6 @@
import { MuiBackdrop, styled, useTheme } from '@toeverything/components/ui'; import { MuiBackdrop, styled, useTheme } from '@toeverything/components/ui';
import { createContext, ReactNode, useContext, useState } from 'react'; import { createContext, ReactNode, useContext, useState } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { useEditor } from '../Contexts';
import { RenderBlock } from '../render-block'; import { RenderBlock } from '../render-block';
const Dialog = styled('div')({ const Dialog = styled('div')({
@@ -44,8 +43,6 @@ const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => {
}; };
const ModalPage = ({ blockId }: { blockId: string | null }) => { const ModalPage = ({ blockId }: { blockId: string | null }) => {
const { editor } = useEditor();
return ( return (
<Modal open={!!blockId}> <Modal open={!!blockId}>
{blockId && <RenderBlock blockId={blockId} />} {blockId && <RenderBlock blockId={blockId} />}

View File

@@ -116,7 +116,7 @@ export const ReferenceMenu = ({ editor, hooks, style }: ReferenceMenuProps) => {
}; };
const handle_close = () => { const handle_close = () => {
editor.blockHelper.removeSearchSlash(block_id); block_id && editor.blockHelper.removeSearchSlash(block_id);
}; };
return ( return (

View File

@@ -1,5 +1,5 @@
import type { BlockClientInstance } from '@toeverything/datasource/jwt'; import type { BlockClientInstance } from '@toeverything/datasource/jwt';
import { PAGE_TREE } from '../../utils'; import { PAGE_TREE as pageTreeName } from '../../utils';
import type { ReturnUnobserve } from '../database/observer'; import type { ReturnUnobserve } from '../database/observer';
import { ServiceBaseClass } from '../base'; import { ServiceBaseClass } from '../base';
import { TreeItem } from './types'; import { TreeItem } from './types';
@@ -7,22 +7,22 @@ import { TreeItem } from './types';
export type ObserveCallback = () => void; export type ObserveCallback = () => void;
export class PageTree extends ServiceBaseClass { export class PageTree extends ServiceBaseClass {
private async fetch_page_tree<TreeItem>(workspace: string) { private async _fetchPageTree<TreeItem>(workspace: string) {
const workspace_db_block = await this.getWorkspaceDbBlock(workspace); const workspaceDbBlock = await this.getWorkspaceDbBlock(workspace);
const page_tree_config = const pageTreeConfig =
workspace_db_block.getDecoration<TreeItem[]>(PAGE_TREE); workspaceDbBlock.getDecoration<TreeItem[]>(pageTreeName);
return page_tree_config; return pageTreeConfig;
} }
async getPageTree<TreeItem>(workspace: string): Promise<TreeItem[]> { async getPageTree<TreeItem>(workspace: string): Promise<TreeItem[]> {
try { try {
const page_tree = await this.fetch_page_tree(workspace); const pageTree = await this._fetchPageTree(workspace);
if (page_tree && page_tree.length) { if (pageTree && pageTree.length) {
const db = await this.database.getDatabase(workspace); const db = await this.database.getDatabase(workspace);
const pages = await update_tree_items_title( const pages = await _updateTreeItemsTitle(
db, db,
page_tree as [], pageTree as [],
{} {}
); );
return pages; return pages;
@@ -36,8 +36,8 @@ export class PageTree extends ServiceBaseClass {
/** @deprecated should implement more fine-grained crud methods instead of replacing each time with a new array */ /** @deprecated should implement more fine-grained crud methods instead of replacing each time with a new array */
async setPageTree<TreeItem>(workspace: string, treeData: TreeItem[]) { async setPageTree<TreeItem>(workspace: string, treeData: TreeItem[]) {
const workspace_db_block = await this.getWorkspaceDbBlock(workspace); const workspaceDbBlock = await this.getWorkspaceDbBlock(workspace);
workspace_db_block.setDecoration(PAGE_TREE, treeData); workspaceDbBlock.setDecoration(pageTreeName, treeData);
} }
async addPage<TreeItem>(workspace: string, treeData: TreeItem[] | string) { async addPage<TreeItem>(workspace: string, treeData: TreeItem[] | string) {
@@ -51,110 +51,107 @@ export class PageTree extends ServiceBaseClass {
await dbBlock?.remove(); await dbBlock?.remove();
} }
async addPageToWorkspacee( async addPageToWorkspacee(targetWorkspaceId: string, newPageId: string) {
target_workspace_id: string, const items = await this.getPageTree<TreeItem>(targetWorkspaceId);
new_page_id: string await this.setPageTree(targetWorkspaceId, [
) { { id: newPageId, children: [] },
const items = await this.getPageTree<TreeItem>(target_workspace_id);
await this.setPageTree(target_workspace_id, [
{ id: new_page_id, children: [] },
...items, ...items,
]); ]);
} }
async addChildPageToWorkspace( async addChildPageToWorkspace(
target_workspace_id: string, targetWorkspaceId: string,
parent_page_id: string, parentPageId: string,
new_page_id: string newPageId: string
) { ) {
const pages = await this.getPageTree<TreeItem>(target_workspace_id); const pages = await this.getPageTree<TreeItem>(targetWorkspaceId);
this.build_items_for_child_page(parent_page_id, new_page_id, pages); this._buildItemsForChildPage(parentPageId, newPageId, pages);
await this.setPageTree<TreeItem>(target_workspace_id, [...pages]); await this.setPageTree<TreeItem>(targetWorkspaceId, [...pages]);
} }
async addPrevPageToWorkspace( async addPrevPageToWorkspace(
target_workspace_id: string, targetWorkspaceId: string,
parent_page_id: string, parentPageId: string,
new_page_id: string newPageId: string
) { ) {
const pages = await this.getPageTree<TreeItem>(target_workspace_id); const pages = await this.getPageTree<TreeItem>(targetWorkspaceId);
this.build_items_for_prev_page(parent_page_id, new_page_id, pages); this._buildItemsForPrevPage(parentPageId, newPageId, pages);
await this.setPageTree<TreeItem>(target_workspace_id, [...pages]); await this.setPageTree<TreeItem>(targetWorkspaceId, [...pages]);
} }
async addNextPageToWorkspace( async addNextPageToWorkspace(
target_workspace_id: string, targetWorkspaceId: string,
parent_page_id: string, parentPageId: string,
new_page_id: string newPageId: string
) { ) {
const pages = await this.getPageTree<TreeItem>(target_workspace_id); const pages = await this.getPageTree<TreeItem>(targetWorkspaceId);
this.build_items_for_next_page(parent_page_id, new_page_id, pages); this._buildItemsForNextPage(parentPageId, newPageId, pages);
await this.setPageTree<TreeItem>(target_workspace_id, [...pages]); await this.setPageTree<TreeItem>(targetWorkspaceId, [...pages]);
} }
private build_items_for_next_page( private _buildItemsForNextPage(
parent_page_id: string, parentPageId: string,
new_page_id: string, newPageId: string,
children: TreeItem[] children: TreeItem[]
) { ) {
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child_page = children[i]; const childPage = children[i];
if (child_page.id === parent_page_id) { if (childPage.id === parentPageId) {
const new_page = { const newPage = {
id: new_page_id, id: newPageId,
title: 'Untitled', title: 'Untitled',
children: [] as TreeItem[], children: [] as TreeItem[],
}; };
children = children.splice(i + 1, 0, new_page); children = children.splice(i + 1, 0, newPage);
} else if (child_page.children && child_page.children.length) { } else if (childPage.children && childPage.children.length) {
this.build_items_for_next_page( this._buildItemsForNextPage(
parent_page_id, parentPageId,
new_page_id, newPageId,
child_page.children childPage.children
); );
} }
} }
} }
private build_items_for_prev_page( private _buildItemsForPrevPage(
parent_page_id: string, parentPageId: string,
new_page_id: string, newPageId: string,
children: TreeItem[] children: TreeItem[]
) { ) {
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child_page = children[i]; const childPage = children[i];
if (child_page.id === parent_page_id) { if (childPage.id === parentPageId) {
const new_page = { const newPage = {
id: new_page_id, id: newPageId,
title: 'Untitled', title: 'Untitled',
children: [] as TreeItem[], children: [] as TreeItem[],
}; };
children = children.splice(i - 1, 0, new_page); children = children.splice(i - 1, 0, newPage);
} else if (child_page.children && child_page.children.length) { } else if (childPage.children && childPage.children.length) {
this.build_items_for_prev_page( this._buildItemsForPrevPage(
parent_page_id, parentPageId,
new_page_id, newPageId,
child_page.children childPage.children
); );
} }
} }
} }
private build_items_for_child_page( private _buildItemsForChildPage(
parent_page_id: string, parentPageId: string,
new_page_id: string, newPageId: string,
children: TreeItem[] children: TreeItem[]
) { ) {
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
const child_page = children[i]; const childPage = children[i];
if (child_page.id === parent_page_id) { if (childPage.id === parentPageId) {
child_page.children = child_page.children || []; childPage.children = childPage.children || [];
child_page.children.push({ childPage.children.push({
id: new_page_id, id: newPageId,
title: 'Untitled', title: 'Untitled',
children: [], children: [],
}); });
} else if (child_page.children && child_page.children.length) { } else if (childPage.children && childPage.children.length) {
this.build_items_for_child_page( this._buildItemsForChildPage(
parent_page_id, parentPageId,
new_page_id, newPageId,
child_page.children childPage.children
); );
} }
} }
@@ -164,10 +161,10 @@ export class PageTree extends ServiceBaseClass {
{ workspace, page }: { workspace: string; page: string }, { workspace, page }: { workspace: string; page: string },
callback: ObserveCallback callback: ObserveCallback
): Promise<ReturnUnobserve> { ): Promise<ReturnUnobserve> {
const workspace_db_block = await this.getWorkspaceDbBlock(workspace); const workspaceDbBlock = await this.getWorkspaceDbBlock(workspace);
const unobserveWorkspace = await this._observe( const unobserveWorkspace = await this._observe(
workspace, workspace,
workspace_db_block.id, workspaceDbBlock.id,
(states, block) => { (states, block) => {
callback(); callback();
} }
@@ -187,12 +184,12 @@ export class PageTree extends ServiceBaseClass {
} }
async unobserve({ workspace }: { workspace: string }) { async unobserve({ workspace }: { workspace: string }) {
const workspace_db_block = await this.getWorkspaceDbBlock(workspace); const workspaceDbBlock = await this.getWorkspaceDbBlock(workspace);
await this._unobserve(workspace, workspace_db_block.id); await this._unobserve(workspace, workspaceDbBlock.id);
} }
} }
async function update_tree_items_title< async function _updateTreeItemsTitle<
TreeItem extends { id: string; title: string; children: TreeItem[] } TreeItem extends { id: string; title: string; children: TreeItem[] }
>( >(
db: BlockClientInstance, db: BlockClientInstance,
@@ -213,7 +210,7 @@ async function update_tree_items_title<
} }
if (item.children.length) { if (item.children.length) {
item.children = await update_tree_items_title( item.children = await _updateTreeItemsTitle(
db, db,
item.children, item.children,
cache cache

14
pnpm-lock.yaml generated
View File

@@ -401,6 +401,7 @@ importers:
'@types/react-window': ^1.8.5 '@types/react-window': ^1.8.5
code-example: ^3.3.6 code-example: ^3.3.6
codemirror: 6.0.1 codemirror: 6.0.1
codemirror-lang-elixir: ^3.0.0
keymap: link:@codemirror/next/keymap keymap: link:@codemirror/next/keymap
nanoid: ^4.0.0 nanoid: ^4.0.0
react-resizable: ^3.0.4 react-resizable: ^3.0.4
@@ -437,6 +438,7 @@ importers:
'@mui/system': 5.8.7_d6menda4vqwq6peqnkbe7mkj4i '@mui/system': 5.8.7_d6menda4vqwq6peqnkbe7mkj4i
code-example: 3.3.6 code-example: 3.3.6
codemirror: 6.0.1 codemirror: 6.0.1
codemirror-lang-elixir: 3.0.0_@codemirror+language@6.2.0
keymap: link:@codemirror/next/keymap keymap: link:@codemirror/next/keymap
nanoid: 4.0.0 nanoid: 4.0.0
react-resizable: 3.0.4 react-resizable: 3.0.4
@@ -4578,8 +4580,8 @@ packages:
dependencies: dependencies:
'@babel/runtime': 7.18.6 '@babel/runtime': 7.18.6
'@emotion/cache': 11.9.3 '@emotion/cache': 11.9.3
'@emotion/react': 11.9.3 '@emotion/react': 11.9.3_@babel+core@7.18.6
'@emotion/styled': 11.9.3_@emotion+react@11.9.3 '@emotion/styled': 11.9.3_dc5dh2wp562rsjxvguwi2i3yzq
csstype: 3.1.0 csstype: 3.1.0
prop-types: 15.8.1 prop-types: 15.8.1
dev: false dev: false
@@ -8518,6 +8520,14 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/codemirror-lang-elixir/3.0.0_@codemirror+language@6.2.0:
resolution: {integrity: sha512-Liy5MDxf+xw7aFqNfhLfntSK6vsRkI0lSlyytw23P1hWSrb0Bw5WunEB3iKJ49iUu8Kj2dx+vvMqD8I5ms7rSQ==}
peerDependencies:
'@codemirror/language': ^6.2.1
dependencies:
'@codemirror/language': 6.2.0
dev: false
/codemirror/6.0.1: /codemirror/6.0.1:
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies: dependencies: