Compare commits
30 Commits
master
...
feature/vd
Author | SHA1 | Date | |
---|---|---|---|
b6d67adc3a | |||
6ab5d32801 | |||
94ad3b879f | |||
bcba14cc8a | |||
5174a80282 | |||
0471b801ec | |||
8c4e888350 | |||
a88958efbb | |||
5a166b1c58 | |||
de668ed15e | |||
04368e7953 | |||
da02a34b89 | |||
df56be32e6 | |||
ec75beee04 | |||
e125c70d65 | |||
365a756dfd | |||
0eba7d8c22 | |||
88e39b44b6 | |||
98d7a86a0a | |||
f720d08874 | |||
be63e1be5b | |||
|
54df145654 | ||
f537c7baf6 | |||
|
6ed7eacf8c | ||
be954b594c | |||
7a3cb28683 | |||
920e634322 | |||
3ab8e3972c | |||
e92b3b1485 | |||
a508444e6e |
@ -16,6 +16,7 @@
|
||||
"MakeRoomPrivateTitle": "Make the Room Private",
|
||||
"PublicRoomBarDescription": "This room is available to anyone with the link. External users will have View Only permission for all the files.",
|
||||
"PublicRoomDescription": "Invite users via external links to view documents without registration. You can also embed this room into any web interface.",
|
||||
"VirtualDataRoomDescription": "Use VDR for advanced file security and transparency while filling and signing documents step-by-step. Set watermarks, automatically index and track all content, restrict downloading and copying.",
|
||||
"PublicRoomSystemFoldersDescription": "System folders store copies of forms at different stages of completion. Forms that are being filled are stored in In progress folder, and completed forms are stored in Complete folder.",
|
||||
"PublicRoomSystemFoldersTitle": "System Folders",
|
||||
"ReviewRoomDescription": "Request a review or comments on the documents",
|
||||
@ -29,5 +30,14 @@
|
||||
"ThirdPartyStoragePermanentSettingDescription": "Files are stored in a third-party {{thirdpartyTitle}} storage in the \"{{thirdpartyFolderName}}\" folder.\n<strong>{{thirdpartyPath}}</strong>",
|
||||
"ThirdPartyStorageRoomAdminNoStorageAlert": "To connect a third-party storage, you need to add the corresponding service in the Integration section of DocSpace settings. Contact DocSpace owner or administrator to enable the integration.",
|
||||
"ViewOnlyRoomDescription": "Share any ready documents, reports, documentation, and other files for viewing.",
|
||||
"ViewOnlyRoomTitle": "View-only room"
|
||||
"ViewOnlyRoomTitle": "View-only room",
|
||||
"AutomaticIndexing": "Automatic indexing",
|
||||
"AutomaticIndexingDescription": "Enable automatic indexing to index files and folders by serial number. Sorting by number will be set as default for all users.",
|
||||
"FileLifetime": "File lifetime",
|
||||
"FileLifetimeDescription": "Set file lifetime to automatically delete the files in this room after a defined period. Lifetime begins on the date of upload/creation of the file.",
|
||||
"RestrictCopyAndDownload": "Restrict copy and download",
|
||||
"RestrictCopyAndDownloadDescription": "Enable this setting to disable downloads and content copying for users with the \"{{role}}\" role.",
|
||||
"AddWatermarksToDocuments": "Add watermarks to documents",
|
||||
"AddWatermarksToDocumentsDescription": "Protect all documents in this room with watermarks. If a document already contains one, it will not be replaced.",
|
||||
"FilesOlderThan": "Files older than:"
|
||||
}
|
||||
|
@ -141,6 +141,7 @@
|
||||
"PrivateRoomHeader": "Welcome to ONLYOFFICE private room where every symbol you type is encrypted",
|
||||
"PrivateRoomSupport": "Work in Private Room is available via {{organizationName}} desktop app. <3>Instructions</3>",
|
||||
"PublicRoom": "Public room",
|
||||
"VirtualDataRoom": "Virtual Data Room",
|
||||
"RecentEmptyContainerDescription": "Your last viewed or edited docs will be displayed in this section.",
|
||||
"RecentlyAccessible": "Recently accessible via link",
|
||||
"RecentViaLinkEmptyContainerDescription": "Here you will find a list of the recently opened files shared with you via an external link.",
|
||||
|
@ -76,6 +76,7 @@ const EditRoomEvent = ({
|
||||
zoom: 1,
|
||||
},
|
||||
roomOwner: item.createdBy,
|
||||
indexing: item.indexing,
|
||||
};
|
||||
|
||||
const updateRoom = (oldRoom, newRoom) => {
|
||||
|
@ -76,6 +76,7 @@ const CreateRoomDialog = ({
|
||||
y: 0.5,
|
||||
zoom: 1,
|
||||
},
|
||||
indexing: false, // VDR Automatic indexing
|
||||
};
|
||||
|
||||
const [roomParams, setRoomParams] = useState({ ...startRoomParams });
|
||||
|
@ -39,7 +39,8 @@ const EditRoomDialog = ({
|
||||
currentParams.tags.map((t) => t.name).sort().join("|").toLowerCase() &&
|
||||
((prevParams.icon.uploadedFile === "" &&
|
||||
currentParams.icon.uploadedFile === null) ||
|
||||
prevParams.icon.uploadedFile === currentParams.icon.uploadedFile)
|
||||
prevParams.icon.uploadedFile === currentParams.icon.uploadedFile) &&
|
||||
prevParams.indexing === currentParams.indexing
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -14,6 +14,8 @@ export const getRoomTypeTitleTranslation = (roomType = 1, t) => {
|
||||
return t("CreateEditRoomDialog:CustomRoomTitle");
|
||||
case RoomsType.PublicRoom:
|
||||
return t("Files:PublicRoom");
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("Files:VirtualDataRoom");
|
||||
case RoomsType.FormRoom:
|
||||
return t("CreateEditRoomDialog:FormRoomTitle");
|
||||
}
|
||||
@ -33,6 +35,8 @@ export const getRoomTypeDescriptionTranslation = (roomType = 1, t) => {
|
||||
return t("CreateEditRoomDialog:CustomRoomDescription");
|
||||
case RoomsType.PublicRoom:
|
||||
return t("CreateEditRoomDialog:PublicRoomDescription");
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("CreateEditRoomDialog:VirtualDataRoomDescription");
|
||||
case RoomsType.FormRoom:
|
||||
return t("CreateEditRoomDialog:FormRoomDescription");
|
||||
}
|
||||
@ -52,6 +56,8 @@ export const getRoomTypeDefaultTagTranslation = (roomType = 1, t) => {
|
||||
return t("Files:CustomRooms");
|
||||
case RoomsType.PublicRoom:
|
||||
return t("Files:PublicRoom");
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("Files:VirtualDataRoom");
|
||||
case RoomsType.FormRoom:
|
||||
return t("Files:FormRoom");
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { mobile } from "@docspace/shared/utils/device";
|
||||
|
||||
const StyledFileLifetime = styled.div`
|
||||
margin-top: 12px;
|
||||
|
||||
.virtual-data-room_file-lifetime_body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@media ${mobile} {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.virtual-data-room_file-lifetime_date {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.virtual-data-room_file-lifetime_input {
|
||||
min-width: 150px;
|
||||
margin-right: 4px;
|
||||
|
||||
@media ${mobile} {
|
||||
margin-right: 8px;
|
||||
width: 165px;
|
||||
}
|
||||
}
|
||||
|
||||
.virtual-data-room_file-lifetime_combo-box {
|
||||
margin-right: 16px;
|
||||
width: 92px;
|
||||
min-width: 92px;
|
||||
|
||||
@media ${mobile} {
|
||||
margin-right: 0px;
|
||||
width: 165px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const FileLifetime = ({ t }) => {
|
||||
const dateOptions = [
|
||||
{
|
||||
key: 1,
|
||||
label: t("Common:Days"),
|
||||
"data-type": 1,
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: t("Common:Months"),
|
||||
"data-type": 2,
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
label: t("Common:Years"),
|
||||
"data-type": 3,
|
||||
},
|
||||
];
|
||||
|
||||
const deleteOptions = [
|
||||
{
|
||||
key: 1,
|
||||
label: t("Common:MoveToTrash"),
|
||||
"data-type": 1,
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
label: t("Common:DeletePermanently"),
|
||||
"data-type": 2,
|
||||
},
|
||||
];
|
||||
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [selectedDate, setSelectedDate] = useState(dateOptions[0]);
|
||||
const [selectedDelete, setSelectedDelete] = useState(deleteOptions[0]);
|
||||
|
||||
const onChange = (e) => {
|
||||
// /^(?:[1-9][0-9]*|0)$/
|
||||
if (e.target.value && !/^(?:[1-9][0-9]*)$/.test(e.target.value)) return;
|
||||
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
const isLoading = false;
|
||||
|
||||
const onSelectDate = (option) => {
|
||||
setSelectedDate(option);
|
||||
console.log("onDateSelect", option);
|
||||
};
|
||||
|
||||
const onSelectDelete = (option) => {
|
||||
setSelectedDelete(option);
|
||||
console.log("onSelectDelete", option);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledFileLifetime className="virtual-data-room_file-lifetime">
|
||||
<Text fontWeight={600} fontSize="13px">
|
||||
{t("FilesOlderThan")}
|
||||
</Text>
|
||||
|
||||
<div className="virtual-data-room_file-lifetime_body">
|
||||
<div className="virtual-data-room_file-lifetime_date">
|
||||
<TextInput
|
||||
className="virtual-data-room_file-lifetime_input"
|
||||
isAutoFocussed={true}
|
||||
isDisabled={isLoading}
|
||||
tabIndex={1}
|
||||
value={inputValue}
|
||||
onChange={onChange}
|
||||
scale
|
||||
/>
|
||||
<ComboBox
|
||||
className="virtual-data-room_file-lifetime_combo-box"
|
||||
options={dateOptions}
|
||||
isDisabled={isLoading}
|
||||
showDisabledItems
|
||||
selectedOption={selectedDate}
|
||||
scaledOptions={true}
|
||||
onSelect={onSelectDate}
|
||||
/>
|
||||
</div>
|
||||
<ComboBox
|
||||
options={deleteOptions}
|
||||
isDisabled={isLoading}
|
||||
showDisabledItems
|
||||
selectedOption={selectedDelete}
|
||||
scale
|
||||
onSelect={onSelectDelete}
|
||||
/>
|
||||
</div>
|
||||
</StyledFileLifetime>
|
||||
);
|
||||
};
|
||||
|
||||
export default FileLifetime;
|
@ -19,7 +19,7 @@ import { getRoomTypeDefaultTagTranslation } from "../data";
|
||||
import { ImageEditor } from "@docspace/shared/components/image-editor";
|
||||
import PreviewTile from "@docspace/shared/components/image-editor/PreviewTile";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import VirtualDataRoomBlock from "./VirtualDataRoomBlock";
|
||||
import SystemFolders from "./SystemFolders";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
|
||||
@ -64,6 +64,8 @@ const SetRoomParams = ({
|
||||
}) => {
|
||||
const [previewIcon, setPreviewIcon] = React.useState(null);
|
||||
|
||||
const isVDRRoom = roomParams.type === RoomsType.VirtualDataRoom;
|
||||
|
||||
const isFormRoom = roomParams.type === RoomsType.FormRoom;
|
||||
|
||||
const onChangeName = (e) => {
|
||||
@ -155,6 +157,14 @@ const SetRoomParams = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
{isVDRRoom && (
|
||||
<VirtualDataRoomBlock
|
||||
t={t}
|
||||
roomParams={roomParams}
|
||||
setRoomParams={setRoomParams}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isEdit && enableThirdParty && (
|
||||
<ThirdPartyStorage
|
||||
t={t}
|
||||
|
@ -0,0 +1,131 @@
|
||||
import { useState } from "react";
|
||||
import { Trans } from "react-i18next";
|
||||
import styled from "styled-components";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { ToggleButton } from "@docspace/shared/components/toggle-button";
|
||||
import FileLifetime from "./FileLifetime";
|
||||
|
||||
const StyledVirtualDataRoomBlock = styled.div`
|
||||
.virtual-data-room-block {
|
||||
margin-bottom: 18px;
|
||||
:last-child {
|
||||
margin-bottom: -26px;
|
||||
}
|
||||
|
||||
.virtual-data-room-block_header {
|
||||
display: flex;
|
||||
|
||||
.virtual-data-room-block_toggle {
|
||||
margin-left: auto;
|
||||
margin-right: 28px;
|
||||
}
|
||||
}
|
||||
.virtual-data-room-block_description {
|
||||
max-width: 420px;
|
||||
margin-right: 28px;
|
||||
|
||||
color: ${({ theme }) => theme.editLink.text.color};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Block = ({
|
||||
headerText,
|
||||
bodyText,
|
||||
onChange,
|
||||
isDisabled,
|
||||
isChecked,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className="virtual-data-room-block">
|
||||
<div className="virtual-data-room-block_header">
|
||||
<Text fontWeight={600} fontSize="13px">
|
||||
{headerText}
|
||||
</Text>
|
||||
<ToggleButton
|
||||
isDisabled={isDisabled}
|
||||
isChecked={isChecked}
|
||||
onChange={onChange}
|
||||
className="virtual-data-room-block_toggle"
|
||||
/>
|
||||
</div>
|
||||
<Text
|
||||
fontWeight={400}
|
||||
fontSize="12px"
|
||||
className="virtual-data-room-block_description"
|
||||
>
|
||||
{bodyText}
|
||||
</Text>
|
||||
{isChecked && (
|
||||
<div className="virtual-data-room-block_content">{children}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const VirtualDataRoomBlock = ({ t, roomParams, setRoomParams }) => {
|
||||
const role = t("Translations:RoleViewer");
|
||||
|
||||
const [fileLifetimeChecked, setFileLifetimeChecked] = useState(false);
|
||||
const [copyAndDownloadChecked, setCopyAndDownloadChecked] = useState(false);
|
||||
const [watermarksChecked, setWatermarksChecked] = useState(false);
|
||||
|
||||
const onChangeAutomaticIndexing = () => {
|
||||
setRoomParams({ ...roomParams, indexing: !roomParams.indexing });
|
||||
};
|
||||
|
||||
const onChangeFileLifetime = () => {
|
||||
setFileLifetimeChecked(!fileLifetimeChecked);
|
||||
};
|
||||
|
||||
const onChangeRestrictCopyAndDownload = () => {
|
||||
setCopyAndDownloadChecked(!copyAndDownloadChecked);
|
||||
};
|
||||
|
||||
const onChangeAddWatermarksToDocuments = () => {
|
||||
setWatermarksChecked(!watermarksChecked);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledVirtualDataRoomBlock>
|
||||
<Block
|
||||
headerText={t("AutomaticIndexing")}
|
||||
bodyText={t("AutomaticIndexingDescription")}
|
||||
onChange={onChangeAutomaticIndexing}
|
||||
isDisabled={false}
|
||||
isChecked={roomParams.indexing}
|
||||
></Block>
|
||||
<Block
|
||||
headerText={t("FileLifetime")}
|
||||
bodyText={t("FileLifetimeDescription")}
|
||||
onChange={onChangeFileLifetime}
|
||||
isDisabled={false}
|
||||
isChecked={fileLifetimeChecked}
|
||||
>
|
||||
<FileLifetime t={t} />
|
||||
</Block>
|
||||
<Block
|
||||
headerText={t("RestrictCopyAndDownload")}
|
||||
bodyText={
|
||||
<Trans t={t} i18nKey="RestrictCopyAndDownloadDescription">
|
||||
Enable this setting to disable downloads and content copying for
|
||||
users with the {{ role }} role.
|
||||
</Trans>
|
||||
}
|
||||
onChange={onChangeRestrictCopyAndDownload}
|
||||
isDisabled={false}
|
||||
isChecked={copyAndDownloadChecked}
|
||||
></Block>
|
||||
<Block
|
||||
headerText={t("AddWatermarksToDocuments")}
|
||||
bodyText={t("AddWatermarksToDocumentsDescription")}
|
||||
onChange={onChangeAddWatermarksToDocuments}
|
||||
isDisabled={false}
|
||||
isChecked={watermarksChecked}
|
||||
></Block>
|
||||
</StyledVirtualDataRoomBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default VirtualDataRoomBlock;
|
@ -61,6 +61,9 @@ export const getDefaultRoomName = (room, t) => {
|
||||
|
||||
case RoomsType.PublicRoom:
|
||||
return t("Files:PublicRoom");
|
||||
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("Files:VirtualDataRoom");
|
||||
case RoomsType.FormRoom:
|
||||
return t("Files:FormRoom");
|
||||
}
|
||||
|
@ -303,8 +303,22 @@ const StyledProperties = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledItemOptions = styled.div`
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: auto;
|
||||
`
|
||||
: css`
|
||||
margin-left: auto;
|
||||
`}
|
||||
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
StyledInfoPanelBody.defaultProps = { theme: Base };
|
||||
StyledTitle.defaultProps = { theme: Base };
|
||||
StyledItemOptions.defaultProps = { theme: Base };
|
||||
|
||||
export {
|
||||
StyledInfoPanelBody,
|
||||
|
@ -0,0 +1,94 @@
|
||||
import IconCalendar from "PUBLIC_DIR/images/calendar.info.panel.react.svg?url";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import moment from "moment";
|
||||
import {Calendar} from "@docspace/shared/components/calendar"
|
||||
import { Portal } from "@docspace/shared/components/portal";
|
||||
import { isMobile } from "@docspace/shared/utils";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const StyledCalendarComponent = styled.div`
|
||||
position: relative;
|
||||
|
||||
.icon-calendar {
|
||||
padding-right: 2px;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCalendar = styled(Calendar)`
|
||||
position: absolute;
|
||||
top: 134px;
|
||||
right: 16px;
|
||||
|
||||
${(props) =>
|
||||
props.isMobile &&
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
right: auto;
|
||||
`}
|
||||
`;
|
||||
|
||||
const CalendarComponent = ({ roomCreationDate, setCalendarDay }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedDate, setSelectedDate] = useState(null);
|
||||
|
||||
const calendarRef = useRef();
|
||||
const calendarButtonRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("click", handleClick, { capture: true });
|
||||
return () => {
|
||||
document.removeEventListener("click", handleClick, { capture: true });
|
||||
setCalendarDay(null);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleClick = (e) => {
|
||||
!calendarButtonRef?.current?.contains(e.target) &&
|
||||
!calendarRef?.current?.contains(e.target) &&
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const toggleCalendar = () => setIsOpen((open) => !open);
|
||||
|
||||
const onDateSet = (date) => {
|
||||
const formattedDate = moment(date.format("YYYY-MM-DD"));
|
||||
setSelectedDate(date);
|
||||
setCalendarDay(formattedDate._i);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const formattedRoomCreationDate =
|
||||
moment(roomCreationDate).format("YYYY/MM/DD");
|
||||
|
||||
return (
|
||||
<StyledCalendarComponent>
|
||||
<div ref={calendarButtonRef}>
|
||||
<ReactSVG
|
||||
className="icon-calendar"
|
||||
src={IconCalendar}
|
||||
onClick={toggleCalendar}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isOpen && (
|
||||
<Portal
|
||||
element={
|
||||
<StyledCalendar
|
||||
setSelectedDate={onDateSet}
|
||||
selectedDate={selectedDate}
|
||||
minDate={new Date(formattedRoomCreationDate)}
|
||||
maxDate={new Date()}
|
||||
forwardedRef={calendarRef}
|
||||
isMobile={isMobile()}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</StyledCalendarComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalendarComponent;
|
@ -9,6 +9,7 @@ import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { StyledTitle } from "../../../styles/common";
|
||||
import { RoomIcon } from "@docspace/shared/components/room-icon";
|
||||
import RoomsContextBtn from "./context-btn";
|
||||
import CalendarComponent from "../Calendar";
|
||||
import {
|
||||
FolderType,
|
||||
RoomsType,
|
||||
@ -29,6 +30,8 @@ const RoomsItemHeader = ({
|
||||
setBufferSelection,
|
||||
isArchive,
|
||||
hasLinks,
|
||||
setCalendarDay,
|
||||
openHistory,
|
||||
}) => {
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
@ -99,7 +102,13 @@ const RoomsItemHeader = ({
|
||||
size={16}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* TODO: Add a condition so that there is a vdr room when the correct room type is returned from the backend for Calendar */}
|
||||
{openHistory && (
|
||||
<CalendarComponent
|
||||
setCalendarDay={setCalendarDay}
|
||||
roomCreationDate={selection.created}
|
||||
/>
|
||||
)}
|
||||
<RoomsContextBtn
|
||||
selection={selection}
|
||||
itemTitleRef={itemTitleRef}
|
||||
@ -119,7 +128,8 @@ export default inject(
|
||||
infoPanelStore,
|
||||
publicRoomStore,
|
||||
}) => {
|
||||
const { infoPanelSelection, roomsView, setIsMobileHidden } = infoPanelStore;
|
||||
const { infoPanelSelection, roomsView, setIsMobileHidden, setCalendarDay } =
|
||||
infoPanelStore;
|
||||
const { externalLinks } = publicRoomStore;
|
||||
|
||||
const selection = infoPanelSelection.length > 1 ? null : infoPanelSelection;
|
||||
@ -145,6 +155,7 @@ export default inject(
|
||||
setBufferSelection: filesStore.setBufferSelection,
|
||||
isArchive,
|
||||
hasLinks: externalLinks.length,
|
||||
setCalendarDay,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -15,6 +15,8 @@ const ItemTitle = ({
|
||||
currentColorScheme,
|
||||
getIcon,
|
||||
getUserContextOptions,
|
||||
setCalendarDay,
|
||||
roomsView,
|
||||
}) => {
|
||||
if (!infoPanelSelection) return null;
|
||||
if (isNoItem) return null;
|
||||
@ -29,6 +31,7 @@ const ItemTitle = ({
|
||||
/>
|
||||
);
|
||||
|
||||
const openHistory = roomsView === "info_history";
|
||||
if (isGallery)
|
||||
return (
|
||||
<GalleryItemTitle
|
||||
@ -38,21 +41,35 @@ const ItemTitle = ({
|
||||
/>
|
||||
);
|
||||
|
||||
return <RoomsItemHeader />;
|
||||
return (
|
||||
<RoomsItemHeader
|
||||
openHistory={openHistory}
|
||||
setCalendarDay={setCalendarDay}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ settingsStore, filesSettingsStore, peopleStore, oformsStore }) => {
|
||||
({
|
||||
settingsStore,
|
||||
filesSettingsStore,
|
||||
peopleStore,
|
||||
oformsStore,
|
||||
infoPanelStore,
|
||||
}) => {
|
||||
const { currentColorScheme } = settingsStore;
|
||||
const { getIcon } = filesSettingsStore;
|
||||
const { getUserContextOptions } = peopleStore.contextOptionsStore;
|
||||
const { gallerySelected } = oformsStore;
|
||||
const { roomsView, setCalendarDay } = infoPanelStore;
|
||||
|
||||
return {
|
||||
currentColorScheme,
|
||||
gallerySelected,
|
||||
getUserContextOptions,
|
||||
getIcon,
|
||||
roomsView,
|
||||
setCalendarDay,
|
||||
};
|
||||
}
|
||||
)(observer(ItemTitle));
|
||||
|
@ -42,6 +42,7 @@ const HistoryBlock = ({
|
||||
|
||||
return (
|
||||
<StyledHistoryBlock
|
||||
className={json.ModifiedDate}
|
||||
withBottomDivider={!isLastEntity}
|
||||
isUserAction={isUserAction}
|
||||
>
|
||||
|
@ -22,6 +22,8 @@ const History = ({
|
||||
openUser,
|
||||
isVisitor,
|
||||
isCollaborator,
|
||||
calendarDay,
|
||||
setCalendarDay,
|
||||
}) => {
|
||||
const isMount = useRef(true);
|
||||
const abortControllerRef = useRef(new AbortController());
|
||||
@ -67,6 +69,84 @@ const History = ({
|
||||
fetchHistory(infoPanelSelection);
|
||||
}, [infoPanelSelection.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!calendarDay) return;
|
||||
|
||||
const heightTitleRoom = 80;
|
||||
const heightDayWeek = 40;
|
||||
|
||||
const historyListNode = document.getElementById("history-list-info-panel");
|
||||
if (!historyListNode) return;
|
||||
|
||||
const scroll = historyListNode.closest(".scroller");
|
||||
if (!scroll) return;
|
||||
|
||||
let dateCoincidingWithCalendarDay = null;
|
||||
|
||||
selectionHistory.every((item) => {
|
||||
if (dateCoincidingWithCalendarDay) return false;
|
||||
|
||||
item.feeds.every((feed) => {
|
||||
if (feed.json.ModifiedDate.slice(0, 10) === calendarDay) {
|
||||
dateCoincidingWithCalendarDay = feed.json.ModifiedDate;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (dateCoincidingWithCalendarDay) {
|
||||
const dayNode = historyListNode.getElementsByClassName(
|
||||
dateCoincidingWithCalendarDay
|
||||
);
|
||||
if (!dayNode[0]) return;
|
||||
|
||||
const y = dayNode[0].offsetTop - heightTitleRoom - heightDayWeek;
|
||||
scroll.scrollTo(0, y);
|
||||
setCalendarDay(null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//If there are no entries in the history for the selected day
|
||||
const calendarDayModified = new Date(calendarDay);
|
||||
let nearestNewerDate = null;
|
||||
|
||||
selectionHistory.every((item, indexItem) => {
|
||||
if (nearestNewerDate) return false;
|
||||
|
||||
item.feeds.every((feed) => {
|
||||
const date = new Date(feed.json.ModifiedDate);
|
||||
|
||||
//Stop checking all entries for one day
|
||||
if (date > calendarDayModified) return false;
|
||||
|
||||
//Looking for the nearest new date
|
||||
if (date < calendarDayModified) {
|
||||
//If there are no nearby new entries in the post history, then scroll to the last one
|
||||
if (indexItem === 0) {
|
||||
nearestNewerDate = feed.json.ModifiedDate;
|
||||
return false;
|
||||
}
|
||||
|
||||
nearestNewerDate =
|
||||
selectionHistory[indexItem - 1].feeds[0].json.ModifiedDate;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!nearestNewerDate) return;
|
||||
|
||||
const dayNode = historyListNode.getElementsByClassName(nearestNewerDate);
|
||||
if (!dayNode[0]) return;
|
||||
|
||||
const y = dayNode[0].offsetTop - heightTitleRoom - heightDayWeek;
|
||||
scroll.scrollTo(0, y);
|
||||
setCalendarDay(null);
|
||||
}, [calendarDay]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
abortControllerRef.current?.abort();
|
||||
@ -78,7 +158,7 @@ const History = ({
|
||||
if (!selectionHistory?.length) return <NoHistory t={t} />;
|
||||
|
||||
return (
|
||||
<StyledHistoryList>
|
||||
<StyledHistoryList id="history-list-info-panel">
|
||||
{selectionHistory.map(({ day, feeds }) => [
|
||||
<StyledHistorySubtitle key={day}>{day}</StyledHistorySubtitle>,
|
||||
...feeds.map((feed, i) => (
|
||||
@ -117,6 +197,8 @@ export default inject(
|
||||
historyWithFileList,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
calendarDay,
|
||||
setCalendarDay,
|
||||
} = infoPanelStore;
|
||||
const { personal, culture } = settingsStore;
|
||||
|
||||
@ -140,6 +222,8 @@ export default inject(
|
||||
openUser,
|
||||
isVisitor,
|
||||
isCollaborator,
|
||||
calendarDay,
|
||||
setCalendarDay,
|
||||
};
|
||||
}
|
||||
)(withTranslation(["InfoPanel", "Common", "Translations"])(observer(History)));
|
||||
|
@ -1243,6 +1243,13 @@ const SectionFilterContent = ({
|
||||
group: FilterGroups.roomFilterType,
|
||||
label: t("PublicRoom"),
|
||||
};
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return {
|
||||
id: "filter_type-virtual-data",
|
||||
key: RoomsType.VirtualDataRoom,
|
||||
group: FilterGroups.roomFilterType,
|
||||
label: t("VirtualDataRoom"),
|
||||
};
|
||||
case RoomsType.CustomRoom:
|
||||
default:
|
||||
return {
|
||||
|
@ -93,6 +93,7 @@ class CreateEditRoomStore {
|
||||
const createRoomData = {
|
||||
roomType: roomParams.type,
|
||||
title: roomParams.title || t("Files:NewRoom"),
|
||||
indexing: roomParams.indexing,
|
||||
};
|
||||
|
||||
const createTagsData = roomParams.tags
|
||||
|
@ -345,6 +345,9 @@ class FilesSettingsStore {
|
||||
case RoomsType.PublicRoom:
|
||||
path = "public.svg";
|
||||
break;
|
||||
case RoomsType.VirtualDataRoom:
|
||||
path = "virtual.data.svg";
|
||||
break;
|
||||
case RoomsType.FormRoom:
|
||||
path = "form.svg";
|
||||
}
|
||||
|
@ -3059,6 +3059,7 @@ class FilesStore {
|
||||
mute,
|
||||
inRoom,
|
||||
requestToken,
|
||||
indexing,
|
||||
} = item;
|
||||
|
||||
const thirdPartyIcon = this.thirdPartyStore.getThirdPartyIcon(
|
||||
@ -3220,6 +3221,7 @@ class FilesStore {
|
||||
viewAccessibility,
|
||||
...pluginOptions,
|
||||
inRoom,
|
||||
indexing,
|
||||
type,
|
||||
hasDraft,
|
||||
isForm,
|
||||
|
@ -64,6 +64,7 @@ class InfoPanelStore {
|
||||
membersIsLoading = false;
|
||||
|
||||
shareChanged = false;
|
||||
calendarDay = null;
|
||||
|
||||
constructor(userStore) {
|
||||
this.userStore = userStore;
|
||||
@ -122,13 +123,13 @@ class InfoPanelStore {
|
||||
? peopleSelection.length
|
||||
? [...peopleSelection]
|
||||
: peopleBufferSelection
|
||||
? [peopleBufferSelection]
|
||||
: []
|
||||
? [peopleBufferSelection]
|
||||
: []
|
||||
: filesSelection?.length > 0
|
||||
? [...filesSelection]
|
||||
: filesBufferSelection
|
||||
? [filesBufferSelection]
|
||||
: [];
|
||||
? [...filesSelection]
|
||||
: filesBufferSelection
|
||||
? [filesBufferSelection]
|
||||
: [];
|
||||
}
|
||||
|
||||
getInfoPanelSelectedFolder = () => {
|
||||
@ -145,10 +146,10 @@ class InfoPanelStore {
|
||||
return this.infoPanelSelection
|
||||
? this.infoPanelSelection
|
||||
: selection.length
|
||||
? selection[0]
|
||||
: bufferSelection
|
||||
? bufferSelection
|
||||
: null;
|
||||
? selection[0]
|
||||
: bufferSelection
|
||||
? bufferSelection
|
||||
: null;
|
||||
}
|
||||
|
||||
get withPublicRoomBlock() {
|
||||
@ -263,26 +264,20 @@ class InfoPanelStore {
|
||||
? item.rootFolderType === FolderType.Archive
|
||||
? item.logo && item.logo.medium
|
||||
: this.filesSettingsStore.getIcon(
|
||||
size,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
item.roomType,
|
||||
true
|
||||
)
|
||||
? item.logo?.medium
|
||||
: item.icon
|
||||
? item.icon
|
||||
: this.filesSettingsStore.getIcon(
|
||||
size,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
item.roomType
|
||||
)
|
||||
size,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
item.roomType,
|
||||
true
|
||||
)
|
||||
? item.logo?.medium
|
||||
: item.icon
|
||||
? item.icon
|
||||
: this.filesSettingsStore.getIcon(size, null, null, null, item.roomType)
|
||||
: item.isFolder && item.folderType
|
||||
? this.filesSettingsStore.getIconByFolderType(item.folderType, size)
|
||||
: this.filesSettingsStore.getIcon(size, item.fileExst || ".file");
|
||||
? this.filesSettingsStore.getIconByFolderType(item.folderType, size)
|
||||
: this.filesSettingsStore.getIcon(size, item.fileExst || ".file");
|
||||
};
|
||||
|
||||
// User link actions //
|
||||
@ -590,6 +585,10 @@ class InfoPanelStore {
|
||||
setShareChanged = (shareChanged) => {
|
||||
this.shareChanged = shareChanged;
|
||||
};
|
||||
|
||||
setCalendarDay = (calendarDay) => {
|
||||
this.calendarDay = calendarDay;
|
||||
};
|
||||
}
|
||||
|
||||
export default InfoPanelStore;
|
||||
|
@ -10,6 +10,7 @@ import EditingSvg32Url from "PUBLIC_DIR/images/icons/32/room/editing.svg?url";
|
||||
// import ViewOnlySvg32Url from "PUBLIC_DIR/images/icons/32/room/view.only.svg?url";
|
||||
import PublicRoomSvg32Url from "PUBLIC_DIR/images/icons/32/room/public.svg?url";
|
||||
import FormRoomSvg32Url from "PUBLIC_DIR/images/icons/32/room/form.svg?url";
|
||||
import VirtualDataRoomRoomSvg32Url from "PUBLIC_DIR/images/icons/32/room/virtual-data.svg?url";
|
||||
|
||||
import { RoomsType } from "../../enums";
|
||||
|
||||
@ -48,6 +49,8 @@ const RoomLogoPure = ({
|
||||
return CustomSvg32Url;
|
||||
case RoomsType.PublicRoom:
|
||||
return PublicRoomSvg32Url;
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return VirtualDataRoomRoomSvg32Url;
|
||||
case RoomsType.FormRoom:
|
||||
return FormRoomSvg32Url;
|
||||
default:
|
||||
|
@ -48,6 +48,8 @@ export const ROOMS_TYPE_TRANSLATIONS = Object.freeze({
|
||||
4: "Files:ViewOnlyRooms",
|
||||
5: "Files:CustomRooms",
|
||||
6: "Files:PublicRoom",
|
||||
|
||||
8: "Files:VirtualDataRoom",
|
||||
});
|
||||
|
||||
export const ROOMS_PROVIDER_TYPE_NAME = Object.freeze({
|
||||
|
@ -433,5 +433,6 @@ export enum RoomsType {
|
||||
// ReviewRoom: 3, //TODO: Restore when certs will be done
|
||||
// ReadOnlyRoom: 4, //TODO: Restore when certs will be done
|
||||
PublicRoom = 6,
|
||||
VirtualDataRoom = 8,
|
||||
CustomRoom = 5,
|
||||
}
|
||||
|
19
public/images/calendar.info.panel.react.svg
Normal file
19
public/images/calendar.info.panel.react.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Сalendar" clip-path="url(#clip0_253_66351)">
|
||||
<rect id="Rectangle 2138" x="7" width="2" height="5" rx="1" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2162" x="3" width="2" height="5" rx="1" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2145" x="11" width="2" height="5" rx="1" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2163" x="1" y="3" width="14" height="12" rx="1" stroke="#A3A9AE" stroke-width="2"/>
|
||||
<rect id="Rectangle 2164" x="4" y="7" width="2" height="2" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2167" x="4" y="10" width="2" height="2" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2165" x="7" y="7" width="2" height="2" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2168" x="7" y="10" width="2" height="2" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2166" x="10" y="7" width="2" height="2" fill="#A3A9AE"/>
|
||||
<rect id="Rectangle 2169" x="10" y="10" width="2" height="2" fill="#A3A9AE"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_253_66351">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
4
public/images/icons/32/room/virtual-data.svg
Normal file
4
public/images/icons/32/room/virtual-data.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13 9.5C13 8.67157 13.6716 8 14.5 8H17.5C18.3284 8 19 8.67157 19 9.5V10H22C23.1046 10 24 10.8954 24 12V15V16H23H18V14H22V12H19H17H15H13H10V14H14V16H9H8V15V12C8 10.8954 8.89543 10 10 10H13V9.5ZM11 20V17H9V20C9 21.1046 9.89543 22 11 22H21C22.1046 22 23 21.1046 23 20V17H21V20H11ZM17 14H15V17C15 17.5523 15.4477 18 16 18C16.5523 18 17 17.5523 17 17V14Z" fill="#509ADE"/>
|
||||
<rect x="1" y="1" width="30" height="30" rx="5" stroke="#509ADE" stroke-width="2"/>
|
||||
</svg>
|
After Width: | Height: | Size: 604 B |
@ -334,5 +334,10 @@
|
||||
"Warning": "Warning",
|
||||
"Website": "Website",
|
||||
"Yesterday": "Yesterday",
|
||||
"You": "You"
|
||||
"WED": "WED",
|
||||
"Days": "Days",
|
||||
"Months": "Months",
|
||||
"Years": "Years",
|
||||
"MoveToTrash": "Move to trash",
|
||||
"DeletePermanently": "Delete permanently"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user