From 9539befce82e1894c903bf85f515da2338033be2 Mon Sep 17 00:00:00 2001 From: spaenleh Date: Tue, 23 Aug 2022 14:47:09 +0200 Subject: [PATCH] fix: add translations and improve styling with theme --- example/src/components/ChatboxWrapper.tsx | 7 +- package.json | 4 +- src/components/Chatbox/Input.tsx | 108 +++++++++++++--------- src/components/Mentions/MentionButton.tsx | 66 +++++++------ src/components/Mentions/MentionsTable.tsx | 58 ++++++++---- yarn.lock | 21 +++-- 6 files changed, 162 insertions(+), 102 deletions(-) diff --git a/example/src/components/ChatboxWrapper.tsx b/example/src/components/ChatboxWrapper.tsx index fc1940c7..6ecf598a 100644 --- a/example/src/components/ChatboxWrapper.tsx +++ b/example/src/components/ChatboxWrapper.tsx @@ -27,13 +27,12 @@ const ChatboxWrapper: FC = ({ // use kooks const { data: currentMember } = hooks.useCurrentMember(); const { data: chat } = hooks.useItemChat(chatId); + const memberships = hooks.useItemMemberships(chatId).data; // get chat messages const chatMessages = chat?.messages; - // get id of member that posted messages in the chat - const memberIds: string[] = Array.from( - new Set(chatMessages?.map(({ creator }: { creator: string }) => creator)), - ); + const memberIds: string[] = + memberships?.map((m) => m.memberId)?.toArray() || []; const member = new ImmutableMember(currentMember); const members = hooks.useMembers(memberIds).data; diff --git a/package.json b/package.json index 0ed2f69b..d34abbf1 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "react-dom": "*" }, "dependencies": { - "@graasp/translations": "github:graasp/graasp-translations.git", + "@graasp/translations": "github:graasp/graasp-translations#32/addMentionsTranslations", "@graasp/ui": "github:graasp/graasp-ui", "clsx": "1.1.1", "i18next": "21.8.1", @@ -60,7 +60,7 @@ "react-csv": "2.2.2", "react-i18next": "11.18.1", "react-markdown": "8.0.3", - "react-mentions": "4.4.7", + "react-mentions": "4.4.6", "react-router-dom": "6.3.0", "remark-breaks": "3.0.2", "remark-gfm": "3.0.1" diff --git a/src/components/Chatbox/Input.tsx b/src/components/Chatbox/Input.tsx index 5fd57319..ddd7027a 100644 --- a/src/components/Chatbox/Input.tsx +++ b/src/components/Chatbox/Input.tsx @@ -9,7 +9,7 @@ import { SuggestionDataItem, } from 'react-mentions'; -import { Typography } from '@material-ui/core'; +import { Typography, useTheme } from '@material-ui/core'; import Box from '@material-ui/core/Box'; import IconButton from '@material-ui/core/IconButton'; import { makeStyles } from '@material-ui/core/styles'; @@ -60,46 +60,8 @@ const useStyles = makeStyles((theme) => ({ }, })); -const inputStyle = { - width: '100%', - // mentions - control: { - minHeight: '63px', - }, - input: { - padding: '9px', - border: '1px solid silver', - width: '100%', - overflow: 'auto', - height: '70px', - borderRadius: '4px', - }, - highlighter: { - padding: '9px', - border: '1px solid transparent', - boxSizing: 'border-box', - overflow: 'hidden', - height: '70px', - }, - - suggestions: { - list: { - backgroundColor: 'white', - border: '1px solid rgba(0,0,0,0.15)', - fontSize: '1rem', - }, - item: { - padding: '15px 20px', - borderBottom: '1px solid rgba(0,0,0,0.15)', - '&focused': { - backgroundColor: '#cee4e5', - }, - }, - }, -}; - const mentionStyle = { - backgroundColor: '#c5c9e8', + backgroundColor: '#b9b9ed', }; const Input: FC = ({ @@ -110,6 +72,60 @@ const Input: FC = ({ placeholder, sendMessageFunction, }) => { + // use mui theme for the mentions component + // we can not use 'useStyles' with it because it requests an object for the styles + const theme = useTheme(); + // padding for the input field, needs to match the padding for the overlay + // in the 'highlighter' key + const inputPadding = theme.spacing(1); + const inputRadius = theme.spacing(0.5); + const inputStyle = { + width: '100%', + minWidth: '0px', + // mentions + control: { + minHeight: '63px', + }, + input: { + padding: inputPadding, + border: '1px solid silver', + width: '100%', + overflow: 'auto', + height: '70px', + borderRadius: inputRadius, + }, + highlighter: { + padding: inputPadding, + border: '1px solid transparent', + boxSizing: 'border-box', + overflow: 'hidden', + height: '70px', + }, + + suggestions: { + // hides the sharp corners + overflow: 'hidden', + borderRadius: inputRadius, + list: { + // hides the sharp corners + overflow: 'hidden', + backgroundColor: 'white', + fontSize: '1rem', + border: '1px solid rgba(0,0,0,0.15)', + borderRadius: inputRadius, + }, + item: { + display: { + // change the style of the suggestions + }, + padding: theme.spacing(0.5, 2), + '&focused': { + backgroundColor: '#b9b9ed', + }, + }, + }, + }; + const classes = useStyles(); const { members } = useMessagesContext(); const { id: currentMemberId } = useCurrentMemberContext(); @@ -178,9 +194,13 @@ const Input: FC = ({ let helperText = ' '; const normalizedTextInput = normalizeMentions(textInput); if (textInput) { - helperText = - normalizedTextInput.length + - (isMessageTooLong ? ` (max. ${HARD_MAX_MESSAGE_LENGTH} chars)` : ''); + helperText = normalizedTextInput.length.toString(); + // append the max message size + if (isMessageTooLong) { + helperText += t(CHATBOX.INPUT_MESSAGE_TOO_LONG, { + length: HARD_MAX_MESSAGE_LENGTH, + }); + } } return ( = ({ onKeyDown={keyDown} style={inputStyle} forceSuggestionsAboveCursor - a11ySuggestionsListLabel={'Suggested mentions'} + a11ySuggestionsListLabel={t(CHATBOX.SUGGESTED_MENTIONS)} placeholder={placeholder || t(CHATBOX.INPUT_FIELD_PLACEHOLDER)} > QueryObserverResult; @@ -28,12 +31,18 @@ type Props = { const MentionButton: FC = ({ color = 'primary', + lang = langs.en, useMentions, useMembers, patchMentionFunction, deleteMentionFunction, clearAllMentionsFunction, }) => { + const i18n = useMemo(() => { + const i18nInstance = buildI18n(namespaces.chatbox); + i18nInstance.changeLanguage(lang); + return i18nInstance; + }, [lang]); const useStyles = makeStyles((theme) => ({ badge: { '& .MuiBadge-badge': { @@ -46,6 +55,7 @@ const MentionButton: FC = ({ }, })); const classes = useStyles(); + const t = i18n.t; const { data: memberMentions } = useMentions(); const mentions = memberMentions?.mentions; @@ -58,7 +68,9 @@ const MentionButton: FC = ({ const mentionsWithMembers = mentions?.map((m) => { return m.update( 'creator', - () => members.find((u) => u.id === m.creator)?.name || 'Anonymous', + () => + members.find((u) => u.id === m.creator)?.name || + t(CHATBOX.ANONYMOUS_USER), ); }); @@ -66,31 +78,33 @@ const MentionButton: FC = ({ return (
- setOpen(true)}> - m.status === MentionStatus.UNREAD)?.size || - 0 + + setOpen(true)}> + m.status === MentionStatus.UNREAD) + ?.size || 0 + } + > + + + + } - > - - - - - } - open={open} - setOpen={setOpen} - /> + open={open} + setOpen={setOpen} + /> +
); }; diff --git a/src/components/Mentions/MentionsTable.tsx b/src/components/Mentions/MentionsTable.tsx index 76577cca..dff9c9bc 100644 --- a/src/components/Mentions/MentionsTable.tsx +++ b/src/components/Mentions/MentionsTable.tsx @@ -1,6 +1,7 @@ import { List } from 'immutable'; import { FC, ReactElement, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { Grid, @@ -11,16 +12,28 @@ import { TableHead, TableRow, Tooltip, + makeStyles, } from '@material-ui/core'; import { Check, Close, FiberManualRecord } from '@material-ui/icons'; import { ChatMentionRecord } from '@graasp/query-client/dist/src/types'; -import { MentionStatus } from '@graasp/sdk'; +import { MentionStatus, buildItemLinkForBuilder } from '@graasp/sdk'; +import { getIdsFromPath } from '@graasp/sdk/dist/utils/item'; +import { CHATBOX } from '@graasp/translations'; import { Button } from '@graasp/ui'; import { normalizeMentions } from '../../utils/mentions'; import ConfirmationDialog from '../common/ConfirmationDialog'; +const useStyles = makeStyles({ + row: { + '&:hover': { + // make the cursor a pointer to indicate we can click + cursor: 'pointer', + }, + }, +}); + type Props = { mentions?: List; patchMention: (args: { id: string; status: string }) => void; @@ -35,6 +48,8 @@ const MentionsTable: FC = ({ clearAllMentions, }) => { const [openConfirmation, setOpenConfirmation] = useState(false); + const { t } = useTranslation(); + const classes = useStyles(); const markAsRead = (id: string): void => { patchMention({ id: id, status: MentionStatus.READ }); }; @@ -50,25 +65,29 @@ const MentionsTable: FC = ({ return mentions .map((m) => ( console.log('go to item', m.itemPath)} + onClick={(): void => { + const link = buildItemLinkForBuilder({ + host: '', + itemId: getIdsFromPath(m.itemPath).slice(-1)[0], + chatOpen: true, + }); + console.log(link); + window.location.href = link; + }} > - {m.status === MentionStatus.UNREAD ? ( + {m.status === MentionStatus.UNREAD && ( - ) : null} - - - {Object.keys(m.toJS()) - .map((k: string) => `${k}: ${m[k]}`) - .join('\n')} + )} {normalizeMentions(m.message)} {m.creator} - + { e.stopPropagation(); @@ -80,7 +99,7 @@ const MentionsTable: FC = ({ - + { e.stopPropagation(); @@ -111,18 +130,18 @@ const MentionsTable: FC = ({ ); }} > - Mark All As Read + {t(CHATBOX.MARK_ALL_AS_READ)} { clearAllMentions(); setOpenConfirmation(false); @@ -134,11 +153,10 @@ const MentionsTable: FC = ({ - Status - Infos - Message - By - Actions + {t(CHATBOX.COL_STATUS)} + {t(CHATBOX.COL_MESSAGE)} + {t(CHATBOX.COL_BY)} + {t(CHATBOX.COL_ACTIONS)} {renderMentionTableContent()} diff --git a/yarn.lock b/yarn.lock index 46e201d8..8aad987b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2188,7 +2188,7 @@ __metadata: "@cypress/webpack-dev-server": 1.8.4 "@graasp/query-client": "github:graasp/graasp-query-client#183/updateChatMessageTypes" "@graasp/sdk": "github:graasp/graasp-sdk#38/addMentionStatusEnum" - "@graasp/translations": "github:graasp/graasp-translations.git" + "@graasp/translations": "github:graasp/graasp-translations#32/addMentionsTranslations" "@graasp/ui": "github:graasp/graasp-ui" "@material-ui/core": 4.12.4 "@material-ui/icons": 4.11.2 @@ -2241,7 +2241,7 @@ __metadata: react-dom: 17.0.2 react-i18next: 11.18.1 react-markdown: 8.0.3 - react-mentions: 4.4.7 + react-mentions: 4.4.6 react-router-dom: 6.3.0 react-scripts: 5.0.1 remark-breaks: 3.0.2 @@ -2323,6 +2323,15 @@ __metadata: languageName: node linkType: hard +"@graasp/translations@github:graasp/graasp-translations#32/addMentionsTranslations": + version: 0.1.0 + resolution: "@graasp/translations@https://github.com/graasp/graasp-translations.git#commit=496b52ade0ebf655d94bd89f45335dd8f255732e" + dependencies: + i18next: 21.8.1 + checksum: 1b00196da9371f7ec9a864f6b0152fac566786ee38fd744cf00565b6e446748398f5f6baa4dfc137f21e1c2e208ced4288e8f7552efbd624a955ffb2ebe8bc98 + languageName: node + linkType: hard + "@graasp/translations@github:graasp/graasp-translations.git": version: 0.1.0 resolution: "@graasp/translations@https://github.com/graasp/graasp-translations.git#commit=be598da34ba1dda3a95c2dea737dacfad78b50fd" @@ -15894,9 +15903,9 @@ __metadata: languageName: node linkType: hard -"react-mentions@npm:4.4.7": - version: 4.4.7 - resolution: "react-mentions@npm:4.4.7" +"react-mentions@npm:4.4.6": + version: 4.4.6 + resolution: "react-mentions@npm:4.4.6" dependencies: "@babel/runtime": 7.4.5 invariant: ^2.2.4 @@ -15905,7 +15914,7 @@ __metadata: peerDependencies: react: ">=16.8.3" react-dom: ">=16.8.3" - checksum: 3d195df7b8d762d0f184cb8a76c82ea7f6509b122bfac733c0bdebc3d592bd0aa98f3c61535945c2a115c92afb97949590c6cb00d77d3cb5e40ccaa385223dcb + checksum: 174b218936958d4c2ed76d1001b67331475288ad212089552a887382dcc587eda4e14250b89d9cbe91135255ad3a33395f2367ae8d14f8085f70998032608f59 languageName: node linkType: hard