Skip to content

Commit

Permalink
feat: allow user to copy-click the participants email addresses
Browse files Browse the repository at this point in the history
* feat: let user to copy-click addresses on emails

* chore: change the background of chip icon

* chore: used the snackbar from ds
  • Loading branch information
dhavaldodiya authored Oct 25, 2023
1 parent de7f7c1 commit 86ccc03
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 69 deletions.
27 changes: 27 additions & 0 deletions src/ui-actions/participant-displayer-actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2023 Zextras <https://www.zextras.com>
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { CreateSnackbarFn } from '@zextras/carbonio-design-system';
import { t } from '@zextras/carbonio-shell-ui';

import { mailToSharedFunction } from '../integrations/shared-functions';
import { Participant } from '../types';

export const copyEmailToClipboard = (email: string, createSnackbar: CreateSnackbarFn): void => {
navigator.clipboard.writeText(email).then(() => {
createSnackbar({
key: `clipboard-copy-success`,
replace: true,
type: 'success',
hideButton: true,
label: t('snackbar.email_copied_to_clipboard', 'Email copied to clipboard.'),
autoHideTimeout: 3000
});
});
};

export const sendMsg = (contact: Participant): void => {
mailToSharedFunction([contact]);
};
89 changes: 89 additions & 0 deletions src/views/app/detail-panel/preview/parts/contact-names-chips.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* SPDX-FileCopyrightText: 2022 Zextras <https://www.zextras.com>
*
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { FC, ReactElement, useContext } from 'react';

import {
Row,
Text,
Chip,
Container,
SnackbarManagerContext
} from '@zextras/carbonio-design-system';
import { t } from '@zextras/carbonio-shell-ui';
import { map } from 'lodash';

import type { Participant } from '../../../../../types';
import {
copyEmailToClipboard,
sendMsg
} from '../../../../../ui-actions/participant-displayer-actions';

const ContactNameChip: FC<{
showOverflow?: boolean;
contacts: Participant[];
label: string;
}> = ({ contacts, label }): ReactElement => {
const createSnackbar = useContext(SnackbarManagerContext);
return (
<>
<Row mainAlignment="flex-start">
<Text color="secondary" size="small" style={{ paddingRight: '0.25rem' }}>
{label}
</Text>
</Row>
<Row
mainAlignment="flex-start"
takeAvailableSpace
height="fit"
orientation="vertical"
display="flex"
wrap={'nowrap'}
style={{
lineHeight: '1.125rem',
flexDirection: 'row',
overflow: 'hidden'
}}
>
<Container
orientation="horizontal"
wrap="wrap"
mainAlignment="flex-start"
style={{ gap: '0.5rem' }}
>
{map(contacts, (contact) => (
<Chip
label={contact.address}
background="gray2"
color="text"
data-testid={'Chip'}
actions={[
{
id: 'action1',
label: t('message.send_email', 'Send e-mail'),
type: 'button',
icon: 'EmailOutline',
background: 'gray3',
onClick: () => sendMsg(contact)
},
{
id: 'action2',
label: t('message.copy', 'Copy'),
type: 'button',
icon: 'Copy',
background: 'gray3',
onClick: () => copyEmailToClipboard(contact.address, createSnackbar)
}
]}
/>
))}
</Container>
</Row>
</>
);
};

export default ContactNameChip;
13 changes: 5 additions & 8 deletions src/views/app/detail-panel/preview/parts/contact-names.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { capitalize, map } from 'lodash';
import React, { FC, ReactElement, useLayoutEffect, useRef, useState } from 'react';
import styled from 'styled-components';

import { Row, Tooltip, Text } from '@zextras/carbonio-design-system';
import { useUserAccounts } from '@zextras/carbonio-shell-ui';
import { capitalize, map } from 'lodash';
import styled from 'styled-components';

import { participantToString } from '../../../../../commons/utils';
import type { Participant } from '../../../../../types';
Expand All @@ -23,23 +24,19 @@ const ContactSubText = styled(Text)`
}
`;
const ContactName: FC<{
showMoreCB?: (showMore: boolean) => void;
showOverflow?: boolean;
contacts: Participant[];
label: string;
}> = ({ showMoreCB, showOverflow, contacts, label }): ReactElement => {
}> = ({ showOverflow, contacts, label }): ReactElement => {
const accounts = useUserAccounts();
const toRef = useRef<HTMLInputElement>(null);
const [isOverflow, setIsOverflow] = useState(false);
useLayoutEffect(() => {
if (toRef?.current?.clientWidth) {
const rowOverflow = toRef?.current.scrollWidth > toRef?.current.clientWidth;
if (showOverflow && rowOverflow) {
showMoreCB && showMoreCB(true);
}
setIsOverflow(rowOverflow);
}
}, [showMoreCB, showOverflow]);
}, [showOverflow]);

return (
<>
Expand Down
115 changes: 59 additions & 56 deletions src/views/app/detail-panel/preview/parts/message-contact-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React, {
FC,
ReactElement,
useCallback,
useLayoutEffect,
useMemo,
useRef,
useState
} from 'react';

import {
Badge,
Container,
Expand All @@ -15,30 +25,30 @@ import {
} from '@zextras/carbonio-design-system';
import { t } from '@zextras/carbonio-shell-ui';
import { filter } from 'lodash';
import React, {
FC,
ReactElement,
useCallback,
useLayoutEffect,
useMemo,
useRef,
useState
} from 'react';
import type { MailMessage, TextReadValuesProps } from '../../../../../types';

import ContactNames from './contact-names';
import { getFolderTranslatedName } from '../../../../sidebar/utils';
import ContactNameChip from './contact-names-chips';
import { useFoldersMap } from '../../../../../carbonio-ui-commons/store/zustand/folder';
import type { MailMessage, TextReadValuesProps } from '../../../../../types';
import { getFolderTranslatedName } from '../../../../sidebar/utils';

const MessageContactList: FC<{
message: MailMessage;
folderId: string;
}> = ({ message, folderId }): ReactElement => {
contactListExpandCB: (showMore: boolean) => void;
}> = ({ message, folderId, contactListExpandCB }): ReactElement => {
const [open, setOpen] = useState(false);

const toggleOpen = useCallback((e) => {
e.preventDefault();
setOpen((o) => !o);
}, []);
const toggleOpen = useCallback(
(e) => {
e.preventDefault();
setOpen((o) => {
contactListExpandCB(!o);
return !o;
});
},
[contactListExpandCB]
);
const folders = useFoldersMap();

const toContacts = useMemo(
Expand Down Expand Up @@ -74,10 +84,6 @@ const MessageContactList: FC<{
() => messageFolder?.name && messageFolder?.id !== folderId,
[folderId, messageFolder]
);
const [isOverflow, setIsOverflow] = useState(false);
const showMoreCB = useCallback((showMore) => {
setIsOverflow(showMore);
}, []);

const toggleExpandButtonLabel = useMemo(
() =>
Expand Down Expand Up @@ -108,66 +114,63 @@ const MessageContactList: FC<{
mainAlignment="space-between"
orientation="horizontal"
>
{isOverflow && (
<Tooltip label={toggleExpandButtonLabel}>
<IconButton
size="small"
icon={open ? 'ChevronUp' : 'ChevronDown'}
onClick={toggleOpen}
customSize={{
iconSize: 'small',
paddingSize: ''
}}
/>
</Tooltip>
)}
<Tooltip label={toggleExpandButtonLabel}>
<IconButton
size="small"
icon={open ? 'ChevronUp' : 'ChevronDown'}
onClick={toggleOpen}
customSize={{
iconSize: 'small',
paddingSize: ''
}}
/>
</Tooltip>
</Container>
<Container mainAlignment="flex-start" crossAlignment="flex-start" width={badgeWidth}>
{!open && (
<Container width="calc(100% - 1.5rem)" crossAlignment="flex-start">
<Row height="fit" crossAlignment="flex-start" mainAlignment="flex-start">
{toContacts.length > 0 && (
<ContactNames
showMoreCB={showMoreCB}
showOverflow
contacts={toContacts}
label={labelTo}
/>
<ContactNames showOverflow contacts={toContacts} label={labelTo} />
)}
</Row>
<Row height="fit" crossAlignment="flex-start" mainAlignment="flex-start">
{ccContacts.length > 0 && (
<ContactNames
showMoreCB={showMoreCB}
showOverflow
contacts={ccContacts}
label={labelCc}
/>
<ContactNames showOverflow contacts={ccContacts} label={labelCc} />
)}
</Row>
<Row height="fit" width="100%" crossAlignment="flex-start" mainAlignment="flex-start">
{bccContacts.length > 0 && (
<ContactNames
showMoreCB={showMoreCB}
showOverflow
contacts={bccContacts}
label={labelBcc}
/>
<ContactNames showOverflow contacts={bccContacts} label={labelBcc} />
)}
</Row>
</Container>
)}
{open && (
<Container width="calc(100% - 1.5rem)" crossAlignment="flex-start">
<Container width="100%">
<Row height="fit" width="100%" crossAlignment="flex-start" mainAlignment="flex-start">
{toContacts.length > 0 && <ContactNames contacts={toContacts} label={labelTo} />}
<Row
height="fit"
width="100%"
crossAlignment="flex-start"
mainAlignment="flex-start"
padding={{ bottom: 'small' }}
>
{toContacts.length > 0 && <ContactNameChip contacts={toContacts} label={labelTo} />}
</Row>
<Row height="fit" width="100%" crossAlignment="flex-start" mainAlignment="flex-start">
{ccContacts.length > 0 && <ContactNames contacts={ccContacts} label={labelCc} />}
<Row
height="fit"
width="100%"
crossAlignment="flex-start"
mainAlignment="flex-start"
padding={{ bottom: 'small' }}
>
{ccContacts.length > 0 && <ContactNameChip contacts={ccContacts} label={labelCc} />}
</Row>
<Row height="fit" width="100%" crossAlignment="flex-start" mainAlignment="flex-start">
{bccContacts.length > 0 && <ContactNames contacts={bccContacts} label={labelBcc} />}
{bccContacts.length > 0 && (
<ContactNameChip contacts={bccContacts} label={labelBcc} />
)}
</Row>
</Container>
</Container>
Expand Down
Loading

0 comments on commit 86ccc03

Please sign in to comment.