Skip to content

Commit

Permalink
feat(sheets-thread-comment): comment support for sheets (#2228)
Browse files Browse the repository at this point in the history
* feat: add thread-comment pkg

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: temp

* feat: update

* feat: update

* feat: u

* feat: update

* feat: update

* feat: update

* feat: update

* fix: #2121

* fix: close #2120

* fix: #2114

* fix: #2112

* feat: temp

* feat: update

* feat: support at-input

* feat: ref-range

* feat: update mentions

* feat: user

* feat: update

* feat: update comment

* feat: style update

* feat: update

* feat: update

* feat: update

* feat: update

* feat: rename

* feat: scroller

* feat: update

* feat: update

* feat: update

* feat: update

* fix: #684 univer-pro

* feat: auto-height

* feat: update

* feat: update

* fix: eslint

* feat: remove useless code

* build: fix build error

* chore: fix lockfile

* build: fix deps

* feat: update

* feat: update

* feat: update

* feat: i18n

* feat: add sheet name

* feat: disable undo on resolve comment operation

* feat: update

* fix: #2174

* feat: #2162 checkbox ticked and unticked value

* feat: update

* fix: hover-manager-service

* feat: support copy-paste

* feat: sidebar visible status

* feat: style

* feat: update

* feat: update init

* feat: temp

* feat: update

* feat: update

* fix: checkbox validator

* feat: lint

* fix: error when delete worksheet

* feat: refactor canvas popup service

* feat: update

* feat: lock

* feat: custom-render event handler

* feat: update ref

* fix: copy-paste

* feat: update

* feat: update

* feat: update max-height

* feat: update

* feat: fix delete comment

* fix: #715

* feat: update

* feat: update scroll

* feat: style update

* feat: bugfix

* feat: update

* feat: close sidebar

* fix: cv undo

* feat: update

* feat: render z-index

* feat: code review issue

* feat: transform mentions data

* feat: u

* feat: bugfix

* feat: update

* feat: update

* feat: style & bugfix

* feat: style update

* feat: update

* feat: update

* feat: update

* feat: add thread-comment-data-source-service to support async comment crud

* feat: rename

* feat: build issue

* fix: sort order of comments

* feat: lint

* feat: rename

* feat: rebase dev

---------

Co-authored-by: 白熱 <sonne@asaki.me>
  • Loading branch information
weird94 and jikkai authored May 21, 2024
1 parent 57d4e8a commit 313ab79
Show file tree
Hide file tree
Showing 90 changed files with 5,343 additions and 93 deletions.
3 changes: 3 additions & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@
"@univerjs/sheets-find-replace": "workspace:*",
"@univerjs/sheets-formula": "workspace:*",
"@univerjs/sheets-numfmt": "workspace:*",
"@univerjs/sheets-thread-comment": "workspace:*",
"@univerjs/sheets-ui": "workspace:*",
"@univerjs/sheets-zen-editor": "workspace:*",
"@univerjs/slides": "workspace:*",
"@univerjs/slides-ui": "workspace:*",
"@univerjs/thread-comment": "workspace:*",
"@univerjs/thread-comment-ui": "workspace:*",
"@univerjs/ui": "workspace:*",
"@univerjs/uniscript": "workspace:*",
"@wendellhu/redi": "^0.15.1",
Expand Down
4 changes: 4 additions & 0 deletions examples/src/data/sheets/demo/default-workbook-data-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23560,6 +23560,10 @@ export const DEFAULT_WORKBOOK_DATA_DEMO: IWorkbookData = {
},
}),
},
{
name: 'SHEET_THREAD_COMMENT_PLUGIN',
data: '{"sheet-0011":[{"text":{"textRuns":[],"paragraphs":[{"startIndex":3,"paragraphStyle":{}}],"sectionBreaks":[{"startIndex":4}],"dataStream":"123\\n\\r","customRanges":[]},"dT":"2024/05/17 21:16","id":"jwV0QtHwUbhG3o--iy1qa","ref":"H9","personId":"mockId","unitId":"workbook-01","subUnitId":"sheet-0011"}]}',
},
],
// namedRanges: [
// {
Expand Down
35 changes: 34 additions & 1 deletion examples/src/sheets/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { LocaleType, LogLevel, Univer, UniverInstanceType } from '@univerjs/core';
import { LocaleType, LogLevel, Univer, UniverInstanceType, UserManagerService } from '@univerjs/core';
import { defaultTheme } from '@univerjs/design';
import { UniverDocsPlugin } from '@univerjs/docs';
import { UniverDocsUIPlugin } from '@univerjs/docs-ui';
Expand All @@ -34,6 +34,7 @@ import { UniverUIPlugin } from '@univerjs/ui';
import { UniverDataValidationPlugin } from '@univerjs/data-validation';
import { UniverSheetsDataValidationPlugin } from '@univerjs/sheets-data-validation';
import { UniverSheetsConditionalFormattingUIPlugin } from '@univerjs/sheets-conditional-formatting-ui';
import { UniverSheetsThreadCommentPlugin } from '@univerjs/sheets-thread-comment';
import { UniverDebuggerPlugin } from '@univerjs/debugger';

import { FUniver } from '@univerjs/facade';
Expand Down Expand Up @@ -98,9 +99,41 @@ if (!IS_E2E) {
univer.createUnit(UniverInstanceType.UNIVER_SHEET, DEFAULT_WORKBOOK_DATA_DEMO);
}

const mockUser = {
userID: 'mockId',
name: 'MockUser',
avatar: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAInSURBVHgBtZU9TxtBEIbfWRzFSIdkikhBSqRQkJqkCKTCFkqVInSUSaT0wC8w/gXxD4gU2nRJkXQWhAZowDUUWKIwEgWWbEEB3mVmx3dn4DA2nB/ppNuPeWd29mMIPXDr+RxwtgRHeW6+guNPRxogqnL7Dwz9psJ27S4NShaeZTH3kwXy6I81dlRKcmRui88swdq9AcSFL7Buz1Vmlns64MiLsCjzwnIYHLH57tbfFbs7KRaXyEU8FVZofqccOfA5l7Q8LPIkGrwnb2RPNEXWFVMUF3L+kDCk0btDDAMzOm5YfAHDwp4tG74wnzAsiOYMnJ3GoDybA7IT98/jm5+JNnfiIzAS6LlqHQBN/i6b2t/cV1Hh6BfwYlHnHP4AXi5q/8kmMMpOs8+BixZw/Fd6xUEHEbnkgclvQP2fGp7uShRKnQ3G32rkjV1th8JhIGG7tR/JyjGteSOZELwGMmNqIIigRCLRh2OZIE6BjItdd7pCW6Uhm1zzkUtungSxwEUzNpQ+GQumtH1ej1MqgmNT6vwmhCq5yuwq56EYTbgeQUz3yvrpV1b4ok3nYJ+eYhgYmjRUqErx2EDq0Fr8FhG++iqVGqxlUJI/70Ar0UgJaWHj6hYVHJrfKssAHot1JfqwE9WVWzXZVd5z2Ws/4PnmtEjkXeKJDvxUecLbWOXH/DP6QQ4J72NS0adedp1aseBfXP8odlZFfPvBF7SN/8hky1TYuPOAXAEipMx15u5ToAAAAABJRU5ErkJggg==',
};

univer.registerPlugin(UniverSheetsThreadCommentPlugin, {
mentions: [{
trigger: '@',
getMentions: async () => {
return [
{
id: mockUser.userID,
label: mockUser.name,
type: 'user',
icon: mockUser.avatar,
},
{
id: '2',
label: 'User2',
type: 'user',
icon: mockUser.avatar,
},
];
},
}],
});

// debugger plugin
univer.registerPlugin(UniverDebuggerPlugin);

const injector = univer.__getInjector();
const userManagerService = injector.get(UserManagerService);
userManagerService.setCurrentUser(mockUser);

declare global {
interface Window {
univer?: Univer;
Expand Down
16 changes: 15 additions & 1 deletion packages/core/src/services/user-manager/user-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,27 @@
*/

import type { IUser } from '@univerjs/protocol';
import { Subject } from 'rxjs';
import { BehaviorSubject, Subject } from 'rxjs';

export class UserManagerService {
private _model = new Map<string, IUser>();
private _userChange$ = new Subject<{ type: 'add' | 'delete'; user: IUser } | { type: 'clear' }>();
public userChange$ = this._userChange$.asObservable();

private _currentUser: IUser | null;
private _currentUser$ = new BehaviorSubject<IUser | null>(null);
public currentUser$ = this._currentUser$.asObservable();

getCurrentUser() {
return this._currentUser;
}

setCurrentUser(user: IUser) {
this._currentUser = user;
this.addUser(user);
this._currentUser$.next(user);
}

addUser(user: IUser) {
this._model.set(user.userID, user);
this._userChange$.next({ type: 'add', user });
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/interfaces/i-document-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ export enum CustomRangeType {
BOOKMARK,
COMMENT,
CUSTOM,
MENTION,
}

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/design/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"dependencies": {
"@rc-component/color-picker": "^1.5.3",
"@rc-component/trigger": "^1.18.3",
"@types/react-mentions": "^4.1.13",
"@univerjs/icons": "^0.1.45",
"rc-dialog": "^9.4.0",
"rc-dropdown": "^4.2.0",
Expand All @@ -88,6 +89,7 @@
"rc-util": "^5.39.3",
"react-draggable": "^4.4.6",
"react-grid-layout": "^1.4.4",
"react-mentions": "^4.4.10",
"react-transition-group": "^4.4.5"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions packages/design/src/components/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export interface IButtonProps {

/** Set the handler to handle `click` event */
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;

id?: string;
}

export function Button(props: IButtonProps) {
Expand Down
68 changes: 68 additions & 0 deletions packages/design/src/components/mentions/Mentions.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { Meta } from '@storybook/react';
import React, { useState } from 'react';

import { Mention } from 'react-mentions';
import { Mentions } from './Mentions';

const meta: Meta<typeof Mentions> = {
title: 'Components / Mentions',
component: Mentions,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
};

export default meta;

export const InputBasic = {

render() {
const [value, onChange] = useState('');

return (
<div style={{ width: 400 }}>
<Mentions
value={value}
onChange={(e) => onChange(e.target.value)}
>
<Mention
trigger="@"
data={[
{
id: '1',
display: 'zhangwei ',
},
{
id: '2',
display: 'zhangwei2 ',
},
{
id: '3',
display: 'zhangwei3 ',
},
]}
/>
</Mentions>
</div>

);
},
};

33 changes: 33 additions & 0 deletions packages/design/src/components/mentions/Mentions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React, { forwardRef } from 'react';
import type { MentionsInputProps } from 'react-mentions';
import { MentionsInput } from 'react-mentions';
import styles from './index.module.less';

export interface IMentionsProps extends MentionsInputProps {}

export const Mentions = forwardRef<React.Component<MentionsInputProps, any, any>, IMentionsProps>((props, ref) => {
return (
<MentionsInput
ref={ref}
{...props}
className={styles.mentions}
/>
);
});

71 changes: 71 additions & 0 deletions packages/design/src/components/mentions/index.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
.mentions {
width: 100%;
}

.mentions__control {
min-height: 32px;
}

.mentions__highlighter {
border-radius: 6px;
background: rgba(var(--color-white));
padding: 6px 10px;
font-size: 13px !important;
line-height: 20px !important;
max-height: 114px;

strong {
color: rgb(var(--blue-500));
}
}

.mentions__highlighter__substring {
visibility: inherit !important;
color: rgb(var(--color-black));
}

.mentions__input {
width: 100%;
caret-color: red;
background-color: transparent;
color: transparent;
padding: 6px 10px;
border: 1px solid rgb(var(--border-color));
border-radius: 6px;
font-size: 13px !important;
line-height: 20px !important;
max-height: 114px;
}

.mentions__input:focus {
border: 1px solid rgb(var(--blue-500));
outline: none !important;
}

.mentions__suggestions {
border-radius: 8px;
overflow: hidden;
background: rgb(var(--color-white)) !important;
border: 1px solid rgb(var(--grey-200)) !important;
box-shadow: var(--box-shadow-base) !important;
width: 100%;
box-sizing: border-box;
margin-top: 20px !important;
}

.mentions__suggestions__list {
display: flex;
flex-direction: column;
padding: 8px !important;
width: 100%;
box-sizing: border-box;
}

.mentions__suggestions__item {
padding: 4px 8px;
border-radius: 6px;
}

.mentions__suggestions__item--focused {
background-color: rgb(var(--grey-50));
}
19 changes: 19 additions & 0 deletions packages/design/src/components/mentions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export { Mentions } from './Mentions';
export type { IMentionsProps } from './Mentions';
export { Mention, type MentionProps } from 'react-mentions';
Loading

0 comments on commit 313ab79

Please sign in to comment.