Merge branch 'feature/VDR-room' of https://github.com/ONLYOFFICE/DocSpace-client into feature/VDR-room

This commit is contained in:
Nikita Gopienko 2024-06-27 17:02:46 +03:00
commit 82de90538e
27 changed files with 595 additions and 9 deletions

View File

@ -21,5 +21,16 @@
"ThirdPartyStorageDescription": "Use third-party services as data storage for this room. You can create a new folder or select the existing one in the connected storage.",
"ThirdPartyStorageNoStorageAlert": "Before, you need to connect the corresponding service in the “Integration” section. Otherwise, the connection will not be possible.",
"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 {{productName}} settings. Contact {{productName}} owner or administrator to enable the integration."
"ThirdPartyStorageRoomAdminNoStorageAlert": "To connect a third-party storage, you need to add the corresponding service in the Integration section of {{productName}} settings. Contact {{productName}} owner or administrator to enable the integration.",
"ViewOnlyRoomDescription": "Share any ready documents, reports, documentation, and other files for viewing.",
"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:"
}

View File

@ -105,6 +105,7 @@ const EditRoomEvent = ({
zoom: 1,
},
roomOwner: item.createdBy,
indexing: item.indexing,
...(isDefaultRoomsQuotaSet && {
quota: item.quotaLimit,

View File

@ -103,6 +103,7 @@ const CreateRoomDialog = ({
y: 0.5,
zoom: 1,
},
indexing: false, // VDR Automatic indexing
};
const [roomParams, setRoomParams] = useState({ ...startRoomParams });

View File

@ -75,7 +75,8 @@ const EditRoomDialog = ({
(currentParams.icon.uploadedFile === null ||
currentParams.icon.uploadedFile === undefined)) ||
prevParams.icon.uploadedFile === currentParams.icon.uploadedFile) &&
prevParams.quota === currentParams.quota
prevParams.quota === currentParams.quota &&
prevParams.indexing === currentParams.indexing
);
};

View File

@ -40,6 +40,8 @@ export const getRoomTypeDefaultTagTranslation = (roomType = 1, t) => {
return t("Common:CustomRooms");
case RoomsType.PublicRoom:
return t("Common:PublicRoom");
case RoomsType.VirtualDataRoom:
return t("Common:VirtualDataRoom");
case RoomsType.FormRoom:
return t("Common:FormRoom");
}

View File

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

View File

@ -44,6 +44,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 ChangeRoomOwner from "./ChangeRoomOwner";
import RoomQuota from "./RoomQuota";
@ -105,6 +106,8 @@ const SetRoomParams = ({
const [forceHideRoomTypeDropdown, setForceHideRoomTypeDropdown] =
useState(false);
const isVDRRoom = roomParams.type === RoomsType.VirtualDataRoom;
const isFormRoom = roomParams.type === RoomsType.FormRoom;
const isPublicRoom = roomParams.type === RoomsType.PublicRoom;
@ -215,6 +218,14 @@ const SetRoomParams = ({
/>
)}
{isVDRRoom && (
<VirtualDataRoomBlock
t={t}
roomParams={roomParams}
setRoomParams={setRoomParams}
/>
)}
{isDefaultRoomsQuotaSet && !roomParams.storageLocation.providerKey && (
<RoomQuota
setRoomParams={setRoomParams}

View File

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

View File

@ -86,6 +86,9 @@ export const getDefaultRoomName = (room, t) => {
case RoomsType.PublicRoom:
return t("Common:PublicRoom");
case RoomsType.VirtualDataRoom:
return t("Common:VirtualDataRoom");
case RoomsType.FormRoom:
return t("Common:FormRoom");
}

View File

@ -360,8 +360,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,

View File

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

View File

@ -36,8 +36,12 @@ 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 { FolderType, RoomsType } from "@docspace/shared/enums";
import { getDefaultAccessUser } from "@docspace/shared/utils/getDefaultAccessUser";
import CalendarComponent from "../Calendar";
import {
FolderType,
RoomsType,
ShareAccessRights,
} from "@docspace/shared/enums";
import Search from "../../Search";
const RoomsItemHeader = ({
@ -54,6 +58,8 @@ const RoomsItemHeader = ({
isArchive,
hasLinks,
showSearchBlock,
setCalendarDay,
openHistory,
setShowSearchBlock,
roomType,
}) => {
@ -141,7 +147,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}
@ -167,6 +179,7 @@ export default inject(
setIsMobileHidden,
showSearchBlock,
setShowSearchBlock,
setCalendarDay,
} = infoPanelStore;
const { externalLinks } = publicRoomStore;
@ -195,6 +208,7 @@ export default inject(
setBufferSelection: filesStore.setBufferSelection,
isArchive,
hasLinks: externalLinks.length,
setCalendarDay,
roomType,
};
},

View File

@ -43,6 +43,8 @@ const ItemTitle = ({
currentColorScheme,
getIcon,
getUserContextOptions,
setCalendarDay,
roomsView,
getGroupContextOptions,
}) => {
if (!infoPanelSelection) return null;
@ -58,6 +60,7 @@ const ItemTitle = ({
/>
);
const openHistory = roomsView === "info_history";
if (isGroups)
return (
<GroupsItemTitle
@ -77,16 +80,28 @@ 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 { getGroupContextOptions } = peopleStore.groupsStore;
const { gallerySelected } = oformsStore;
const { roomsView, setCalendarDay } = infoPanelStore;
return {
currentColorScheme,
@ -94,6 +109,8 @@ export default inject(
getUserContextOptions,
getGroupContextOptions,
getIcon,
roomsView,
setCalendarDay,
};
},
)(observer(ItemTitle));

View File

@ -44,6 +44,7 @@ const HistoryBlock = ({ t, feed, isLastEntity }) => {
return (
<StyledHistoryBlock
className={json.ModifiedDate}
withBottomDivider={!isLastEntity}
isUserAction={isUserAction}
>

View File

@ -47,6 +47,8 @@ const History = ({
openUser,
isVisitor,
isCollaborator,
calendarDay,
setCalendarDay,
}) => {
const isMount = useRef(true);
const abortControllerRef = useRef(new AbortController());
@ -76,8 +78,87 @@ const History = ({
infoPanelSelection.isFolder || infoPanelSelection.isRoom,
]);
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(() => {
const showLoaderTimer = setTimeout(() => setIsShowLoader(true), 500);
return () => {
clearTimeout(showLoaderTimer);
abortControllerRef.current?.abort();
@ -92,7 +173,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}>
{getRelativeDateDay(t, feeds[0].date)}
@ -127,6 +208,8 @@ export default inject(
historyWithFileList,
getInfoPanelItemIcon,
openUser,
calendarDay,
setCalendarDay,
} = infoPanelStore;
const { culture } = settingsStore;
@ -147,6 +230,8 @@ export default inject(
openUser,
isVisitor,
isCollaborator,
calendarDay,
setCalendarDay,
};
},
)(withTranslation(["InfoPanel", "Common", "Translations"])(observer(History)));

View File

@ -1618,6 +1618,13 @@ const SectionFilterContent = ({
group: FilterGroups.roomFilterType,
label: t("Common:PublicRoom"),
};
case RoomsType.VirtualDataRoom:
return {
id: "filter_type-virtual-data",
key: RoomsType.VirtualDataRoom,
group: FilterGroups.roomFilterType,
label: t("Common:VirtualDataRoom"),
};
case RoomsType.CustomRoom:
default:
return {

View File

@ -125,6 +125,7 @@ class CreateEditRoomStore {
const createRoomData = {
roomType: roomParams.type,
title: roomParams.title || t("Common:NewRoom"),
indexing: roomParams.indexing,
createAsNewFolder: roomParams.createAsNewFolder ?? true,
...(quotaLimit && {
quota: +quotaLimit,

View File

@ -395,6 +395,9 @@ class FilesSettingsStore {
case RoomsType.PublicRoom:
path = "public.svg";
break;
case RoomsType.VirtualDataRoom:
path = "virtual.data.svg";
break;
case RoomsType.FormRoom:
path = "form.svg";
}

View File

@ -3227,6 +3227,7 @@ class FilesStore {
mute,
inRoom,
requestToken,
indexing,
lastOpened,
quotaLimit,
usedSpace,
@ -3395,6 +3396,7 @@ class FilesStore {
viewAccessibility,
...pluginOptions,
inRoom,
indexing,
type,
hasDraft,
isForm,

View File

@ -100,6 +100,7 @@ class InfoPanelStore {
isMembersPanelUpdating = false;
shareChanged = false;
calendarDay = null;
showSearchBlock = false;
searchValue = "";
@ -831,6 +832,10 @@ class InfoPanelStore {
setShareChanged = (shareChanged) => {
this.shareChanged = shareChanged;
};
setCalendarDay = (calendarDay) => {
this.calendarDay = calendarDay;
};
}
export default InfoPanelStore;

View File

@ -36,6 +36,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";
@ -74,6 +75,8 @@ const RoomLogoPure = ({
return CustomSvg32Url;
case RoomsType.PublicRoom:
return PublicRoomSvg32Url;
case RoomsType.VirtualDataRoom:
return VirtualDataRoomRoomSvg32Url;
case RoomsType.FormRoom:
return FormRoomSvg32Url;
default:

View File

@ -18,6 +18,8 @@ export const getRoomTypeTitleTranslation = (
return t("Common:CustomRoomTitle");
case RoomsType.PublicRoom:
return t("Common:PublicRoom");
case RoomsType.VirtualDataRoom:
return t("Common:VirtualDataRoom");
case RoomsType.FormRoom:
return t("Common:FormFilingRoomTitle");
default:
@ -42,6 +44,8 @@ export const getRoomTypeDescriptionTranslation = (
return t("Common:CustomRoomDescription");
case RoomsType.PublicRoom:
return t("Common:PublicRoomDescription");
case RoomsType.VirtualDataRoom:
return t("Common:VirtualDataRoomDescription");
case RoomsType.FormRoom:
return t("Common:FormFilingRoomDescription");
default:

View File

@ -75,6 +75,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({

View File

@ -480,6 +480,7 @@ export enum RoomsType {
EditingRoom = 2,
// ReviewRoom: 3, //TODO: Restore when certs will be done
// ReadOnlyRoom: 4, //TODO: Restore when certs will be done
VirtualDataRoom = 8,
CustomRoom = 5,
}

View 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="&#208;&#161;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

View 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

View File

@ -486,5 +486,12 @@
"Website": "Website",
"Yes": "Yes",
"Yesterday": "Yesterday",
"You": "You"
"WED": "WED",
"Months": "Months",
"Years": "Years",
"MoveToTrash": "Move to trash",
"DeletePermanently": "Delete permanently",
"You": "You",
"VirtualDataRoom": "Virtual Data Room",
"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."
}