Skip to content

Commit

Permalink
Feat/#485 files menu option - sidebar (#491)
Browse files Browse the repository at this point in the history
* add-rest-api-endpoint

* menu-option-ui

* files-menu-sidebar-ui

* menu-sidebar-components

* finalize-code

* format-fixes

* api-change/linting+format-fix

* format-fix

* revert-lint-changes
  • Loading branch information
umangutkarsh authored Mar 12, 2024
1 parent 27108f4 commit 5fa3ed1
Show file tree
Hide file tree
Showing 20 changed files with 492 additions and 11 deletions.
21 changes: 21 additions & 0 deletions packages/api/src/EmbeddedChatApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,27 @@ export default class EmbeddedChatApi {
}
}

async getAllFiles(isChannelPrivate = false) {
const roomType = isChannelPrivate ? "groups" : "channels";
try {
const { userId, authToken } = (await this.auth.getCurrentUser()) || {};
const response = await fetch(
`${this.host}/api/v1/${roomType}.files?roomId=${this.rid}`,
{
headers: {
"Content-Type": "application/json",
"X-Auth-Token": authToken,
"X-User-Id": userId,
},
method: "GET",
}
);
return await response.json();
} catch (err) {
console.error(err);
}
}

async starMessage(mid: string) {
try {
const { userId, authToken } = (await this.auth.getCurrentUser()) || {};
Expand Down
14 changes: 14 additions & 0 deletions packages/react/src/components/ChatHeader/ChatHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
useToastStore,
useThreadsMessageStore,
useMentionsStore,
useFileStore,
} from '../../store';
import { DynamicHeader } from '../DynamicHeader';
import { Tooltip } from '../Tooltip';
Expand Down Expand Up @@ -74,6 +75,7 @@ const ChatHeader = ({
const setShowAllThreads = useThreadsMessageStore(
(state) => state.setShowAllThreads
);
const setShowAllFiles = useFileStore((state) => state.setShowAllFiles);
const setShowMentions = useMentionsStore((state) => state.setShowMentions);
const toastPosition = useToastStore((state) => state.position);

Expand Down Expand Up @@ -143,6 +145,11 @@ const ChatHeader = ({
setShowSearch(false);
}, [setShowAllThreads, setShowSearch]);

const showAllFiles = useCallback(async () => {
setShowAllFiles(true);
setShowSearch(false);
}, [setShowAllFiles, setShowSearch]);

const showMentions = useCallback(async () => {
setShowMentions(true);
setShowSearch(false);
Expand Down Expand Up @@ -242,6 +249,12 @@ const ChatHeader = ({
label: 'Members',
icon: 'members',
},
{
id: 'files',
action: showAllFiles,
label: 'Files',
icon: 'clip',
},
{
id: 'starred',
action: showStarredMessage,
Expand Down Expand Up @@ -285,6 +298,7 @@ const ChatHeader = ({
isUserAuthenticated,
moreOpts,
setFullScreen,
showAllFiles,
showAllThreads,
showMentions,
showChannelMembers,
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/EmbeddedChat.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const EmbeddedChat = ({
useEffect(() => {
setToastbarPosition(toastBarPosition);
setShowAvatar(showAvatar);
}, [toastBarPosition, showAvatar]);
}, [toastBarPosition, showAvatar, setShowAvatar, setToastbarPosition]);

const {
onDrag,
Expand Down
61 changes: 61 additions & 0 deletions packages/react/src/components/Files/FileMetrics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import { css } from '@emotion/react';
import { formatDistance } from 'date-fns';
import useComponentOverrides from '../../theme/useComponentOverrides';
import { Box } from '../Box';
import { appendClassNames } from '../../lib/appendClassNames';
import { Icon } from '../Icon';

const FileMetricsCss = css`
display: flex;
margin-left: -0.25rem;
margin-right: -0.25rem;
margin-inline: -0.25rem;
margin-top: 0.5rem;
`;

const FileMetricsItemCss = css`
letter-spacing: 0rem;
font-size: 0.625rem;
font-weight: 700;
line-height: 0.75rem;
display: flex;
justify-content: center;
align-items: center;
margin-left: 0.25rem;
color: #6c727a;
`;

const FileMetricsItemLabelCss = css`
margin: 0.25rem;
margin-inline-start: 0.25rem;
white-space: nowrap;
`;

export const FileMetrics = ({ className = '', file, style = {}, ...props }) => {
const { styleOverrides, classNames } = useComponentOverrides(
'MessageMetrics',
className,
style
);
return (
<Box
css={FileMetricsCss}
className={appendClassNames('ec-message-metrics', classNames)}
style={styleOverrides}
{...props}
>
<div
css={FileMetricsItemCss}
title={new Date(file.uploadedAt).toLocaleString()}
>
<Icon size="1.25rem" name="clock" />
<div css={FileMetricsItemLabelCss}>
{formatDistance(new Date(file.uploadedAt), new Date(), {
addSuffix: true,
})}
</div>
</div>
</Box>
);
};
27 changes: 27 additions & 0 deletions packages/react/src/components/Files/FilePreviewContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { css } from '@emotion/react';
import { Avatar } from '../Avatar';
import { Box } from '../Box';
import { Icon } from '../Icon';

const FilePreviewContainer = ({ file, sequential, isStarred }) => {
const FilePreviewContainerCss = css`
margin: 3px;
width: 2.25em;
max-height: 2.25em;
display: flex;
justify-content: flex-end;
`;

return (
<Box css={FilePreviewContainerCss}>
{!sequential ? (
<Avatar url={file.url} alt="file" size="2.25em" />
) : isStarred ? (
<Icon style={{ opacity: 0.5 }} name="star-filled" size="1.2em" />
) : null}
</Box>
);
};

export default FilePreviewContainer;
96 changes: 96 additions & 0 deletions packages/react/src/components/Files/FilePreviewHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';
import PropTypes from 'prop-types';
import { css } from '@emotion/react';
import { format } from 'date-fns';
import { useUserStore } from '../../store';
import { Icon } from '../Icon';
import useComponentOverrides from '../../theme/useComponentOverrides';
import { Box } from '../Box';
import { appendClassNames } from '../../lib/appendClassNames';

const FilePreviewHeaderCss = css`
display: flex;
overflow-x: hidden;
flex-direction: row;
flex-grow: 0;
flex-shrink: 1;
min-width: 1px;
padding-right: 3px;
margin-top: 0.125rem;
margin-bottom: 0.125rem;
margin-block: 0.125rem;
gap: 0.125rem;
align-items: center;
max-width: 85%;
`;

const FilePreviewHeaderNameCss = css`
letter-spacing: 0rem;
display: inline-block;
font-size: 0.875rem;
font-weight: 700;
line-height: 1.25rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex-shrink: 1;
color: #2f343d;
`;

const FilePreviewHeaderTimestapCss = css`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
letter-spacing: 0rem;
font-size: 0.75rem;
font-weight: 400;
line-height: 1rem;
flex-shrink: 0;
color: #9ea2a8;
`;

const FilePreviewHeader = ({ file, isTimeStamped = true }) => {
const { styleOverrides, classNames } = useComponentOverrides('MessageHeader');
const authenticatedUserId = useUserStore((state) => state.userId);
const isStarred =
file.starred && file.starred.find((u) => u._id === authenticatedUserId);

return (
<Box
css={FilePreviewHeaderCss}
className={appendClassNames('ec-file-header', classNames)}
style={styleOverrides}
>
<Box
is="span"
css={FilePreviewHeaderNameCss}
className={appendClassNames('ec-file-header-name')}
>
{file.name}
</Box>

{isTimeStamped && (
<Box
is="span"
css={FilePreviewHeaderTimestapCss}
className={appendClassNames('ec-file-header-timestamp')}
>
{format(new Date(file.ts), 'h:mm a')}
</Box>
)}
{isStarred ? (
<Icon
style={{ marginInlineEnd: '0.4rem', opacity: 0.5 }}
name="star-filled"
size="1em"
/>
) : null}
</Box>
);
};

export default FilePreviewHeader;

FilePreviewHeader.propTypes = {
file: PropTypes.any,
};
Loading

0 comments on commit 5fa3ed1

Please sign in to comment.