Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mentions #71

Merged
merged 5 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"parser": "@typescript-eslint/parser",
"extends": [
"standard",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/cypress_tests.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Cypress tests
on: [ push ]
on: [push]
jobs:
test:
runs-on: ubuntu-latest
Expand All @@ -8,13 +8,10 @@ jobs:
uses: actions/checkout@v2

- name: component tests 🧪
uses: cypress-io/github-action@v2
uses: cypress-io/github-action@v5
with:
# to run component tests we need to use "cypress run-ct"
command: yarn cypress run-ct
component: true
browser: chrome
headless: true
quiet: true

# after the test run completes
# store videos and any screenshots
Expand Down
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

49 changes: 49 additions & 0 deletions cypress/components/mention-parsing.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';

import { convertJs } from '@graasp/sdk';

import Chatbox, {
LEGACY_MENTION_MARKUP,
getMentionMarkupFromMember,
} from '../../src';
import { dataCyWrapper, messageIdCyWrapper } from '../../src/config/selectors';
import { ALL_MEMBERS_DISPLAY, ALL_MEMBERS_MEMBER } from '../../src/constants';
import { ImmutableMember } from '../../src/types';
import { CHAT_ID, getMockMessage } from '../fixtures/chat_messages';
import { MEMBERS } from '../fixtures/members';
import { mockUseAvatar } from '../fixtures/mockHooks';

describe('Mention Highlighting', () => {
it('Display legacy mentions', () => {
const { hook: fakeHook } = mockUseAvatar();
const anna = MEMBERS.ANNA;
const annaMessage = getMockMessage({
message: getMentionMarkupFromMember(anna, LEGACY_MENTION_MARKUP),
});
const allMessage = getMockMessage({
message: getMentionMarkupFromMember(
ALL_MEMBERS_MEMBER,
LEGACY_MENTION_MARKUP,
),
});
console.log(allMessage.body);
spaenleh marked this conversation as resolved.
Show resolved Hide resolved

cy.mount(
<Chatbox
chatId={CHAT_ID}
currentMember={new ImmutableMember(MEMBERS.ANNA)}
members={convertJs(Object.values(MEMBERS))}
messages={convertJs([annaMessage, allMessage])}
useAvatarHook={fakeHook}
/>,
);
cy.get(dataCyWrapper(messageIdCyWrapper(annaMessage.id))).should(
'contain',
`@${anna.name}`,
);
cy.get(dataCyWrapper(messageIdCyWrapper(allMessage.id))).should(
'contain',
`@${ALL_MEMBERS_DISPLAY}`,
);
});
});
13 changes: 11 additions & 2 deletions cypress/fixtures/chat_messages.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { v4 } from 'uuid';

import { getMentionMarkupFromMember } from '../../src';
import { ChatMessage } from '../../src/types';
import { CURRENT_MEMBER, MEMBERS } from './members';

export const CHAT_ID = v4();
export const MOCK_MESSAGE_BODY = 'This is a message';

export const getMockMessage = ({ member = CURRENT_MEMBER }): ChatMessage => ({
export const getMockMessage = ({
member = CURRENT_MEMBER,
message = MOCK_MESSAGE_BODY,
}): ChatMessage => ({
id: v4(),
chatId: CHAT_ID,
creator: member.id,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
body: 'This is a message',
body: message,
});

export const CHAT_MESSAGES = [
Expand Down Expand Up @@ -49,6 +54,10 @@ export const CHAT_MESSAGES = [
},
];

export const CHAT_MESSAGES_WITH_LEGACY_MENTIONS: ChatMessage[] = [
getMockMessage({ message: getMentionMarkupFromMember(MEMBERS.ANNA) }),
];

export const SHORT_COMMENT = 'Hello how are you ?';
export const LONG_COMMENT = `# Test Title

Expand Down
15 changes: 14 additions & 1 deletion cypress/fixtures/members.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
export const MEMBERS = {
import { Member, MemberType } from '@graasp/sdk';

const dateNow = new Date().toISOString();
export const MEMBERS: { [key: string]: Member } = {
ANNA: {
id: '0f0a2774-a965-4b97-afb4-bccc3796e060',
name: 'anna',
email: '[email protected]',
type: MemberType.Individual,
extra: {},
createdAt: dateNow,
updatedAt: dateNow,
},
BOB: {
id: '1f0a2774-a965-4b97-afb4-bccc3796e060',
name: 'bob',
email: '[email protected]',
type: MemberType.Individual,
extra: {},
createdAt: dateNow,
updatedAt: dateNow,
},
};

Expand Down
File renamed without changes.
9 changes: 9 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "node"],
"esModuleInterop": true
},
"include": ["**/*.ts"]
}
12 changes: 6 additions & 6 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
},
"dependencies": {
"@graasp/chatbox": "link:..",
"@graasp/query-client": "github:graasp/graasp-query-client",
"@mui/icons-material": "5.10.9",
"@mui/material": "5.10.9",
"@graasp/query-client": "0.1.2",
"@mui/icons-material": "5.11.0",
"@mui/material": "5.11.6",
"@types/jest": "link:../node_modules/@types/jest",
"@types/node": "link:../node_modules/@types/node",
"@types/react": "link:../node_modules/@types/react",
"@types/react-dom": "link:../node_modules/@types/react-dom",
"immutable": "4.0.0",
"immutable": "4.2.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-i18next": "11.18.1",
"react-i18next": "12.0.0",
"react-scripts": "5.0.1",
"typescript": "4.7.4"
"typescript": "4.9.4"
},
"devDependencies": {
"@babel/plugin-syntax-object-rest-spread": "7.8.3"
Expand Down
57 changes: 30 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,21 @@
"react-dom": "*"
},
"dependencies": {
"@emotion/react": "11.10.4",
"@emotion/styled": "11.10.4",
"@graasp/translations": "github:graasp/graasp-translations",
"@graasp/ui": "github:graasp/graasp-ui#v0.3.0",
"clsx": "1.1.1",
"@emotion/react": "11.10.5",
"@emotion/styled": "11.10.5",
"@graasp/translations": "1.3.0",
"@graasp/ui": "0.7.1",
"clsx": "1.2.1",
"i18next": "21.8.1",
"immutable": "4.0.0",
"immutable": "4.1.0",
"lodash.truncate": "4.4.2",
"moment": "2.29.4",
"prism-react-renderer": "1.3.5",
"react-csv": "2.2.2",
"react-i18next": "11.18.1",
"react-i18next": "12.0.0",
"react-markdown": "8.0.3",
"react-mentions": "4.4.6",
"react-mentions": "4.4.7",
"react-query": "3.39.2",
"react-router-dom": "6.3.0",
"remark-breaks": "3.0.2",
"remark-gfm": "3.0.1"
Expand All @@ -72,35 +73,35 @@
"last 1 Chrome version"
],
"devDependencies": {
"@commitlint/cli": "16.2.3",
"@commitlint/config-conventional": "16.0.0",
"@commitlint/cli": "17.4.2",
"@commitlint/config-conventional": "17.4.2",
"@cypress/instrument-cra": "1.4.0",
"@cypress/react": "5.12.4",
"@cypress/webpack-dev-server": "1.8.4",
"@graasp/query-client": "github:graasp/graasp-query-client",
"@graasp/sdk": "github:graasp/graasp-sdk",
"@mui/icons-material": "5.10.9",
"@mui/lab": "5.0.0-alpha.103",
"@mui/material": "5.10.9",
"@cypress/react": "7.0.2",
"@cypress/webpack-dev-server": "3.2.3",
"@graasp/query-client": "0.1.2",
"@graasp/sdk": "0.2.0",
"@mui/icons-material": "5.11.0",
"@mui/lab": "5.0.0-alpha.117",
"@mui/material": "5.11.6",
"@rollup/plugin-commonjs": "21.0.1",
"@rollup/plugin-json": "4.1.0",
"@rollup/plugin-node-resolve": "13.1.3",
"@rollup/plugin-typescript": "8.3.0",
"@trivago/prettier-plugin-sort-imports": "3.2.0",
"@types/jest": "27.4.0",
"@types/lodash.truncate": "4.4.6",
"@types/lodash.truncate": "4.4.7",
"@types/material-ui": "0.21.12",
"@types/node": "17.0.24",
"@types/papaparse": "5.3.2",
"@types/react": "17.0.2",
"@types/react-csv": "1.1.2",
"@types/react-dom": "17.0.11",
"@types/react-mentions": "4.1.6",
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.30.7",
"@typescript-eslint/parser": "5.30.7",
"@types/react-mentions": "4.1.8",
"@types/uuid": "9.0.0",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"cross-env": "7.0.3",
"cypress": "10.6.0",
"cypress": "12.4.0",
"env-cmd": "10.1.0",
"eslint": "8.23.0",
"eslint-config-prettier": "8.3.0",
Expand All @@ -110,9 +111,9 @@
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-promise": "5.2.0",
"eslint-plugin-react": "7.30.1",
"husky": "8.0.1",
"husky": "8.0.3",
"papaparse": "5.3.2",
"prettier": "2.7.1",
"prettier": "2.8.3",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-scripts": "5.0.1",
Expand All @@ -124,10 +125,12 @@
"standard-version": "9.5.0",
"ts-loader": "9.3.1",
"tslib": "2.3.1",
"typescript": "4.8.4"
"typescript": "4.9.4"
},
"resolutions": {
"@types/react": "17.0.2"
"@types/react": "17.0.2",
"immutable": "4.1.0",
"react-query": "3.39.2"
},
"files": [
"dist"
Expand Down
9 changes: 5 additions & 4 deletions src/components/Chatbox/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ import {
sendButtonCypress,
} from '../../config/selectors';
import {
ALL_MEMBERS_DISPLAY,
ALL_MEMBERS_ID,
ALL_MEMBERS_SUGGESTION,
GRAASP_MENTION_COLOR,
HARD_MAX_MESSAGE_LENGTH,
} from '../../constants';
import { useCurrentMemberContext } from '../../context/CurrentMemberContext';
import { useMessagesContext } from '../../context/MessagesContext';
import { MENTION_MARKUP } from '../../utils/mentions';
import FullWidthWrapper from '../common/FullWidthWrapper';

const HelperText = styled(Typography)(({ theme }) => ({
Expand Down Expand Up @@ -125,7 +126,7 @@ const Input: FC<Props> = ({

// exclude self from suggestions and add @all pseudo member
const memberSuggestions: SuggestionDataItem[] = [
{ id: ALL_MEMBERS_ID, display: ALL_MEMBERS_DISPLAY },
ALL_MEMBERS_SUGGESTION,
...(members
?.filter((m) => m.id !== currentMemberId)
?.map((m) => ({ id: m.id, display: m.name }))
Expand Down Expand Up @@ -234,8 +235,8 @@ const Input: FC<Props> = ({
placeholder={placeholder || t(CHATBOX.INPUT_FIELD_PLACEHOLDER)}
>
<Mention
displayTransform={(_, login): string => `@${login}`}
markup="`<!@__display__>[__id__]`"
displayTransform={(_, display): string => `@${display}`}
markup={MENTION_MARKUP}
trigger="@"
renderSuggestion={(_, __, highlightedDisplay): ReactElement => (
<div className="user">{highlightedDisplay}</div>
Expand Down
33 changes: 26 additions & 7 deletions src/components/Chatbox/MessageBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ import { CodeProps } from 'react-markdown/lib/ast-to-react';

import { styled } from '@mui/material';

import { ALL_MEMBERS_ID } from '../../constants';
import { Member } from '@graasp/sdk';

import {
ALL_MEMBERS_ID,
ALL_MEMBERS_MEMBER,
UNKNOWN_USER_NAME,
} from '../../constants';
import { useCurrentMemberContext } from '../../context/CurrentMemberContext';
import { getMention } from '../../utils/mentions';
import { useMessagesContext } from '../../context/MessagesContext';
import { getIdMention, getMention } from '../../utils/mentions';

const StyledReactMarkdown = styled(ReactMarkdown)(({ theme }) => ({
fontFamily: theme.typography.fontFamily,
Expand Down Expand Up @@ -83,6 +90,7 @@ type Props = {

const MessageBody: FC<Props> = ({ messageBody }) => {
const { id: currentMemberId } = useCurrentMemberContext();
const { members } = useMessagesContext();

const renderCode = ({
inline,
Expand All @@ -91,19 +99,30 @@ const MessageBody: FC<Props> = ({ messageBody }) => {
...props
}: CodeProps): ReactElement => {
const match = (classNameInit || '').match(/language-(\w+)/);
const mention = getMention(codeContent.join(''));
if (inline && mention && mention.groups) {
const mentionText = codeContent.join('');
// try to match a legacy mention
const legacyMention = getMention(mentionText);
const mention = getIdMention(mentionText);
if (
inline &&
((legacyMention && legacyMention.groups) || (mention && mention.groups))
) {
const userId = mention?.groups?.id || legacyMention?.groups?.id;
const userName =
[...(members.toJS() as Member[]), ALL_MEMBERS_MEMBER].find(
(m) => m.id === userId,
)?.name || UNKNOWN_USER_NAME;

return (
<span
style={{
...((mention.groups.id === currentMemberId ||
mention.groups.id === ALL_MEMBERS_ID) && {
...((userId === currentMemberId || userId === ALL_MEMBERS_ID) && {
backgroundColor: '#e3c980',
}),
fontWeight: 'bold',
}}
>
@{mention[1]}
@{userName}
</span>
);
}
Expand Down
Loading