Merge pull request #1089 from ONLYOFFICE/feature/info-panel-history-update
info-panel-history-update
This commit is contained in:
commit
ca83c9f80d
@ -0,0 +1,37 @@
|
||||
import moment from "moment";
|
||||
|
||||
import { LANGUAGE } from "@docspace/common/constants";
|
||||
import { getCookie } from "@docspace/common/utils";
|
||||
|
||||
export const getRelativeDateDay = (t, date) => {
|
||||
moment.locale(getCookie(LANGUAGE));
|
||||
|
||||
const given = moment(date);
|
||||
|
||||
const now = moment();
|
||||
const weekAgo = moment().subtract(1, "week");
|
||||
const halfYearAgo = moment().subtract(6, "month");
|
||||
|
||||
if (given.isAfter(weekAgo)) {
|
||||
if (now.weekday() === given.weekday()) return t("Common:Today");
|
||||
if (now.weekday() - 1 === given.weekday()) return t("Common:Yesterday");
|
||||
|
||||
const weekday = moment.weekdays(given.weekday());
|
||||
return weekday.charAt(0).toUpperCase() + weekday.slice(1);
|
||||
}
|
||||
|
||||
if (given.isBetween(halfYearAgo, weekAgo)) {
|
||||
const shortDate = given.format("MMMM D");
|
||||
return shortDate.charAt(0).toUpperCase() + shortDate.slice(1);
|
||||
}
|
||||
|
||||
const longDate = given.format("MMMM D, YYYY");
|
||||
return longDate.charAt(0).toUpperCase() + longDate.slice(1);
|
||||
};
|
||||
|
||||
export const getDateTime = (date) => {
|
||||
moment.locale(getCookie(LANGUAGE));
|
||||
|
||||
const given = moment(date);
|
||||
return given.format("LT");
|
||||
};
|
@ -69,15 +69,12 @@ const InfoPanelBodyContent = ({
|
||||
if (isAccounts) return viewHelper.AccountsView();
|
||||
|
||||
switch (isRooms ? roomsView : fileView) {
|
||||
case "info_members": {
|
||||
case "info_members":
|
||||
return viewHelper.MembersView();
|
||||
}
|
||||
case "info_history": {
|
||||
case "info_history":
|
||||
return viewHelper.HistoryView();
|
||||
}
|
||||
case "info_details": {
|
||||
case "info_details":
|
||||
return viewHelper.DetailsView();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4,9 +4,9 @@ import { Base } from "@docspace/components/themes";
|
||||
import { mobile } from "@docspace/components/utils/device";
|
||||
|
||||
const StyledInfoPanelBody = styled.div`
|
||||
padding: 0 3px 0 20px;
|
||||
padding: 80px 3px 0 20px;
|
||||
@media ${mobile} {
|
||||
padding: 0 8px 0 16px;
|
||||
padding: 80px 8px 0 16px;
|
||||
}
|
||||
height: auto;
|
||||
background-color: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
@ -26,13 +26,24 @@ const StyledInfoPanelBody = styled.div`
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
position: fixed;
|
||||
margin-top: -80px;
|
||||
margin-left: -20px;
|
||||
width: calc(100% - 40px);
|
||||
padding: 24px 0 24px 20px;
|
||||
background: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
z-index: 100;
|
||||
|
||||
@media ${mobile} {
|
||||
width: calc(100% - 32px);
|
||||
padding: 24px 0 24px 16px;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-wrap: no-wrap;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 24px 0;
|
||||
|
||||
${(props) =>
|
||||
props.withBottomBorder &&
|
||||
|
@ -9,6 +9,11 @@ const StyledHistoryList = styled.div`
|
||||
`;
|
||||
|
||||
const StyledHistorySubtitle = styled.div`
|
||||
position: sticky;
|
||||
background: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
top: 80px;
|
||||
z-index: 100;
|
||||
|
||||
padding: 8px 0 12px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
@ -46,7 +51,11 @@ const StyledHistoryBlock = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 16px 0;
|
||||
border-bottom: ${(props) => `solid 1px ${props.theme.infoPanel.borderColor}`};
|
||||
|
||||
${({ withBottomDivider, theme }) =>
|
||||
withBottomDivider
|
||||
? ` border-bottom: solid 1px ${theme.infoPanel.borderColor}; `
|
||||
: ` margin-bottom: 12px; `}
|
||||
|
||||
.avatar {
|
||||
min-width: 32px;
|
||||
|
@ -0,0 +1,93 @@
|
||||
import React from "react";
|
||||
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Text from "@docspace/components/text";
|
||||
import HistoryBlockMessage from "./HistoryBlockMessage";
|
||||
import HistoryBlockItemList from "./HistoryBlockItemList";
|
||||
import HistoryBlockUser from "./HistoryBlockUser";
|
||||
import { FeedItemTypes } from "@docspace/common/constants";
|
||||
|
||||
import { StyledHistoryBlock } from "../../styles/history";
|
||||
import { getDateTime } from "../../helpers/HistoryHelper";
|
||||
|
||||
const HistoryBlock = ({
|
||||
t,
|
||||
selection,
|
||||
feed,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
getInfoPanelItemIcon,
|
||||
checkAndOpenLocationAction,
|
||||
openUser,
|
||||
isVisitor,
|
||||
isLastEntity,
|
||||
}) => {
|
||||
const { target, initiator, json, groupedFeeds } = feed;
|
||||
|
||||
const isUserAction = json.Item === FeedItemTypes.User && target;
|
||||
const isItemAction =
|
||||
json.Item === FeedItemTypes.File || json.Item === FeedItemTypes.Folder;
|
||||
|
||||
return (
|
||||
<StyledHistoryBlock
|
||||
withBottomDivider={!isLastEntity}
|
||||
isUserAction={isUserAction}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
initiator.avatarSmall ||
|
||||
(initiator.displayName
|
||||
? ""
|
||||
: initiator.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={initiator.displayName}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<Text className="name">{initiator.displayName}</Text>
|
||||
{initiator.isOwner && (
|
||||
<Text className="secondary-info">
|
||||
{t("Common:Owner").toLowerCase()}
|
||||
</Text>
|
||||
)}
|
||||
<Text className="date">{getDateTime(json.ModifiedDate)}</Text>
|
||||
</div>
|
||||
|
||||
<HistoryBlockMessage
|
||||
t={t}
|
||||
className="message"
|
||||
action={json}
|
||||
groupedActions={groupedFeeds}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
/>
|
||||
|
||||
{isItemAction && (
|
||||
<HistoryBlockItemList
|
||||
t={t}
|
||||
items={[json, ...groupedFeeds]}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isUserAction &&
|
||||
[target, ...groupedFeeds].map((user, i) => (
|
||||
<HistoryBlockUser
|
||||
isVisitor={isVisitor}
|
||||
key={user.id}
|
||||
user={user}
|
||||
withComma={i !== groupedFeeds.length}
|
||||
openUser={openUser}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</StyledHistoryBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default HistoryBlock;
|
@ -2,25 +2,14 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
StyledHistoryBlock,
|
||||
StyledHistoryList,
|
||||
StyledHistorySubtitle,
|
||||
} from "../../styles/history";
|
||||
import { StyledHistoryList, StyledHistorySubtitle } from "../../styles/history";
|
||||
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Text from "@docspace/components/text";
|
||||
import { parseAndFormatDate } from "../../helpers/DetailsHelper";
|
||||
import HistoryBlockMessage from "./HistoryBlockMessage";
|
||||
import HistoryBlockItemList from "./HistoryBlockItemList";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import HistoryBlockUser from "./HistoryBlockUser";
|
||||
import { FeedItemTypes } from "@docspace/common/constants";
|
||||
import { getRelativeDateDay } from "./../../helpers/HistoryHelper";
|
||||
import HistoryBlock from "./HistoryBlock";
|
||||
|
||||
const History = ({
|
||||
t,
|
||||
personal,
|
||||
culture,
|
||||
selection,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
@ -59,9 +48,11 @@ const History = ({
|
||||
|
||||
const parseHistoryJSON = (fetchedHistory) => {
|
||||
let feeds = fetchedHistory.feeds;
|
||||
let newFeeds = [];
|
||||
let parsedFeeds = [];
|
||||
|
||||
for (let i = 0; i < feeds.length; i++) {
|
||||
const feedsJSON = JSON.parse(feeds[i].json);
|
||||
const feedDay = getRelativeDateDay(t, feeds[i].modifiedDate);
|
||||
|
||||
let newGroupedFeeds = [];
|
||||
if (feeds[i].groupedFeeds) {
|
||||
@ -74,14 +65,26 @@ const History = ({
|
||||
);
|
||||
}
|
||||
|
||||
newFeeds.push({
|
||||
...feeds[i],
|
||||
json: feedsJSON,
|
||||
groupedFeeds: newGroupedFeeds,
|
||||
});
|
||||
if (parsedFeeds.length && parsedFeeds.at(-1).day === feedDay)
|
||||
parsedFeeds.at(-1).feeds.push({
|
||||
...feeds[i],
|
||||
json: feedsJSON,
|
||||
groupedFeeds: newGroupedFeeds,
|
||||
});
|
||||
else
|
||||
parsedFeeds.push({
|
||||
day: feedDay,
|
||||
feeds: [
|
||||
{
|
||||
...feeds[i],
|
||||
json: feedsJSON,
|
||||
groupedFeeds: newGroupedFeeds,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return { ...fetchedHistory, feeds: newFeeds };
|
||||
return { ...fetchedHistory, feedsByDays: parsedFeeds };
|
||||
};
|
||||
|
||||
useEffect(async () => {
|
||||
@ -101,76 +104,24 @@ const History = ({
|
||||
return (
|
||||
<>
|
||||
<StyledHistoryList>
|
||||
<StyledHistorySubtitle>{t("RecentActivities")}</StyledHistorySubtitle>
|
||||
|
||||
{history.feeds.map((feed) => (
|
||||
<StyledHistoryBlock
|
||||
key={feed.json.Id}
|
||||
isUserAction={feed.json.Item === FeedItemTypes.User && feed.target}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
feed.initiator.avatarSmall ||
|
||||
(feed.initiator.displayName
|
||||
? ""
|
||||
: feed.initiator.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={feed.initiator.displayName}
|
||||
{history.feedsByDays.map(({ day, feeds }) => [
|
||||
<StyledHistorySubtitle key={day}>{day}</StyledHistorySubtitle>,
|
||||
...feeds.map((feed, i) => (
|
||||
<HistoryBlock
|
||||
key={feed.json.Id}
|
||||
t={t}
|
||||
feed={feed}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
openUser={openUser}
|
||||
isVisitor={isVisitor}
|
||||
isLastEntity={i === feeds.length - 1}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<Text className="name">{feed.initiator.displayName}</Text>
|
||||
{feed.initiator.isOwner && (
|
||||
<Text className="secondary-info">
|
||||
{t("Common:Owner").toLowerCase()}
|
||||
</Text>
|
||||
)}
|
||||
<Text className="date">
|
||||
{parseAndFormatDate(
|
||||
feed.json.ModifiedDate,
|
||||
personal,
|
||||
culture
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<HistoryBlockMessage
|
||||
t={t}
|
||||
className="message"
|
||||
action={feed.json}
|
||||
groupedActions={feed.groupedFeeds}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
/>
|
||||
|
||||
{(feed.json.Item === FeedItemTypes.File ||
|
||||
feed.json.Item === FeedItemTypes.Folder) && (
|
||||
<HistoryBlockItemList
|
||||
t={t}
|
||||
items={[feed.json, ...feed.groupedFeeds]}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{feed.json.Item === FeedItemTypes.User &&
|
||||
feed.target &&
|
||||
[feed.target, ...feed.groupedFeeds].map((user, i) => (
|
||||
<HistoryBlockUser
|
||||
isVisitor={isVisitor}
|
||||
key={user.id}
|
||||
user={user}
|
||||
withComma={i !== feed.groupedFeeds.length}
|
||||
openUser={openUser}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</StyledHistoryBlock>
|
||||
))}
|
||||
)),
|
||||
])}
|
||||
</StyledHistoryList>
|
||||
</>
|
||||
);
|
||||
|
@ -1072,7 +1072,6 @@ class FilesActionStore {
|
||||
openLocationAction = async (locationId) => {
|
||||
this.filesStore.setBufferSelection(null);
|
||||
const files = await this.filesStore.fetchFiles(locationId, null);
|
||||
console.log(files);
|
||||
return files;
|
||||
};
|
||||
|
||||
|
@ -194,6 +194,7 @@
|
||||
"NoTags": "No tags",
|
||||
"Title": "Title",
|
||||
"TitleSelectFile": "Select",
|
||||
"Today": "Today",
|
||||
"Type": "Type",
|
||||
"Terabyte": "TB",
|
||||
"Unknown": "Unknown",
|
||||
@ -214,6 +215,7 @@
|
||||
"HelpCenter": "Help center",
|
||||
"FeedbackAndSupport": "Feedback & Support",
|
||||
"VideoGuides": "Video Guides",
|
||||
"Yesterday": "Yesterday",
|
||||
"SelectFile": "Select file",
|
||||
"HideArticleMenu": "Hide menu"
|
||||
}
|
||||
|
@ -175,6 +175,7 @@
|
||||
"NoTags": "Нет тэгов",
|
||||
"Title": "Заголовок",
|
||||
"TitleSelectFile": "Выделить",
|
||||
"Today": "Сегодня",
|
||||
"Type": "Тип",
|
||||
"Terabyte": "Тб",
|
||||
"Unknown": "Неизвестный",
|
||||
@ -191,6 +192,7 @@
|
||||
"AboutCompanyTitle": "О программе",
|
||||
"LogoutButton": "Выйти",
|
||||
"HelpCenter": "Справочный центр",
|
||||
"Yesterday": "Вчера",
|
||||
"SelectFile": "Выбрать файл",
|
||||
"HideArticleMenu": "Скрыть меню"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user