Skip to content

Commit

Permalink
feat: tag search by clicking on tag (#81)
Browse files Browse the repository at this point in the history
* feat: tag search by clicking on tag

* fix: search query update regex fixed

* fix: regex update inside the search to prefill advance filters

* fix: added missing optional chaining in attachments block

* fix: removing un necesssary dependency from editor's useeffect
  • Loading branch information
geeky-abhishek authored May 9, 2022
1 parent 80b41cc commit 83cd3f7
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 50 deletions.
29 changes: 26 additions & 3 deletions src/hooks/use-get-tags-accordions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { ReactElement, useMemo } from 'react';
import { useTags, ZIMBRA_STANDARD_COLORS } from '@zextras/carbonio-shell-ui';
import React, { ReactElement, useCallback, useMemo } from 'react';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { useTags, ZIMBRA_STANDARD_COLORS, runSearch } from '@zextras/carbonio-shell-ui';
import {
AccordionItem,
Dropdown,
Expand Down Expand Up @@ -36,14 +38,35 @@ const CustomComp = (props: ItemProps): ReactElement => {
const [t] = useTranslation();
const actions = useGetTagsActions({ tag: props?.item, t });

const triggerSearch = useCallback(
() =>
runSearch(
[
{
avatarBackground: ZIMBRA_STANDARD_COLORS[props?.item?.color || 0].hex,
avatarIcon: 'Tag',
background: 'gray2',
hasAvatar: true,
isGeneric: false,
isQueryFilter: true,
label: `tag:${props?.item?.name}`,
value: `tag:"${props?.item?.name}"`
}
],
'mails'
),
[props?.item?.color, props?.item?.name]
);

return (
<Dropdown contextMenu items={actions} display="block" width="fit">
<Dropdown contextMenu items={actions} display="block" width="fit" onClick={triggerSearch}>
<Row mainAlignment="flex-start" height="fit" padding={{ left: 'large' }} takeAvailableSpace>
<Icon
size="large"
icon="Tag"
customColor={ZIMBRA_STANDARD_COLORS[props?.item?.color].hex}
/>

<Padding right="large" />
<Tooltip label={props?.item?.name} placement="right" maxWidth="100%">
<AccordionItem {...props} height={40} />
Expand Down
44 changes: 31 additions & 13 deletions src/ui-actions/mail-message-preview-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ import React, {
useCallback,
useContext
} from 'react';
import { Row, IconButton, Tooltip, Dropdown, ThemeContext } from '@zextras/carbonio-design-system';
import {
Row,
IconButton,
Tooltip,
Dropdown,
ThemeContext,
Padding
} from '@zextras/carbonio-design-system';
import { difference, map, slice } from 'lodash';
import { useParams } from 'react-router-dom';

import { useVisibleActionsCount } from '../hooks/use-visible-actions-count';

type MailMsgPreviewActionsType = {
Expand Down Expand Up @@ -108,18 +116,28 @@ const MailMsgPreviewActions: FC<MailMsgPreviewActionsType> = ({
}}
>
{firstActions?.length > 0 &&
map(firstActions, (action) => (
<Tooltip key={`${action.icon}`} label={action.label}>
<IconButton
size="small"
icon={action.icon}
onClick={(ev: React.MouseEvent<HTMLButtonElement>): void => {
if (ev) ev.preventDefault();
action.click();
}}
/>
</Tooltip>
))}
map(firstActions, (action) =>
action.items ? (
<Padding right="small">
<Tooltip label={action.label}>
<Dropdown items={action.items}>
<IconButton icon={action.icon} size="small" />
</Dropdown>
</Tooltip>
</Padding>
) : (
<Tooltip key={`${action.icon}`} label={action.label}>
<IconButton
size="small"
icon={action.icon}
onClick={(ev: React.MouseEvent<HTMLButtonElement>): void => {
if (ev) ev.preventDefault();
action.click();
}}
/>
</Tooltip>
)
)}
{secondActions?.length > 0 && (
<Dropdown items={secondActions} forceOpen={open} onClose={onDropdownClose}>
<IconButton size="small" icon="MoreVertical" onClick={onIconClick} />
Expand Down
10 changes: 9 additions & 1 deletion src/ui-actions/tag-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,13 @@ export const applyTag = ({
conversation: any;
tags: TagsFromStoreType;
isMessage?: boolean;
}): { id: string; items: TagType[]; customComponent: ReactElement } => {
}): {
id: string;
items: TagType[];
customComponent: ReactElement;
label?: 'string';
icon?: string;
} => {
const tagItem = reduce(
tags,
(acc, v) => {
Expand All @@ -412,6 +418,8 @@ export const applyTag = ({
return {
id: TagsActionsType.Apply,
items: tagItem,
label: t('label.tag', 'Tag'),
icon: 'TagsMoreOutline',
customComponent: (
<Row takeAvailableSpace mainAlignment="flex-start">
<Padding right="small">
Expand Down
3 changes: 1 addition & 2 deletions src/views/app/detail-panel/edit/edit-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,7 @@ export default function EditView({ mailId, folderId, setHeader, toggleAppBoard }
messages,
saveDraftCb,
settings,
t,
throttledSaveToDraft
t
]);

useEffect(() => {
Expand Down
6 changes: 3 additions & 3 deletions src/views/app/detail-panel/preview/attachments-block.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function Attachment({ filename, size, link, message, part, iconColors, att }) {
[att.name, createSnackbar, message.id, t]
);

const isAValidDestination = useMemo((node) => node.permissions?.can_write_file, []);
const isAValidDestination = useMemo((node) => node?.permissions?.can_write_file, []);

const actionTarget = useMemo(
() => ({
Expand Down Expand Up @@ -265,7 +265,7 @@ const copyToFiles = (att, message, nodes) =>
_jsns: 'urn:zimbraMail',
mid: message.id,
part: att.name,
destinationFolderId: nodes[0].id
destinationFolderId: nodes?.[0]?.id
});

export default function AttachmentsBlock({ message }) {
Expand Down Expand Up @@ -343,7 +343,7 @@ export default function AttachmentsBlock({ message }) {
[attachments, createSnackbar, message, t]
);

const isAValidDestination = useMemo((node) => node.permissions?.can_write_file, []);
const isAValidDestination = useMemo((node) => node?.permissions?.can_write_file, []);

const actionTarget = useMemo(
() => ({
Expand Down
29 changes: 28 additions & 1 deletion src/views/app/detail-panel/preview/parts/preview-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ import {
} from '@zextras/carbonio-design-system';
import { capitalize, every, find, includes, isEmpty, map, reduce } from 'lodash';
import { useTranslation } from 'react-i18next';
import { useTags, useUserAccounts, ZIMBRA_STANDARD_COLORS } from '@zextras/carbonio-shell-ui';
import {
useTags,
useUserAccounts,
ZIMBRA_STANDARD_COLORS,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
runSearch
} from '@zextras/carbonio-shell-ui';
import { useParams } from 'react-router-dom';
import OnBehalfOfDisplayer from './on-behalf-of-displayer';
import MailMsgPreviewActions from '../../../../../ui-actions/mail-message-preview-actions';
Expand Down Expand Up @@ -162,6 +169,25 @@ const PreviewHeader: FC<PreviewHeaderProps> = ({ compProps }): ReactElement => {
every(message.tags, (tn) => tn !== ''),
[isTagInStore, message.tags, showMultiTagIcon]
);
const triggerSearch = useCallback(
(tagToSearch) =>
runSearch(
[
{
avatarBackground: tagToSearch?.color,
avatarIcon: 'Tag',
background: 'gray2',
hasAvatar: true,
isGeneric: false,
isQueryFilter: true,
label: `tag:${tagToSearch?.name}`,
value: `tag:"${tagToSearch?.name}"`
}
],
'mails'
),
[]
);

return (
<HoverContainer
Expand Down Expand Up @@ -294,6 +320,7 @@ const PreviewHeader: FC<PreviewHeaderProps> = ({ compProps }): ReactElement => {
background="gray2"
hasAvatar
avatarIcon="Tag"
onClick={(): void => triggerSearch(tag)}
/>
))}
</Text>
Expand Down
2 changes: 2 additions & 0 deletions src/views/app/detail-panel/preview/preview-panel-actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export default function PreviewPanelActions({ item, folderId, isMessageView, con
{map(primaryActions, (action) => (
<Padding left="extrasmall" key={action.label}>
<IconButton
key={action.id}
size="medium"
icon={action.icon}
onClick={(ev) => {
Expand All @@ -137,6 +138,7 @@ export default function PreviewPanelActions({ item, folderId, isMessageView, con
/>
</Padding>
))}

<Padding left="extrasmall">
<Dropdown
placement="right-end"
Expand Down
42 changes: 21 additions & 21 deletions src/views/search/advance-filter-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,77 +107,77 @@ const AdvancedFilterModal: FC<AdvancedFilterModalProps> = ({
query,
(v) =>
!includes(queryArray, v.label) &&
!/^Subject:*/.test(v.label) &&
!/^Attachment:*/.test(v.label) &&
!/^Is:*/.test(v.label) &&
!/^Smaller:*/.test(v.label) &&
!/^Larger:*/.test(v.label) &&
!/^subject:*/.test(v.label) &&
!/^in:*/.test(v.label) &&
!/^before:*/.test(v.label) &&
!/^after:*/.test(v.label) &&
!/^date:*/.test(v.label) &&
!/^tag:*/.test(v.label) &&
!/^Subject:/.test(v.label) &&
!/^Attachment:/.test(v.label) &&
!/^Is:/.test(v.label) &&
!/^Smaller:/.test(v.label) &&
!/^Larger:/.test(v.label) &&
!/^subject:/.test(v.label) &&
!/^in:/.test(v.label) &&
!/^before:/.test(v.label) &&
!/^after:/.test(v.label) &&
!/^date:/.test(v.label) &&
!/^tag:/.test(v.label) &&
!v.isQueryFilter
),
(q) => ({ ...q, hasAvatar: false })
);

const subjectsFromQuery = map(
filter(query, (v) => /^Subject:*/.test(v.label)),
filter(query, (v) => /^Subject:/.test(v.label)),
(q) => ({ ...q, hasAvatar: false })
);
setSubject(subjectsFromQuery);

const attachmentTypeFromQuery = map(
filter(query, (v) => /^Attachment:*/.test(v.label)),
filter(query, (v) => /^Attachment:/.test(v.label)),
(q) => ({ ...q })
);
setAttachmentType(attachmentTypeFromQuery);

const emailStatusFromQuery = map(
filter(query, (v) => /^Is:*/.test(v.label)),
filter(query, (v) => /^Is:/.test(v.label)),
(q) => ({ ...q })
);
setEmailStatus(emailStatusFromQuery);

const sizeSmallerFromQuery = map(
filter(query, (v) => /^Smaller:*/.test(v.label)),
filter(query, (v) => /^Smaller:/.test(v.label)),
(q) => ({ ...q })
);
setSizeSmaller(sizeSmallerFromQuery);

const sizeLargerFromQuery = map(
filter(query, (v) => /^Larger:*/.test(v.label)),
filter(query, (v) => /^Larger:/.test(v.label)),
(q) => ({ ...q })
);
setSizeLarger(sizeLargerFromQuery);
const sentBeforeFromQuery = map(
filter(query, (v) => /^before:*/.test(v.label)),
filter(query, (v) => /^before:/.test(v.label)),
(q) => ({ ...q, hasAvatar: true, icon: 'CalendarOutline' })
);
setSentBefore(sentBeforeFromQuery);

const sentAfterFromQuery = map(
filter(query, (v) => /^after:*/.test(v.label)),
filter(query, (v) => /^after:/.test(v.label)),
(q) => ({ ...q, hasAvatar: true, icon: 'CalendarOutline' })
);
setSentAfter(sentAfterFromQuery);

const tagFromQuery = map(
filter(query, (v) => /^tag:*/.test(v.label)),
filter(query, (v) => /^tag:/.test(v.label)),
(q) => ({ ...q, hasAvatar: true, icon: 'TagOutline' })
);
setTag(tagFromQuery);

const sentOnFromQuery = map(
filter(query, (v) => /^date:*/.test(v.label)),
filter(query, (v) => /^date:/.test(v.label)),
(q) => ({ ...q, hasAvatar: true, icon: 'CalendarOutline' })
);
setSentOn(sentOnFromQuery);

const folderFromQuery = map(
filter(query, (v) => /^in:*/.test(v.label)),
filter(query, (v) => /^in:/.test(v.label)),
(q) => ({
...q,
hasAvatar: true,
Expand Down
12 changes: 6 additions & 6 deletions src/views/search/search-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,12 @@ const SearchView: FC<SearchProps> = ({ useDisableSearch, useQuery, ResultsHeader
const modifiedQuery = map(query, (q) => {
if (
(includes(queryArray, q.label) ||
/^subject:*/.test(q.label) ||
/^in:*/.test(q.label) ||
/^before:*/.test(q.label) ||
/^after:*/.test(q.label) ||
/^tag:*/.test(q.label) ||
/^date:*/.test(q.label)) &&
/^subject:/.test(q.label) ||
/^in:/.test(q.label) ||
/^before:/.test(q.label) ||
/^after:/.test(q.label) ||
/^tag:/.test(q.label) ||
/^date:/.test(q.label)) &&
!includes(Object.keys(q), 'isGeneric') &&
!includes(Object.keys(q), 'isQueryFilter')
) {
Expand Down

0 comments on commit 83cd3f7

Please sign in to comment.