Merge pull request #1089 from ONLYOFFICE/feature/info-panel-history-update

info-panel-history-update
This commit is contained in:
Alexey Safronov 2022-11-30 18:03:14 +03:00 committed by GitHub
commit ca83c9f80d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 203 additions and 102 deletions

View File

@ -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");
};

View File

@ -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();
}
}
};

View File

@ -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 &&

View File

@ -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;

View File

@ -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;

View File

@ -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>
</>
);

View File

@ -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;
};

View File

@ -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"
}

View File

@ -175,6 +175,7 @@
"NoTags": "Нет тэгов",
"Title": "Заголовок",
"TitleSelectFile": "Выделить",
"Today": "Сегодня",
"Type": "Тип",
"Terabyte": "Тб",
"Unknown": "Неизвестный",
@ -191,6 +192,7 @@
"AboutCompanyTitle": "О программе",
"LogoutButton": "Выйти",
"HelpCenter": "Справочный центр",
"Yesterday": "Вчера",
"SelectFile": "Выбрать файл",
"HideArticleMenu": "Скрыть меню"
}