mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-18 14:01:44 +03:00
Merge remote-tracking branch 'origin/develop' into feature/new-grid-drop
This commit is contained in:
commit
f87d4e3d18
45
CODE_OF_CONDUCT.md
Normal file
45
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,45 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
|
||||
|
||||
For answers to common questions about this code of conduct, see <https://www.contributor-covenant.org/faq>
|
88
CONTRIBUTING.md
Normal file
88
CONTRIBUTING.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Welcome to ourcontributing guide <!-- omit in toc -->
|
||||
|
||||
Thank you for investing your time in contributing to our project! Any contribution you make will be reflected on our GitHub :sparkles:.
|
||||
|
||||
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
|
||||
|
||||
In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR.
|
||||
|
||||
Use the table of contents icon on the top left corner of this document to get to a specific section of this guide quickly.
|
||||
|
||||
## New contributor guide
|
||||
|
||||
To get an overview of the project, read the [README](README.md). Here are some resources to help you get started with open source contributions:
|
||||
|
||||
- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
|
||||
- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
|
||||
- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
|
||||
- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
|
||||
|
||||
## Getting started
|
||||
|
||||
To navigate our codebase with confidence, see [the introduction to working in the docs repository](/contributing/working-in-docs-repository.md) :confetti_ball:. For more information on how we write our markdown files, see [the GitHub Markdown reference](contributing/content-markup-reference.md).
|
||||
|
||||
Check to see what [types of contributions](/contributing/types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:.
|
||||
|
||||
### Issues
|
||||
|
||||
#### Create a new issue
|
||||
|
||||
If you spot a problem, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/toeverything/AFFiNE/issues/new/choose).
|
||||
|
||||
#### Solve an issue
|
||||
|
||||
Scan through our [existing issues](https://github.com/toeverything/AFFiNE/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See [Labels](/contributing/how-to-use-labels.md) for more information. As a general rule, we don’t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix.
|
||||
|
||||
### Make Changes
|
||||
|
||||
#### Make changes in the UI
|
||||
|
||||
Click **Make a contribution** at the bottom of any docs page to make small changes such as a typo, sentence fix, or a broken link. This takes you to the `.md` file where you can make your changes and [create a pull request](#pull-request) for a review.
|
||||
|
||||
#### Make changes in a codespace
|
||||
|
||||
For more information about using a codespace for working on GitHub documentation, see "[Working in a codespace](https://github.com/github/docs/blob/main/contributing/codespace.md)."
|
||||
|
||||
#### Make changes locally
|
||||
|
||||
1. [Install Git LFS](https://docs.github.com/en/github/managing-large-files/versioning-large-files/installing-git-large-file-storage).
|
||||
|
||||
2. Fork the repository.
|
||||
|
||||
- Using GitHub Desktop:
|
||||
|
||||
- [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.
|
||||
- Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)!
|
||||
|
||||
- Using the command line:
|
||||
- [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.
|
||||
|
||||
3. Install or update to **Node.js v16**. For more information, see [the development guide](contributing/development.md).
|
||||
|
||||
4. Create a working branch and start with your changes!
|
||||
|
||||
### Commit your update
|
||||
|
||||
Commit the changes once you are happy with them.
|
||||
|
||||
Once your changes are ready, don't forget to self-review to speed up the review process:zap:.
|
||||
|
||||
### Pull Request
|
||||
|
||||
When you're finished with the changes, create a pull request, also known as a PR.
|
||||
|
||||
- Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
|
||||
- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
|
||||
- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
|
||||
Once you submit your PR, a Docs team member will review your proposal. We may ask questions or request for additional information.
|
||||
- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
|
||||
- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
|
||||
- If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues.
|
||||
|
||||
### Your PR is merged!
|
||||
|
||||
Congratulations :tada::tada: The AFFiNE team thanks you :sparkles:.
|
||||
|
||||
Once your PR is merged, your contributions will be publicly visible on the our GitHub.
|
||||
|
||||
Now that you are part of the AFFiNE community, see how else you can join and help over at [Gitbook](https://affine.gitbook.io/affine/)
|
@ -10,7 +10,6 @@ const StyledTabs = styled('div')(({ theme }) => {
|
||||
display: 'flex',
|
||||
fontSize: '12px',
|
||||
fontWeight: '600',
|
||||
color: theme.affine.palette.primary,
|
||||
};
|
||||
});
|
||||
|
||||
@ -26,13 +25,18 @@ const StyledTabTitle = styled('div', {
|
||||
padding-top: 4px;
|
||||
border-top: 2px solid #ecf1fb;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
color: ${({ theme, isActive }) =>
|
||||
isActive ? theme.affine.palette.primary : 'rgba(62, 111, 219, 0.6)'};
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background-color: ${({ isActive, theme }) =>
|
||||
isActive ? theme.affine.palette.primary : ''};
|
||||
isActive
|
||||
? theme.affine.palette.primary
|
||||
: 'rgba(62, 111, 219, 0.6)'};
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: -2px;
|
||||
|
@ -36,6 +36,9 @@ export class GridBlock extends BaseView {
|
||||
}
|
||||
return block.remove();
|
||||
}
|
||||
if (block.childrenIds.length === 0) {
|
||||
return block.remove();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,13 @@ export const CardContainer = (props: CardContainerProps) => {
|
||||
const { kanban } = useKanban();
|
||||
const { containerIds, items: dataSource, activeId } = props;
|
||||
return (
|
||||
<KanbanContainer>
|
||||
<KanbanContainer
|
||||
onMouseDown={e => {
|
||||
// Fix https://github.com/toeverything/AFFiNE/issues/29
|
||||
// Prevent active selection when dragging kanban card
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{containerIds.map((containerId, idx) => {
|
||||
const items = dataSource[containerId];
|
||||
|
||||
|
@ -128,8 +128,12 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
||||
if (clientHeight - rectTop <= COMMAND_MENU_HEIGHT) {
|
||||
setCommandMenuPosition({
|
||||
left: rect.left - left,
|
||||
bottom: rectTop - top + 10,
|
||||
top: 'initial',
|
||||
top:
|
||||
rectTop -
|
||||
top -
|
||||
COMMAND_MENU_HEIGHT +
|
||||
20,
|
||||
bottom: 'initial',
|
||||
});
|
||||
} else {
|
||||
setCommandMenuPosition({
|
||||
|
@ -17,16 +17,20 @@ export const StatusIcon = ({ mode }: StatusIconProps) => {
|
||||
const IconWrapper = styled('div')<Pick<StatusIconProps, 'mode'>>(
|
||||
({ theme, mode }) => {
|
||||
return {
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
width: '24px',
|
||||
height: '24px',
|
||||
borderRadius: '5px',
|
||||
boxShadow: theme.affine.shadows.shadow1,
|
||||
color: theme.affine.palette.primary,
|
||||
cursor: 'pointer',
|
||||
backgroundColor: theme.affine.palette.white,
|
||||
transform: `translateX(${mode === DocMode.doc ? 0 : 20}px)`,
|
||||
transform: `translateX(${mode === DocMode.doc ? 0 : 30}px)`,
|
||||
transition: 'transform 300ms ease',
|
||||
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
|
||||
'& > svg': {
|
||||
fontSize: '20px',
|
||||
},
|
||||
|
@ -2,26 +2,37 @@ import { styled } from '@toeverything/components/ui';
|
||||
|
||||
type StatusTextProps = {
|
||||
children: string;
|
||||
width?: string;
|
||||
active?: boolean;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const StatusText = ({ children, active, onClick }: StatusTextProps) => {
|
||||
export const StatusText = ({
|
||||
children,
|
||||
width,
|
||||
active,
|
||||
onClick,
|
||||
}: StatusTextProps) => {
|
||||
return (
|
||||
<StyledText active={active} onClick={onClick}>
|
||||
<StyledText width={width} active={active} onClick={onClick}>
|
||||
{children}
|
||||
</StyledText>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledText = styled('div')<StatusTextProps>(({ theme, active }) => {
|
||||
return {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: theme.affine.palette.primary,
|
||||
fontWeight: active ? '500' : '300',
|
||||
fontSize: '15px',
|
||||
cursor: 'pointer',
|
||||
padding: '0 6px',
|
||||
};
|
||||
});
|
||||
const StyledText = styled('div')<StatusTextProps>(
|
||||
({ theme, width, active }) => {
|
||||
return {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
color: active
|
||||
? theme.affine.palette.primary
|
||||
: 'rgba(62, 111, 219, 0.6)',
|
||||
fontWeight: active ? '600' : '400',
|
||||
fontSize: '16px',
|
||||
lineHeight: '22px',
|
||||
cursor: 'pointer',
|
||||
...(!!width && { width }),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -18,11 +18,15 @@ export const StatusTrack: FC<StatusTrackProps> = ({ mode, onClick }) => {
|
||||
|
||||
const Container = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '64px',
|
||||
height: '32px',
|
||||
backgroundColor: theme.affine.palette.textHover,
|
||||
borderRadius: '5px',
|
||||
height: '30px',
|
||||
width: '50px',
|
||||
border: '1px solid #ECF1FB',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
padding: '5px',
|
||||
margin: '0 8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0 4px',
|
||||
};
|
||||
});
|
||||
|
@ -32,6 +32,7 @@ export const Switcher = () => {
|
||||
return (
|
||||
<StyledContainerForSwitcher>
|
||||
<StatusText
|
||||
width={'44px'}
|
||||
active={pageViewMode === DocMode.doc}
|
||||
onClick={() => switchToPageView(DocMode.doc)}
|
||||
>
|
||||
@ -48,6 +49,7 @@ export const Switcher = () => {
|
||||
}}
|
||||
/>
|
||||
<StatusText
|
||||
width={'56px'}
|
||||
active={pageViewMode === DocMode.board}
|
||||
onClick={() => switchToPageView(DocMode.board)}
|
||||
>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IconButton, styled } from '@toeverything/components/ui';
|
||||
import { IconButton, styled, MuiButton } from '@toeverything/components/ui';
|
||||
import {
|
||||
LogoIcon,
|
||||
SideBarViewIcon,
|
||||
@ -24,9 +24,13 @@ export const LayoutHeader = () => {
|
||||
</FlexContainer>
|
||||
<FlexContainer>
|
||||
<StyledHelper>
|
||||
<StyledShare>Share</StyledShare>
|
||||
<StyledShare disabled={true}>Share</StyledShare>
|
||||
<div style={{ margin: '0px 12px' }}>
|
||||
<IconButton size="large">
|
||||
<IconButton
|
||||
size="large"
|
||||
hoverColor={'transparent'}
|
||||
disabled={true}
|
||||
>
|
||||
<SearchIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
@ -119,17 +123,19 @@ const StyledHelper = styled('div')({
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
const StyledShare = styled('div')({
|
||||
const StyledShare = styled(MuiButton)<{ disabled?: boolean }>({
|
||||
padding: '10px 12px',
|
||||
fontWeight: 600,
|
||||
fontSize: '14px',
|
||||
color: '#3E6FDB',
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:hover': {
|
||||
background: '#F5F7F8',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
color: '#98ACBD',
|
||||
textTransform: 'none',
|
||||
/* disabled for current time */
|
||||
// color: '#3E6FDB',
|
||||
// '&:hover': {
|
||||
// background: '#F5F7F8',
|
||||
// borderRadius: '5px',
|
||||
// },
|
||||
});
|
||||
|
||||
const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
|
||||
@ -141,9 +147,7 @@ const StyledLogoIcon = styled(LogoIcon)(({ theme }) => {
|
||||
|
||||
const StyledContainerForEditorBoardSwitcher = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
left: '50%',
|
||||
};
|
||||
});
|
||||
|
@ -67,8 +67,12 @@ export function ChildrenListenerHandler(
|
||||
const keys = Array.from(event.keys.entries()).map(
|
||||
([key, { action }]) => [key, action] as [string, ChangedStateKeys]
|
||||
);
|
||||
const deleted = Array.from(event.changes.deleted.values())
|
||||
.flatMap(val => val.content.getContent() as string[])
|
||||
.filter(v => v)
|
||||
.map(k => [k, 'delete'] as [string, ChangedStateKeys]);
|
||||
for (const listener of listeners.values()) {
|
||||
EmitEvents(keys, listener);
|
||||
EmitEvents([...keys, ...deleted], listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,13 @@ export class AbstractBlock<
|
||||
C extends ContentOperation
|
||||
> {
|
||||
private readonly _id: string;
|
||||
readonly #block: BlockInstance<C>;
|
||||
private readonly _block: BlockInstance<C>;
|
||||
private readonly _history: HistoryManager;
|
||||
private readonly _root?: AbstractBlock<B, C>;
|
||||
private readonly _parentListener: Map<string, BlockListener>;
|
||||
|
||||
_parent?: AbstractBlock<B, C>;
|
||||
private _parent?: AbstractBlock<B, C>;
|
||||
private _changeParent?: () => void;
|
||||
|
||||
constructor(
|
||||
block: B,
|
||||
@ -40,20 +41,14 @@ export class AbstractBlock<
|
||||
parent?: AbstractBlock<B, C>
|
||||
) {
|
||||
this._id = block.id;
|
||||
this.#block = block;
|
||||
this._history = this.#block.scopedHistory([this._id]);
|
||||
this._block = block;
|
||||
this._history = this._block.scopedHistory([this._id]);
|
||||
|
||||
this._root = root;
|
||||
this._parentListener = new Map();
|
||||
this._parent = parent;
|
||||
|
||||
JWT_DEV && logger_debug(`init: exists ${this._id}`);
|
||||
if (parent) {
|
||||
parent.addChildrenListener(this._id, states => {
|
||||
if (states.get(this._id) === 'delete') {
|
||||
this._emitParent(parent._id, 'delete');
|
||||
}
|
||||
});
|
||||
}
|
||||
if (parent) this._refreshParent(parent);
|
||||
}
|
||||
|
||||
public get root() {
|
||||
@ -66,7 +61,7 @@ export class AbstractBlock<
|
||||
|
||||
protected _getParentPage(warning = true): string | undefined {
|
||||
if (this.flavor === 'page') {
|
||||
return this.#block.id;
|
||||
return this._block.id;
|
||||
} else if (!this._parent) {
|
||||
if (warning && this.flavor !== 'workspace') {
|
||||
console.warn('parent not found');
|
||||
@ -89,7 +84,7 @@ export class AbstractBlock<
|
||||
if (event === 'parent') {
|
||||
this._parentListener.set(name, callback);
|
||||
} else {
|
||||
this.#block.on(event, name, callback);
|
||||
this._block.on(event, name, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,42 +92,40 @@ export class AbstractBlock<
|
||||
if (event === 'parent') {
|
||||
this._parentListener.delete(name);
|
||||
} else {
|
||||
this.#block.off(event, name);
|
||||
this._block.off(event, name);
|
||||
}
|
||||
}
|
||||
|
||||
public addChildrenListener(name: string, listener: BlockListener) {
|
||||
this.#block.addChildrenListener(name, listener);
|
||||
this._block.addChildrenListener(name, listener);
|
||||
}
|
||||
|
||||
public removeChildrenListener(name: string) {
|
||||
this.#block.removeChildrenListener(name);
|
||||
this._block.removeChildrenListener(name);
|
||||
}
|
||||
|
||||
public addContentListener(name: string, listener: BlockListener) {
|
||||
this.#block.addContentListener(name, listener);
|
||||
this._block.addContentListener(name, listener);
|
||||
}
|
||||
|
||||
public removeContentListener(name: string) {
|
||||
this.#block.removeContentListener(name);
|
||||
this._block.removeContentListener(name);
|
||||
}
|
||||
|
||||
public getContent<
|
||||
T extends ContentTypes = ContentOperation
|
||||
>(): MapOperation<T> {
|
||||
if (this.#block.type === BlockTypes.block) {
|
||||
return this.#block.content.asMap() as MapOperation<T>;
|
||||
if (this._block.type === BlockTypes.block) {
|
||||
return this._block.content.asMap() as MapOperation<T>;
|
||||
}
|
||||
throw new Error(
|
||||
`this block not a structured block: ${this._id}, ${
|
||||
this.#block.type
|
||||
}`
|
||||
`this block not a structured block: ${this._id}, ${this._block.type}`
|
||||
);
|
||||
}
|
||||
|
||||
public getBinary(): ArrayBuffer | undefined {
|
||||
if (this.#block.type === BlockTypes.binary) {
|
||||
return this.#block.content.asArray<ArrayBuffer>()?.get(0);
|
||||
if (this._block.type === BlockTypes.binary) {
|
||||
return this._block.content.asArray<ArrayBuffer>()?.get(0);
|
||||
}
|
||||
throw new Error('this block not a binary block');
|
||||
}
|
||||
@ -162,7 +155,7 @@ export class AbstractBlock<
|
||||
|
||||
// Last update UTC time
|
||||
public get lastUpdated(): number {
|
||||
return this.#block.updated || this.#block.created;
|
||||
return this._block.updated || this._block.created;
|
||||
}
|
||||
|
||||
private get last_updated_date(): string | undefined {
|
||||
@ -171,7 +164,7 @@ export class AbstractBlock<
|
||||
|
||||
// create UTC time
|
||||
public get created(): number {
|
||||
return this.#block.created;
|
||||
return this._block.created;
|
||||
}
|
||||
|
||||
private get created_date(): string | undefined {
|
||||
@ -180,11 +173,11 @@ export class AbstractBlock<
|
||||
|
||||
// creator id
|
||||
public get creator(): string | undefined {
|
||||
return this.#block.creator;
|
||||
return this._block.creator;
|
||||
}
|
||||
|
||||
[_GET_BLOCK]() {
|
||||
return this.#block;
|
||||
return this._block;
|
||||
}
|
||||
|
||||
private _emitParent(
|
||||
@ -199,8 +192,20 @@ export class AbstractBlock<
|
||||
}
|
||||
}
|
||||
|
||||
[_SET_PARENT](parent: AbstractBlock<B, C>) {
|
||||
private _refreshParent(parent: AbstractBlock<B, C>) {
|
||||
this._changeParent?.();
|
||||
parent.addChildrenListener(this._id, states => {
|
||||
if (states.get(this._id) === 'delete') {
|
||||
this._emitParent(parent._id, 'delete');
|
||||
}
|
||||
});
|
||||
|
||||
this._parent = parent;
|
||||
this._changeParent = () => parent.removeChildrenListener(this._id);
|
||||
}
|
||||
|
||||
[_SET_PARENT](parent: AbstractBlock<B, C>) {
|
||||
this._refreshParent(parent);
|
||||
this._emitParent(parent.id);
|
||||
}
|
||||
|
||||
@ -234,23 +239,23 @@ export class AbstractBlock<
|
||||
* current block type
|
||||
*/
|
||||
public get type(): typeof BlockTypes[BlockTypeKeys] {
|
||||
return this.#block.type;
|
||||
return this._block.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* current block flavor
|
||||
*/
|
||||
public get flavor(): typeof BlockFlavors[BlockFlavorKeys] {
|
||||
return this.#block.flavor;
|
||||
return this._block.flavor;
|
||||
}
|
||||
|
||||
// TODO: flavor needs optimization
|
||||
setFlavor(flavor: typeof BlockFlavors[BlockFlavorKeys]) {
|
||||
this.#block.setFlavor(flavor);
|
||||
this._block.setFlavor(flavor);
|
||||
}
|
||||
|
||||
public get children(): string[] {
|
||||
return this.#block.children;
|
||||
return this._block.children;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,12 +279,12 @@ export class AbstractBlock<
|
||||
throw new Error('insertChildren: binary not allow insert children');
|
||||
}
|
||||
|
||||
this.#block.insertChildren(block[_GET_BLOCK](), position);
|
||||
this._block.insertChildren(block[_GET_BLOCK](), position);
|
||||
block[_SET_PARENT](this);
|
||||
}
|
||||
|
||||
public hasChildren(id: string): boolean {
|
||||
return this.#block.hasChildren(id);
|
||||
return this._block.hasChildren(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,11 +294,11 @@ export class AbstractBlock<
|
||||
*/
|
||||
protected get_children(blockId?: string): BlockInstance<C>[] {
|
||||
JWT_DEV && logger(`get children: ${blockId}`);
|
||||
return this.#block.getChildren([blockId]);
|
||||
return this._block.getChildren([blockId]);
|
||||
}
|
||||
|
||||
public removeChildren(blockId?: string) {
|
||||
this.#block.removeChildren([blockId]);
|
||||
this._block.removeChildren([blockId]);
|
||||
}
|
||||
|
||||
public remove() {
|
||||
|
Loading…
Reference in New Issue
Block a user