Merge pull request #536 from ONLYOFFICE/feature/VDR-indexing
Feature/vdr indexing
This commit is contained in:
commit
1bfa73ac4b
@ -66,6 +66,7 @@
|
||||
"EmptyScreenFolder": "No docs here yet",
|
||||
"EnableLink": "Enable link",
|
||||
"EnableNotifications": "Enable notifications",
|
||||
"ErrorChangeIndex": "Error when changing index. The problem may be caused on the server side. Reload the page or check your Internet connection settings.",
|
||||
"ExcludeSubfolders": "Exclude subfolders",
|
||||
"ExportRoomIndex": "Export room index",
|
||||
"ExportRoomIndexAlreadyInProgressError": "Room index export is already in progress. Please wait until the current export is completed to start the new one.",
|
||||
@ -88,6 +89,7 @@
|
||||
"GoToPersonal": "Go to Documents",
|
||||
"Images": "Images",
|
||||
"InviteUsersInRoom": "Invite users in room",
|
||||
"Index": "Index",
|
||||
"LeaveRoomDescription": "You are the owner of this room. Before you leave the room, you must transfer the owner's role to another user.",
|
||||
"LeaveTheRoom": "Leave the room",
|
||||
"LeftAndAppointNewOwner": "You have left the room and appointed a new owner",
|
||||
@ -154,6 +156,8 @@
|
||||
"RoomsRemoved": "Rooms removed",
|
||||
"RoomsUnpinned": "Rooms unpinned: {{count}}",
|
||||
"RoomUnpinned": "Room unpinned",
|
||||
"ReorderIndex": "The Reorder action will remove spaces in the indexes. The files will be re-indexed in order with offset to fill in missing indexes.",
|
||||
"Reorder": "Reorder",
|
||||
"SearchByContent": "Search by file contents",
|
||||
"SendByEmail": "Send by email",
|
||||
"ShareFolder": "Share folder",
|
||||
|
@ -65,6 +65,7 @@
|
||||
"EmptyScreenFolder": "Здесь пока нет документов",
|
||||
"EnableLink": "Активировать ссылку",
|
||||
"EnableNotifications": "Включить уведомления",
|
||||
"ErrorChangeIndex": "Ошибка при изменении индекса. Проблема может быть вызвана на стороне сервера. Перезагрузите страницу или проверьте настройки подключения к Интернету.",
|
||||
"ExcludeSubfolders": "Исключить вложенные папки",
|
||||
"FavoritesEmptyContainerDescription": "Чтобы добавить файлы в избранное или удалить их из этого списка, используйте контекстное меню.",
|
||||
"FileContents": "Содержимое файла",
|
||||
@ -84,6 +85,7 @@
|
||||
"GoToPersonal": "Перейти к Документам",
|
||||
"Images": "Изображения",
|
||||
"InviteUsersInRoom": "Пригласить пользователей в комнату",
|
||||
"Index": "Индекс",
|
||||
"LeaveRoomDescription": "Вы являетесь новым владельцем комнаты. Перед тем, как покинуть комнату, вы должны передать роль владельца другому пользователю.",
|
||||
"LeaveTheRoom": "Покинуть комнату",
|
||||
"LeftAndAppointNewOwner": "Вы покинули комнату и назначили нового владельца",
|
||||
@ -135,6 +137,8 @@
|
||||
"RemoveFromList": "Убрать из списка",
|
||||
"RestoreAll": "Восстановить все",
|
||||
"RevokeLink": "Отозвать ссылку",
|
||||
"ReorderIndex": "Действие «Изменить порядок» удалит пробелы в индексах. Файлы будут переиндексированы по порядку со смещением для заполнения недостающих индексов.",
|
||||
"Reorder": "Изменить порядок",
|
||||
"RoomAvailableViaExternalLink": "Комната доступна по внешней ссылке",
|
||||
"RoomCreated": "Комната создана",
|
||||
"RoomEmptyAtTheMoment": "В данный момент эта комната пуста.",
|
||||
|
@ -276,7 +276,9 @@ export default function withFileActions(WrappedFileItem) {
|
||||
isDisabledDropItem,
|
||||
isRecentTab,
|
||||
canDrag,
|
||||
isIndexUpdated,
|
||||
} = this.props;
|
||||
|
||||
const { access, id } = item;
|
||||
|
||||
const isDragging =
|
||||
@ -336,6 +338,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
value={value}
|
||||
displayShareButton={displayShareButton}
|
||||
isPrivacy={isPrivacy}
|
||||
isIndexUpdated={isIndexUpdated}
|
||||
checkedProps={checkedProps}
|
||||
dragging={dragging}
|
||||
getContextModel={this.getContextModel}
|
||||
@ -361,6 +364,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
filesStore,
|
||||
uploadDataStore,
|
||||
contextOptionsStore,
|
||||
indexingStore,
|
||||
},
|
||||
{ item, t },
|
||||
) => {
|
||||
@ -374,6 +378,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
uploadEmptyFolders,
|
||||
} = filesActionsStore;
|
||||
const { setSharingPanelVisible } = dialogsStore;
|
||||
const { updateSelection } = indexingStore;
|
||||
const {
|
||||
isPrivacyFolder,
|
||||
isRecycleBinFolder,
|
||||
@ -408,6 +413,10 @@ export default function withFileActions(WrappedFileItem) {
|
||||
(x) => x.id === item.id && x.fileExst === item.fileExst,
|
||||
);
|
||||
|
||||
const isIndexUpdated = !!updateSelection.find(
|
||||
(x) => x.id === item.id && x.fileExst === item?.fileExst,
|
||||
);
|
||||
|
||||
const isDisabledDropItem = item.security?.Create === false;
|
||||
|
||||
const draggable =
|
||||
@ -505,6 +514,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
currentDeviceType: settingsStore.currentDeviceType,
|
||||
isDisabledDropItem,
|
||||
isRecentTab,
|
||||
isIndexUpdated,
|
||||
|
||||
canDrag: !dragIsDisabled,
|
||||
};
|
||||
|
@ -93,6 +93,7 @@ const withHotkeys = (Component) => {
|
||||
isGroupMenuBlocked,
|
||||
isFormRoom,
|
||||
isParentFolderFormRoom,
|
||||
isIndexEditingMode,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -178,7 +179,8 @@ const withHotkeys = (Component) => {
|
||||
(e) => {
|
||||
const someDialogIsOpen = checkDialogsOpen();
|
||||
|
||||
if (e.shiftKey || e.ctrlKey || someDialogIsOpen) return;
|
||||
if (e.shiftKey || e.ctrlKey || someDialogIsOpen || isIndexEditingMode)
|
||||
return;
|
||||
|
||||
switch (e.key) {
|
||||
case "ArrowDown":
|
||||
@ -423,6 +425,7 @@ const withHotkeys = (Component) => {
|
||||
selectedFolderStore,
|
||||
userStore,
|
||||
currentTariffStatusStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const {
|
||||
setSelected,
|
||||
@ -530,6 +533,7 @@ const withHotkeys = (Component) => {
|
||||
isTrashFolder,
|
||||
isArchiveFolder,
|
||||
isRoomsFolder,
|
||||
isIndexEditingMode: indexingStore.isIndexEditingMode,
|
||||
|
||||
selection,
|
||||
setFavoriteAction,
|
||||
|
@ -150,6 +150,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
isPublicRoom,
|
||||
isPersonalRoom,
|
||||
isArchiveFolder,
|
||||
isIndexEditingMode,
|
||||
currentDeviceType,
|
||||
roomLifetime,
|
||||
} = this.props;
|
||||
@ -177,6 +178,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
folderCategory={folderCategory}
|
||||
onCopyPrimaryLink={this.onCopyPrimaryLink}
|
||||
isArchiveFolder={isArchiveFolder}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
currentDeviceType={currentDeviceType}
|
||||
showLifetimeIcon={showLifetimeIcon}
|
||||
expiredDate={expiredDate}
|
||||
@ -202,6 +204,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
treeFoldersStore,
|
||||
filesStore,
|
||||
infoPanelStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const { lockFileAction, setFavoriteAction, onSelectItem } =
|
||||
filesActionsStore;
|
||||
@ -213,6 +216,8 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
isArchiveFolder,
|
||||
} = treeFoldersStore;
|
||||
|
||||
const { isIndexEditingMode } = indexingStore;
|
||||
|
||||
const { setSharingPanelVisible } = dialogsStore;
|
||||
|
||||
const folderCategory =
|
||||
@ -238,6 +243,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
isArchiveFolder,
|
||||
getPrimaryFileLink,
|
||||
setShareChanged,
|
||||
isIndexEditingMode,
|
||||
roomLifetime: infoPanelRoom?.lifetime,
|
||||
};
|
||||
},
|
||||
|
@ -75,10 +75,12 @@ const Item = ({
|
||||
iconBadge,
|
||||
folderId,
|
||||
currentColorScheme,
|
||||
isIndexEditingMode,
|
||||
}) => {
|
||||
const [isDragActive, setIsDragActive] = useState(false);
|
||||
|
||||
const isDragging = dragging ? showDragItems(item) : false;
|
||||
const isDragging =
|
||||
dragging && !isIndexEditingMode ? showDragItems(item) : false;
|
||||
|
||||
let value = "";
|
||||
if (isDragging) value = `${item.id} dragging`;
|
||||
@ -221,6 +223,7 @@ const Items = ({
|
||||
currentDeviceType,
|
||||
folderAccess,
|
||||
currentColorScheme,
|
||||
isIndexEditingMode,
|
||||
}) => {
|
||||
const getEndOfBlock = React.useCallback((item) => {
|
||||
switch (item.key) {
|
||||
@ -343,6 +346,7 @@ const Items = ({
|
||||
iconBadge={iconBadge}
|
||||
folderId={`document_catalog-${FOLDER_NAMES[item.rootFolderType]}`}
|
||||
currentColorScheme={currentColorScheme}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -395,6 +399,7 @@ const Items = ({
|
||||
firstLoad,
|
||||
activeItemId,
|
||||
emptyTrashInProgress,
|
||||
isIndexEditingMode,
|
||||
],
|
||||
);
|
||||
|
||||
@ -421,6 +426,7 @@ export default inject(
|
||||
clientLoadingStore,
|
||||
userStore,
|
||||
settingsStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const { isCommunity, isPaymentPageAvailable, currentDeviceType } =
|
||||
authStore;
|
||||
@ -437,6 +443,8 @@ export default inject(
|
||||
startDrag,
|
||||
} = filesStore;
|
||||
|
||||
const { isIndexEditingMode } = indexingStore;
|
||||
|
||||
const { firstLoad } = clientLoadingStore;
|
||||
|
||||
const { startUpload } = uploadDataStore;
|
||||
@ -488,6 +496,7 @@ export default inject(
|
||||
currentDeviceType,
|
||||
folderAccess,
|
||||
currentColorScheme,
|
||||
isIndexEditingMode,
|
||||
};
|
||||
},
|
||||
)(withTranslation(["Files", "Common", "Translations"])(observer(Items)));
|
||||
|
@ -76,6 +76,7 @@ import LeaveRoomDialog from "../dialogs/LeaveRoomDialog";
|
||||
import ChangeRoomOwnerPanel from "../panels/ChangeRoomOwnerPanel";
|
||||
import { CreatedPDFFormDialog } from "../dialogs/CreatedPDFFormDialog";
|
||||
import { PDFFormEditingDialog } from "../dialogs/PDFFormEditingDialog";
|
||||
import ReorderIndexDialog from "../dialogs/ReorderIndexDialog";
|
||||
import LifetimeDialog from "../dialogs/LifetimeDialog";
|
||||
import { SharePDFFormDialog } from "../dialogs/SharePDFFormDialog";
|
||||
|
||||
@ -133,6 +134,7 @@ const Panels = (props) => {
|
||||
shareFolderDialogVisible,
|
||||
pdfFormEditVisible,
|
||||
selectFileFormRoomOpenRoot,
|
||||
reorderDialogVisible,
|
||||
} = props;
|
||||
|
||||
const [createPDFFormFile, setCreatePDFFormFile] = useState({
|
||||
@ -347,6 +349,7 @@ const Panels = (props) => {
|
||||
<ChangeRoomOwnerPanel key="change-room-owner" />
|
||||
),
|
||||
shareFolderDialogVisible && <ShareFolderDialog key="share-folder-dialog" />,
|
||||
reorderDialogVisible && <ReorderIndexDialog key="reorder-index-dialog" />,
|
||||
createPDFFormFile.visible && (
|
||||
<CreatedPDFFormDialog
|
||||
key="created-pdf-form-dialog"
|
||||
@ -418,6 +421,7 @@ export default inject(
|
||||
shareFolderDialogVisible,
|
||||
pdfFormEditVisible,
|
||||
selectFileFormRoomOpenRoot,
|
||||
reorderDialogVisible,
|
||||
} = dialogsStore;
|
||||
|
||||
const { preparationPortalDialogVisible } = backup;
|
||||
@ -487,6 +491,7 @@ export default inject(
|
||||
shareFolderDialogVisible,
|
||||
pdfFormEditVisible,
|
||||
selectFileFormRoomOpenRoot,
|
||||
reorderDialogVisible,
|
||||
};
|
||||
},
|
||||
)(observer(Panels));
|
||||
|
@ -81,6 +81,7 @@ const QuickButtons = (props) => {
|
||||
onClickShare,
|
||||
isPersonalRoom,
|
||||
isArchiveFolder,
|
||||
isIndexEditingMode,
|
||||
currentDeviceType,
|
||||
showLifetimeIcon,
|
||||
expiredDate,
|
||||
@ -163,83 +164,85 @@ const QuickButtons = (props) => {
|
||||
|
||||
return (
|
||||
<StyledQuickButtons className="badges additional-badges badges__quickButtons">
|
||||
{showLifetimeIcon && (
|
||||
{!isIndexEditingMode && (
|
||||
<>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LifetimeReactSvgUrl}
|
||||
className="badge file-lifetime icons-group"
|
||||
size={sizeQuickButton}
|
||||
isClickable
|
||||
isDisabled={isDisabled}
|
||||
data-tooltip-id="lifetimeTooltip"
|
||||
color={theme.filesQuickButtons.lifeTimeColor}
|
||||
/>
|
||||
{showLifetimeIcon && (
|
||||
<>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LifetimeReactSvgUrl}
|
||||
className="badge file-lifetime icons-group"
|
||||
size={sizeQuickButton}
|
||||
isClickable
|
||||
isDisabled={isDisabled}
|
||||
data-tooltip-id="lifetimeTooltip"
|
||||
color={theme.filesQuickButtons.lifeTimeColor}
|
||||
/>
|
||||
|
||||
<Tooltip
|
||||
id="lifetimeTooltip"
|
||||
place="bottom"
|
||||
getContent={getTooltipContent}
|
||||
maxWidth="300px"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Tooltip
|
||||
id="lifetimeTooltip"
|
||||
place="bottom"
|
||||
getContent={getTooltipContent}
|
||||
maxWidth="300px"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isAvailableLockFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={iconLock}
|
||||
className="badge lock-file icons-group"
|
||||
size={sizeQuickButton}
|
||||
data-id={id}
|
||||
data-locked={locked ? true : false}
|
||||
onClick={onClickLock}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("UnblockVersion")}
|
||||
/>
|
||||
)}
|
||||
{isAvailableDownloadFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={FileActionsDownloadReactSvgUrl}
|
||||
className="badge download-file icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onClickDownload}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Common:Download")}
|
||||
/>
|
||||
)}
|
||||
{showCopyLinkIcon && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LinkReactSvgUrl}
|
||||
className="badge copy-link icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onCopyPrimaryLink}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Files:CopySharedLink")}
|
||||
/>
|
||||
)}
|
||||
{isAvailableShareFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LinkReactSvgUrl}
|
||||
className="badge copy-link icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onClickShare}
|
||||
color={colorShare}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Files:CopySharedLink")}
|
||||
/>
|
||||
)}
|
||||
{/* {fileExst && !isTrashFolder && displayBadges && (
|
||||
{isAvailableLockFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={iconLock}
|
||||
className="badge lock-file icons-group"
|
||||
size={sizeQuickButton}
|
||||
data-id={id}
|
||||
data-locked={locked ? true : false}
|
||||
onClick={onClickLock}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("UnblockVersion")}
|
||||
/>
|
||||
)}
|
||||
{isAvailableDownloadFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={FileActionsDownloadReactSvgUrl}
|
||||
className="badge download-file icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onClickDownload}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Common:Download")}
|
||||
/>
|
||||
)}
|
||||
{showCopyLinkIcon && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LinkReactSvgUrl}
|
||||
className="badge copy-link icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onCopyPrimaryLink}
|
||||
color={colorLock}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Files:CopySharedLink")}
|
||||
/>
|
||||
)}
|
||||
{isAvailableShareFile && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={LinkReactSvgUrl}
|
||||
className="badge copy-link icons-group"
|
||||
size={sizeQuickButton}
|
||||
onClick={onClickShare}
|
||||
color={colorShare}
|
||||
isDisabled={isDisabled}
|
||||
hoverColor={theme.filesQuickButtons.sharedColor}
|
||||
title={t("Files:CopySharedLink")}
|
||||
/>
|
||||
)}
|
||||
{/* {fileExst && !isTrashFolder && displayBadges && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
iconName={iconFavorite}
|
||||
@ -253,6 +256,8 @@ const QuickButtons = (props) => {
|
||||
hoverColor={theme.filesQuickButtons.hoverColor}
|
||||
/>
|
||||
)} */}
|
||||
</>
|
||||
)}
|
||||
</StyledQuickButtons>
|
||||
);
|
||||
};
|
||||
|
@ -41,10 +41,12 @@ export default inject(
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
infoPanelStore,
|
||||
indexingStore,
|
||||
}: {
|
||||
settingsStore: any;
|
||||
dialogsStore: any;
|
||||
infoPanelStore: any;
|
||||
indexingStore: any;
|
||||
}) => {
|
||||
const {
|
||||
isDesktopClient: isDesktop,
|
||||
@ -59,6 +61,8 @@ export default inject(
|
||||
const { isVisible, isMobileHidden, setIsVisible, getCanDisplay } =
|
||||
infoPanelStore;
|
||||
|
||||
const { isIndexEditingMode } = indexingStore;
|
||||
|
||||
const { createRoomDialogVisible, invitePanelOptions } = dialogsStore;
|
||||
|
||||
const canDisplay = getCanDisplay();
|
||||
@ -71,7 +75,7 @@ export default inject(
|
||||
return {
|
||||
isDesktop,
|
||||
currentDeviceType,
|
||||
isInfoPanelVisible: isVisible,
|
||||
isInfoPanelVisible: isVisible && !isIndexEditingMode,
|
||||
isMobileHidden,
|
||||
setIsInfoPanelVisible: setIsVisible,
|
||||
canDisplay,
|
||||
|
@ -0,0 +1,128 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TTranslation } from "@docspace/shared/types";
|
||||
|
||||
import {
|
||||
ModalDialog,
|
||||
ModalDialogType,
|
||||
} from "@docspace/shared/components/modal-dialog";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Button, ButtonSize } from "@docspace/shared/components/button";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
import DialogsStore from "SRC_DIR/store/DialogsStore";
|
||||
import SelectedFolderStore from "SRC_DIR/store/SelectedFolderStore";
|
||||
import FilesActionsStore from "SRC_DIR/store/FilesActionsStore";
|
||||
import { TSelectedFolder } from "@docspace/client/src/store/SelectedFolderStore";
|
||||
|
||||
export interface ReorderIndexDialogProps {
|
||||
reorder: (id: number | string | null, t: TTranslation) => void;
|
||||
setIsVisible: (visible: boolean) => void;
|
||||
visible: boolean;
|
||||
selectedFolder: TSelectedFolder;
|
||||
}
|
||||
|
||||
const ReorderIndexDialog = ({
|
||||
visible,
|
||||
setIsVisible,
|
||||
reorder,
|
||||
selectedFolder,
|
||||
}: ReorderIndexDialogProps) => {
|
||||
const { t, ready } = useTranslation(["Files", "Common"]);
|
||||
|
||||
const onClose = () => {
|
||||
setIsVisible(false);
|
||||
};
|
||||
|
||||
const onReorder = () => {
|
||||
reorder(selectedFolder?.id, t);
|
||||
setIsVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialog
|
||||
displayType={ModalDialogType.modal}
|
||||
isLarge
|
||||
isLoading={!ready}
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ModalDialog.Header>{t("Common:Warning")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text fontSize="13px" fontWeight={400} noSelect>
|
||||
{t("Files:ReorderIndex")}
|
||||
</Text>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="create-room"
|
||||
key="OkButton"
|
||||
label={t("Files:Reorder")}
|
||||
size={ButtonSize.normal}
|
||||
primary
|
||||
onClick={onReorder}
|
||||
scale={isMobile}
|
||||
/>
|
||||
<Button
|
||||
id="cancel-share-folder"
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size={ButtonSize.normal}
|
||||
onClick={onClose}
|
||||
scale={isMobile}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({
|
||||
dialogsStore,
|
||||
filesActionsStore,
|
||||
selectedFolderStore,
|
||||
}: {
|
||||
dialogsStore: DialogsStore;
|
||||
filesActionsStore: FilesActionsStore;
|
||||
selectedFolderStore: SelectedFolderStore;
|
||||
}) => {
|
||||
const { reorderDialogVisible, setReorderDialogVisible } = dialogsStore;
|
||||
const selectedFolder = selectedFolderStore.getSelectedFolder();
|
||||
const { reorder } = filesActionsStore;
|
||||
|
||||
return {
|
||||
visible: reorderDialogVisible,
|
||||
setIsVisible: setReorderDialogVisible,
|
||||
reorder,
|
||||
selectedFolder,
|
||||
};
|
||||
},
|
||||
)(observer(ReorderIndexDialog));
|
@ -174,6 +174,7 @@ class DetailsHelper {
|
||||
"Date modified",
|
||||
"Last modified by",
|
||||
"Creation date",
|
||||
this.item.order && "Index",
|
||||
]
|
||||
: [
|
||||
"Owner",
|
||||
@ -186,6 +187,7 @@ class DetailsHelper {
|
||||
"Creation date",
|
||||
this.item.expired && "Lifetime ends",
|
||||
"Versions",
|
||||
this.item.order && "Index",
|
||||
"Comments",
|
||||
]
|
||||
).filter((nP) => !!nP);
|
||||
@ -220,6 +222,9 @@ class DetailsHelper {
|
||||
case "Lifetime ends":
|
||||
return this.t("LifetimeEnds");
|
||||
|
||||
case "Index":
|
||||
return this.t("Files:Index");
|
||||
|
||||
case "Versions":
|
||||
return this.t("InfoPanel:Versions");
|
||||
case "Comments":
|
||||
@ -245,6 +250,9 @@ class DetailsHelper {
|
||||
case "Location":
|
||||
return this.getItemLocation();
|
||||
|
||||
case "Index":
|
||||
return this.getItemIndex();
|
||||
|
||||
case "Type":
|
||||
return this.getItemType();
|
||||
case "Storage Type":
|
||||
@ -337,6 +345,10 @@ class DetailsHelper {
|
||||
return text(this.item.contentLength);
|
||||
};
|
||||
|
||||
getItemIndex = () => {
|
||||
return text(this.item.order);
|
||||
};
|
||||
|
||||
getItemDateModified = () => {
|
||||
return text(parseAndFormatDate(this.item.updated, this.culture));
|
||||
};
|
||||
|
@ -36,6 +36,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 { getDefaultAccessUser } from "@docspace/shared/utils/getDefaultAccessUser";
|
||||
import CalendarComponent from "../Calendar";
|
||||
import {
|
||||
FolderType,
|
||||
|
@ -74,6 +74,8 @@ const FilesRowContainer = ({
|
||||
withPaging,
|
||||
highlightFile,
|
||||
currentDeviceType,
|
||||
isIndexEditingMode,
|
||||
changeIndex,
|
||||
}) => {
|
||||
useViewEffect({
|
||||
view: viewAs,
|
||||
@ -93,9 +95,11 @@ const FilesRowContainer = ({
|
||||
sectionWidth={sectionWidth}
|
||||
isRooms={isRooms}
|
||||
isTrashFolder={isTrashFolder}
|
||||
changeIndex={changeIndex}
|
||||
isHighlight={
|
||||
highlightFile.id == item.id && highlightFile.isExst === !item.fileExst
|
||||
}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
/>
|
||||
));
|
||||
}, [
|
||||
@ -124,7 +128,14 @@ const FilesRowContainer = ({
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ filesStore, settingsStore, infoPanelStore, treeFoldersStore }) => {
|
||||
({
|
||||
filesStore,
|
||||
settingsStore,
|
||||
infoPanelStore,
|
||||
treeFoldersStore,
|
||||
indexingStore,
|
||||
filesActionsStore,
|
||||
}) => {
|
||||
const {
|
||||
filesList,
|
||||
viewAs,
|
||||
@ -138,6 +149,7 @@ export default inject(
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder } = treeFoldersStore;
|
||||
const { withPaging, currentDeviceType } = settingsStore;
|
||||
const { isIndexEditingMode } = indexingStore;
|
||||
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
|
||||
@ -154,6 +166,8 @@ export default inject(
|
||||
withPaging,
|
||||
highlightFile,
|
||||
currentDeviceType,
|
||||
isIndexEditingMode,
|
||||
changeIndex: filesActionsStore.changeIndex,
|
||||
};
|
||||
},
|
||||
)(observer(FilesRowContainer));
|
||||
|
@ -216,6 +216,7 @@ const FilesRowContent = ({
|
||||
isDefaultRoomsQuotaSet,
|
||||
isStatisticsAvailable,
|
||||
showStorageInfo,
|
||||
isIndexing,
|
||||
}) => {
|
||||
const {
|
||||
contentLength,
|
||||
@ -230,6 +231,7 @@ const FilesRowContent = ({
|
||||
tags,
|
||||
quotaLimit,
|
||||
usedSpace,
|
||||
order,
|
||||
} = item;
|
||||
|
||||
const contentComponent = () => {
|
||||
@ -323,6 +325,17 @@ const FilesRowContent = ({
|
||||
{!isRoom && !isRooms && quickButtons}
|
||||
</div>
|
||||
|
||||
{isIndexing && (
|
||||
<Text
|
||||
containerMinWidth="200px"
|
||||
containerWidth="15%"
|
||||
fontSize="12px"
|
||||
fontWeight={400}
|
||||
className="row_update-text"
|
||||
>
|
||||
{`${t("Files:Index")} ${order}`}
|
||||
</Text>
|
||||
)}
|
||||
{mainInfo && (
|
||||
<Text
|
||||
containerMinWidth="200px"
|
||||
@ -352,7 +365,13 @@ const FilesRowContent = ({
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ currentQuotaStore, settingsStore, treeFoldersStore, filesStore }) => {
|
||||
({
|
||||
currentQuotaStore,
|
||||
settingsStore,
|
||||
treeFoldersStore,
|
||||
filesStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const { filter, roomsFilter } = filesStore;
|
||||
const { isRecycleBinFolder, isRoomsFolder, isArchiveFolder } =
|
||||
treeFoldersStore;
|
||||
@ -360,6 +379,8 @@ export default inject(
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const filterSortBy = isRooms ? roomsFilter.sortBy : filter.sortBy;
|
||||
|
||||
const { isIndexing } = indexingStore;
|
||||
|
||||
const { isDefaultRoomsQuotaSet, isStatisticsAvailable, showStorageInfo } =
|
||||
currentQuotaStore;
|
||||
return {
|
||||
@ -369,6 +390,7 @@ export default inject(
|
||||
isDefaultRoomsQuotaSet,
|
||||
isStatisticsAvailable,
|
||||
showStorageInfo,
|
||||
isIndexing,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -68,7 +68,10 @@ const StyledWrapper = styled.div`
|
||||
`1px ${props.theme.filesSection.tableView.row.borderColor} solid`};
|
||||
margin-top: -1px;
|
||||
|
||||
${(props) => (props.checked || props.isActive) && checkedStyle};
|
||||
${(props) =>
|
||||
(props.checked || props.isActive) &&
|
||||
!props.isIndexEditingMode &&
|
||||
checkedStyle};
|
||||
${(props) =>
|
||||
(props.checked || props.isActive) &&
|
||||
props.isFirstElem &&
|
||||
@ -77,9 +80,20 @@ const StyledWrapper = styled.div`
|
||||
`${props.theme.filesSection.tableView.row.borderColor} !important`};
|
||||
`};
|
||||
|
||||
${(props) =>
|
||||
props.isIndexUpdated &&
|
||||
css`
|
||||
background: ${(props) =>
|
||||
props.isIndexEditingMode
|
||||
? `${props.theme.filesSection.tableView.row.indexUpdate} !important`
|
||||
: `${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
${marginStyles}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
!isMobile &&
|
||||
!props.isDragging &&
|
||||
!props.isIndexEditingMode &&
|
||||
css`
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
@ -87,6 +101,18 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
`};
|
||||
|
||||
${(props) =>
|
||||
!isMobile &&
|
||||
props.isIndexEditingMode &&
|
||||
css`
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
props.theme.filesSection.tableView.row.indexActive};
|
||||
${marginStyles}
|
||||
}
|
||||
`};
|
||||
|
||||
${(props) =>
|
||||
props.showHotkeyBorder &&
|
||||
css`
|
||||
@ -335,6 +361,7 @@ StyledSimpleFilesRow.defaultProps = { theme: Base };
|
||||
|
||||
const SimpleFilesRow = (props) => {
|
||||
const {
|
||||
t,
|
||||
item,
|
||||
sectionWidth,
|
||||
dragging,
|
||||
@ -368,6 +395,9 @@ const SimpleFilesRow = (props) => {
|
||||
itemIndex,
|
||||
badgeUrl,
|
||||
canDrag,
|
||||
isIndexEditingMode,
|
||||
changeIndex,
|
||||
isIndexUpdated,
|
||||
} = props;
|
||||
|
||||
const isMobileDevice = isMobileUtile();
|
||||
@ -377,6 +407,10 @@ const SimpleFilesRow = (props) => {
|
||||
const withAccess = item.security?.Lock;
|
||||
const isSmallContainer = sectionWidth <= 500;
|
||||
|
||||
const onChangeIndex = (action) => {
|
||||
return changeIndex(action, item, t);
|
||||
};
|
||||
|
||||
const element = (
|
||||
<ItemIcon
|
||||
id={item.id}
|
||||
@ -433,6 +467,8 @@ const SimpleFilesRow = (props) => {
|
||||
checked={checkedProps}
|
||||
isActive={isActive}
|
||||
showHotkeyBorder={showHotkeyBorder}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
isIndexUpdated={isIndexUpdated}
|
||||
isFirstElem={itemIndex === 0}
|
||||
isHighlight={isHighlight}
|
||||
>
|
||||
@ -468,6 +504,8 @@ const SimpleFilesRow = (props) => {
|
||||
contextButtonSpacerWidth={displayShareButton}
|
||||
dragging={dragging && isDragging}
|
||||
isDragging={dragging}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
onChangeIndex={onChangeIndex}
|
||||
isActive={isActive}
|
||||
inProgress={inProgress}
|
||||
isThirdPartyFolder={item.isThirdPartyFolder}
|
||||
|
@ -74,11 +74,19 @@ const contextMenuWrapperDraggingStyle = css`
|
||||
const StyledTableRow = styled(TableRow)`
|
||||
.table-container_cell:not(.table-container_element-wrapper) {
|
||||
border-top: ${(props) =>
|
||||
!props.isIndexEditingMode &&
|
||||
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
|
||||
margin-top: -1px;
|
||||
border-left: 0; //for Safari
|
||||
border-right: 0; //for Safari
|
||||
}
|
||||
${(props) =>
|
||||
props.isIndexEditingMode &&
|
||||
css`
|
||||
.table-container_element {
|
||||
display: flex !important;
|
||||
}
|
||||
`}
|
||||
|
||||
.table-container_cell:not(.table-container_element-wrapper) {
|
||||
height: auto;
|
||||
@ -107,14 +115,18 @@ const StyledTableRow = styled(TableRow)`
|
||||
`}
|
||||
${(props) =>
|
||||
!props.isDragging &&
|
||||
!props.isIndexUpdated &&
|
||||
css`
|
||||
:hover {
|
||||
.table-container_cell {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
props.isIndexEditingMode
|
||||
? `${props.theme.filesSection.tableView.row.indexActive} !important`
|
||||
: `${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
}
|
||||
.table-container_file-name-cell {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
@ -126,6 +138,7 @@ const StyledTableRow = styled(TableRow)`
|
||||
padding-left: 24px;
|
||||
`}
|
||||
}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
@ -140,9 +153,49 @@ const StyledTableRow = styled(TableRow)`
|
||||
}
|
||||
}
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.isIndexUpdated &&
|
||||
css`
|
||||
.table-container_cell {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
props.isIndexEditingMode
|
||||
? `${props.theme.filesSection.tableView.row.indexUpdate} !important`
|
||||
: `${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
}
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: -24px;
|
||||
padding-right: 24px;
|
||||
`
|
||||
: css`
|
||||
margin-left: -24px;
|
||||
padding-left: 24px;
|
||||
`}
|
||||
}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: -20px;
|
||||
padding-left: 20px !important;
|
||||
`
|
||||
: css`
|
||||
margin-right: -20px;
|
||||
padding-right: 20px !important;
|
||||
`}
|
||||
}
|
||||
`}
|
||||
.table-container_cell {
|
||||
background: ${(props) =>
|
||||
(props.checked || props.isActive) &&
|
||||
!props.isIndexUpdated &&
|
||||
!props.isIndexEditingMode &&
|
||||
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
cursor: ${(props) =>
|
||||
!props.isThirdPartyFolder &&
|
||||
@ -219,7 +272,8 @@ const StyledTableRow = styled(TableRow)`
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.table-container_file-name-cell {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${(props) =>
|
||||
props.showHotkeyBorder &&
|
||||
css`
|
||||
@ -239,6 +293,30 @@ const StyledTableRow = styled(TableRow)`
|
||||
${(props) => props.dragging && rowCheckboxDraggingStyle};
|
||||
}
|
||||
|
||||
.table-container_element-wrapper {
|
||||
${(props) =>
|
||||
props.isIndexing &&
|
||||
css`
|
||||
margin-left: 0px;
|
||||
padding-left: 0px;
|
||||
`}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.isIndexing &&
|
||||
css`
|
||||
.table-container_file-name-cell {
|
||||
margin-left: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
&:hover {
|
||||
.table-container_file-name-cell {
|
||||
margin-left: 0px !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
}
|
||||
`}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
@ -281,6 +359,10 @@ const StyledTableRow = styled(TableRow)`
|
||||
padding-inline: 0 8px;
|
||||
}
|
||||
|
||||
.item-file-name-index {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.isHighlight &&
|
||||
css`
|
||||
@ -298,7 +380,8 @@ const StyledTableRow = styled(TableRow)`
|
||||
}
|
||||
}
|
||||
|
||||
.table-container_file-name-cell {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
|
@ -70,19 +70,28 @@ const StyledTableContainer = styled(TableContainer)`
|
||||
.table-container_file-name-cell {
|
||||
${fileNameCss}
|
||||
}
|
||||
.table-container_index-cell {
|
||||
${fileNameCss}
|
||||
}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${contextCss}
|
||||
}
|
||||
}
|
||||
.table-container_index-cell {
|
||||
margin-right: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.table-row-selected + .table-row-selected {
|
||||
.table-row {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell,
|
||||
.table-container_row-context-menu-wrapper {
|
||||
border-image-slice: 1;
|
||||
}
|
||||
.table-container_file-name-cell {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${fileNameCss}
|
||||
border-left: 0; //for Safari macOS
|
||||
border-right: 0; //for Safari macOS
|
||||
@ -101,7 +110,8 @@ const StyledTableContainer = styled(TableContainer)`
|
||||
|
||||
.files-item:not(.table-row-selected) + .table-row-selected {
|
||||
.table-row {
|
||||
.table-container_file-name-cell {
|
||||
.table-container_file-name-cell,
|
||||
.table-container_index-cell {
|
||||
${fileNameCss}
|
||||
}
|
||||
|
||||
@ -133,11 +143,14 @@ const Table = ({
|
||||
filterTotal,
|
||||
isRooms,
|
||||
isTrashFolder,
|
||||
isIndexEditingMode,
|
||||
withPaging,
|
||||
columnStorageName,
|
||||
columnInfoPanelStorageName,
|
||||
highlightFile,
|
||||
currentDeviceType,
|
||||
onEditIndex,
|
||||
isIndexing,
|
||||
}) => {
|
||||
const [tagCount, setTagCount] = React.useState(null);
|
||||
const [hideColumns, setHideColumns] = React.useState(false);
|
||||
@ -200,6 +213,9 @@ const Table = ({
|
||||
item={item}
|
||||
itemIndex={index}
|
||||
index={index}
|
||||
onEditIndex={onEditIndex}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
isIndexing={isIndexing}
|
||||
setFirsElemChecked={setFirsElemChecked}
|
||||
setHeaderBorder={setHeaderBorder}
|
||||
theme={theme}
|
||||
@ -223,6 +239,8 @@ const Table = ({
|
||||
highlightFile.id,
|
||||
highlightFile.isExst,
|
||||
isTrashFolder,
|
||||
isIndexEditingMode,
|
||||
isIndexing,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -235,6 +253,7 @@ const Table = ({
|
||||
navigate={navigate}
|
||||
location={location}
|
||||
isRooms={isRooms}
|
||||
isIndexing={isIndexing}
|
||||
filesList={filesList}
|
||||
/>
|
||||
|
||||
@ -246,6 +265,7 @@ const Table = ({
|
||||
itemCount={filterTotal}
|
||||
useReactWindow={!withPaging}
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
itemHeight={48}
|
||||
>
|
||||
@ -264,6 +284,9 @@ export default inject(
|
||||
tableStore,
|
||||
userStore,
|
||||
settingsStore,
|
||||
|
||||
indexingStore,
|
||||
filesActionsStore,
|
||||
}) => {
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
|
||||
@ -285,6 +308,9 @@ export default inject(
|
||||
highlightFile,
|
||||
} = filesStore;
|
||||
|
||||
const { isIndexEditingMode, isIndexing } = indexingStore;
|
||||
const { changeIndex } = filesActionsStore;
|
||||
|
||||
const { withPaging, theme, currentDeviceType } = settingsStore;
|
||||
|
||||
return {
|
||||
@ -301,11 +327,14 @@ export default inject(
|
||||
filterTotal: isRooms ? roomsFilterTotal : filterTotal,
|
||||
isRooms,
|
||||
isTrashFolder,
|
||||
isIndexEditingMode,
|
||||
isIndexing,
|
||||
withPaging,
|
||||
columnStorageName,
|
||||
columnInfoPanelStorageName,
|
||||
highlightFile,
|
||||
currentDeviceType,
|
||||
onEditIndex: changeIndex,
|
||||
};
|
||||
},
|
||||
)(observer(Table));
|
||||
|
@ -54,6 +54,8 @@ class FilesTableHeader extends React.Component {
|
||||
showStorageInfo,
|
||||
isArchiveFolder,
|
||||
tableStorageName,
|
||||
isIndexing,
|
||||
indexColumnSize,
|
||||
} = this.props;
|
||||
|
||||
const defaultColumns = [];
|
||||
@ -357,6 +359,17 @@ class FilesTableHeader extends React.Component {
|
||||
defaultColumns.push(...columns);
|
||||
}
|
||||
|
||||
if (isIndexing) {
|
||||
defaultColumns.unshift({
|
||||
key: "Index",
|
||||
title: "#",
|
||||
enable: this.props.indexColumnIsEnabled,
|
||||
minWidth: indexColumnSize,
|
||||
resizable: false,
|
||||
isShort: true,
|
||||
});
|
||||
}
|
||||
|
||||
let columns = getColumns(defaultColumns);
|
||||
const storageColumns = localStorage.getItem(tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
@ -426,11 +439,15 @@ class FilesTableHeader extends React.Component {
|
||||
columnInfoPanelStorageName,
|
||||
isRecentTab,
|
||||
isArchiveFolder,
|
||||
isIndexEditingMode,
|
||||
showStorageInfo,
|
||||
indexColumnSize,
|
||||
} = this.props;
|
||||
|
||||
if (
|
||||
isArchiveFolder !== prevProps.isArchiveFolder ||
|
||||
indexColumnSize !== prevProps.indexColumnSize ||
|
||||
isIndexEditingMode !== prevProps.isIndexEditingMode ||
|
||||
isRooms !== prevProps.isRooms ||
|
||||
isTrashFolder !== prevProps.isTrashFolder ||
|
||||
columnStorageName !== prevProps.columnStorageName ||
|
||||
@ -543,6 +560,9 @@ class FilesTableHeader extends React.Component {
|
||||
setHideColumns,
|
||||
isFrame,
|
||||
showSettings,
|
||||
|
||||
isIndexing,
|
||||
isIndexEditingMode,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@ -568,7 +588,9 @@ class FilesTableHeader extends React.Component {
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
sectionWidth={sectionWidth}
|
||||
resetColumnsSize={resetColumnsSize}
|
||||
sortingVisible={sortingVisible}
|
||||
isIndexing={isIndexing}
|
||||
sortingVisible={isIndexing ? false : sortingVisible}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
useReactWindow={!withPaging}
|
||||
tagRef={tagRef}
|
||||
@ -592,11 +614,14 @@ export default inject(
|
||||
clientLoadingStore,
|
||||
infoPanelStore,
|
||||
currentQuotaStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
|
||||
const { isDefaultRoomsQuotaSet, showStorageInfo } = currentQuotaStore;
|
||||
|
||||
const { isIndexEditingMode, isIndexing } = indexingStore;
|
||||
|
||||
const {
|
||||
isHeaderChecked,
|
||||
|
||||
@ -607,6 +632,7 @@ export default inject(
|
||||
headerBorder,
|
||||
roomsFilter,
|
||||
setRoomsFilter,
|
||||
indexColumnSize,
|
||||
} = filesStore;
|
||||
const { isRecentTab, isArchiveFolder, isTrashFolder } = treeFoldersStore;
|
||||
const withContent = canShare;
|
||||
@ -627,6 +653,7 @@ export default inject(
|
||||
roomColumnIsEnabled,
|
||||
erasureColumnIsEnabled,
|
||||
sizeColumnIsEnabled,
|
||||
indexColumnIsEnabled,
|
||||
sizeTrashColumnIsEnabled,
|
||||
typeColumnIsEnabled,
|
||||
typeTrashColumnIsEnabled,
|
||||
@ -655,6 +682,8 @@ export default inject(
|
||||
withContent,
|
||||
sortingVisible,
|
||||
|
||||
isIndexing,
|
||||
|
||||
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
|
||||
|
||||
roomsFilter,
|
||||
@ -678,6 +707,7 @@ export default inject(
|
||||
roomColumnIsEnabled,
|
||||
erasureColumnIsEnabled,
|
||||
sizeColumnIsEnabled,
|
||||
indexColumnIsEnabled,
|
||||
sizeTrashColumnIsEnabled,
|
||||
typeColumnIsEnabled,
|
||||
typeTrashColumnIsEnabled,
|
||||
@ -704,6 +734,9 @@ export default inject(
|
||||
isDefaultRoomsQuotaSet,
|
||||
showStorageInfo,
|
||||
isArchiveFolder,
|
||||
isIndexEditingMode,
|
||||
|
||||
indexColumnSize,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -65,6 +65,8 @@ const FilesTableRow = (props) => {
|
||||
id,
|
||||
isRooms,
|
||||
isTrashFolder,
|
||||
isIndexEditingMode,
|
||||
isIndexing,
|
||||
isHighlight,
|
||||
hideColumns,
|
||||
onDragOver,
|
||||
@ -72,7 +74,10 @@ const FilesTableRow = (props) => {
|
||||
badgeUrl,
|
||||
isRecentTab,
|
||||
canDrag,
|
||||
onEditIndex,
|
||||
isIndexUpdated,
|
||||
} = props;
|
||||
|
||||
const { acceptBackground, background } = theme.dragAndDrop;
|
||||
|
||||
const element = (
|
||||
@ -99,7 +104,7 @@ const FilesTableRow = (props) => {
|
||||
const dragStyles = {
|
||||
style: {
|
||||
background:
|
||||
dragging && isDragging
|
||||
dragging && isDragging && !isIndexEditingMode
|
||||
? isDragActive
|
||||
? acceptBackground
|
||||
: background
|
||||
@ -107,6 +112,10 @@ const FilesTableRow = (props) => {
|
||||
},
|
||||
};
|
||||
|
||||
const onChangeIndex = (action) => {
|
||||
return onEditIndex(action, item, t);
|
||||
};
|
||||
|
||||
const onDragOverEvent = (dragActive, e) => {
|
||||
onDragOver && onDragOver(e);
|
||||
|
||||
@ -140,6 +149,13 @@ const FilesTableRow = (props) => {
|
||||
? `${item.id}_${item.fileExst}`
|
||||
: item.id ?? "";
|
||||
|
||||
const contextOptionProps = isIndexEditingMode
|
||||
? {}
|
||||
: {
|
||||
contextOptions: item.contextOptions,
|
||||
getContextModel,
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledDragAndDrop
|
||||
id={id}
|
||||
@ -163,16 +179,18 @@ const FilesTableRow = (props) => {
|
||||
selectionProp={selectionProp}
|
||||
key={item.id}
|
||||
fileContextClick={fileContextClick}
|
||||
onClick={onMouseClick}
|
||||
onClick={isIndexEditingMode ? () => {} : onMouseClick}
|
||||
onChangeIndex={onChangeIndex}
|
||||
isActive={isActive}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
inProgress={inProgress}
|
||||
isFolder={item.isFolder}
|
||||
onHideContextMenu={onHideContextMenu}
|
||||
isThirdPartyFolder={item.isThirdPartyFolder}
|
||||
onDoubleClick={onDoubleClick}
|
||||
checked={checkedProps}
|
||||
contextOptions={item.contextOptions}
|
||||
getContextModel={getContextModel}
|
||||
onDoubleClick={isIndexEditingMode ? () => {} : onDoubleClick}
|
||||
checked={checkedProps || isIndexUpdated}
|
||||
isIndexing={isIndexing}
|
||||
isIndexUpdated={isIndexUpdated}
|
||||
showHotkeyBorder={showHotkeyBorder}
|
||||
title={
|
||||
item.isFolder
|
||||
@ -184,6 +202,7 @@ const FilesTableRow = (props) => {
|
||||
hideColumns={hideColumns}
|
||||
badgeUrl={badgeUrl}
|
||||
canDrag={canDrag}
|
||||
{...contextOptionProps}
|
||||
>
|
||||
{isRooms ? (
|
||||
<RoomsRowDataComponent
|
||||
|
@ -27,6 +27,7 @@
|
||||
import React from "react";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { classNames } from "@docspace/shared/utils";
|
||||
import { TableCell } from "@docspace/shared/components/table";
|
||||
import { Loader } from "@docspace/shared/components/loader";
|
||||
|
||||
@ -40,6 +41,7 @@ const FileNameCell = ({
|
||||
theme,
|
||||
t,
|
||||
inProgress,
|
||||
isIndexEditingMode,
|
||||
}) => {
|
||||
const { title, viewAccessibility } = item;
|
||||
|
||||
@ -49,6 +51,9 @@ const FileNameCell = ({
|
||||
|
||||
const isMedia = viewAccessibility?.ImageView || viewAccessibility?.MediaView;
|
||||
|
||||
const indexingClass = isIndexEditingMode ? "item-file-name-index" : "";
|
||||
const linkProps = isIndexEditingMode ? null : { ...linkStyles };
|
||||
|
||||
return (
|
||||
<>
|
||||
{inProgress ? (
|
||||
@ -59,31 +64,35 @@ const FileNameCell = ({
|
||||
/>
|
||||
) : (
|
||||
<TableCell
|
||||
className="table-container_element-wrapper"
|
||||
className={classNames("table-container_element-wrapper", {
|
||||
["table-container-index"]: isIndexEditingMode,
|
||||
})}
|
||||
style={{background: "none !important"}}
|
||||
hasAccess={true}
|
||||
checked={checked}
|
||||
>
|
||||
<div className="table-container_element-container">
|
||||
<div className="table-container_element">{element}</div>
|
||||
<Checkbox
|
||||
className="table-container_row-checkbox"
|
||||
onChange={onChange}
|
||||
isChecked={checked}
|
||||
title={t("Common:TitleSelectFile")}
|
||||
/>
|
||||
{!isIndexEditingMode && (
|
||||
<Checkbox
|
||||
className="table-container_row-checkbox"
|
||||
onChange={onChange}
|
||||
isChecked={checked}
|
||||
title={t("Common:TitleSelectFile")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</TableCell>
|
||||
)}
|
||||
|
||||
<Link
|
||||
type="page"
|
||||
title={title}
|
||||
fontWeight="600"
|
||||
fontSize="13px"
|
||||
{...linkStyles}
|
||||
color={theme.filesSection.tableView.fileName.linkColor}
|
||||
isTextOverflow
|
||||
className="item-file-name"
|
||||
{...linkProps}
|
||||
className={`item-file-name ${indexingClass}`}
|
||||
dir="auto"
|
||||
>
|
||||
{titleWithoutExt}
|
||||
|
@ -0,0 +1,46 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React from "react";
|
||||
import { StyledText } from "./CellStyles";
|
||||
|
||||
const IndexCell = ({ t, item, sideColor }) => {
|
||||
const { order } = item;
|
||||
|
||||
return (
|
||||
<StyledText
|
||||
color={sideColor}
|
||||
fontSize="12px"
|
||||
fontWeight={600}
|
||||
title={order}
|
||||
style={{ marginRight: 0 }}
|
||||
>
|
||||
{order}
|
||||
</StyledText>
|
||||
);
|
||||
};
|
||||
|
||||
export default IndexCell;
|
@ -32,7 +32,9 @@ import TypeCell from "./TypeCell";
|
||||
import AuthorCell from "./AuthorCell";
|
||||
import DateCell from "./DateCell";
|
||||
import SizeCell from "./SizeCell";
|
||||
import IndexCell from "./IndexCell";
|
||||
import { classNames, getLastColumn } from "@docspace/shared/utils";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
import {
|
||||
StyledBadgesContainer,
|
||||
StyledQuickButtonsContainer,
|
||||
@ -45,6 +47,7 @@ const RowDataComponent = (props) => {
|
||||
modifiedColumnIsEnabled,
|
||||
sizeColumnIsEnabled,
|
||||
typeColumnIsEnabled,
|
||||
indexColumnIsEnabled,
|
||||
quickButtonsColumnIsEnabled,
|
||||
|
||||
dragStyles,
|
||||
@ -58,6 +61,8 @@ const RowDataComponent = (props) => {
|
||||
showHotkeyBorder,
|
||||
badgesComponent,
|
||||
quickButtonsComponent,
|
||||
|
||||
isIndexing,
|
||||
tableStorageName,
|
||||
} = props;
|
||||
|
||||
@ -65,6 +70,24 @@ const RowDataComponent = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{indexColumnIsEnabled && isIndexing && (
|
||||
<TableCell
|
||||
className={classNames(
|
||||
selectionProp?.className,
|
||||
"table-container_index-cell",
|
||||
)}
|
||||
style={
|
||||
!indexColumnIsEnabled ? { background: "none" } : dragStyles.style
|
||||
}
|
||||
value={value}
|
||||
>
|
||||
<IndexCell
|
||||
sideColor={theme.filesSection.tableView.row.sideColor}
|
||||
{...props}
|
||||
/>
|
||||
</TableCell>
|
||||
)}
|
||||
|
||||
<TableCell
|
||||
{...dragStyles}
|
||||
className={classNames(
|
||||
@ -214,24 +237,30 @@ const RowDataComponent = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ tableStore }) => {
|
||||
export default inject(({ tableStore, indexingStore }) => {
|
||||
const {
|
||||
authorColumnIsEnabled,
|
||||
createdColumnIsEnabled,
|
||||
modifiedColumnIsEnabled,
|
||||
sizeColumnIsEnabled,
|
||||
indexColumnIsEnabled,
|
||||
typeColumnIsEnabled,
|
||||
quickButtonsColumnIsEnabled,
|
||||
tableStorageName,
|
||||
} = tableStore;
|
||||
|
||||
const { isIndexing } = indexingStore;
|
||||
|
||||
return {
|
||||
authorColumnIsEnabled,
|
||||
createdColumnIsEnabled,
|
||||
modifiedColumnIsEnabled,
|
||||
sizeColumnIsEnabled,
|
||||
indexColumnIsEnabled,
|
||||
typeColumnIsEnabled,
|
||||
quickButtonsColumnIsEnabled,
|
||||
|
||||
isIndexing,
|
||||
tableStorageName,
|
||||
};
|
||||
})(observer(RowDataComponent));
|
||||
|
@ -38,9 +38,13 @@ import withHotkeys from "../../../../HOCs/withHotkeys";
|
||||
import { Consumer, isMobile, isTablet } from "@docspace/shared/utils";
|
||||
import { isElementInViewport } from "@docspace/shared/utils/common";
|
||||
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import { DeviceType, VDRIndexingAction } from "@docspace/shared/enums";
|
||||
|
||||
const separatorStyles = `width: 100vw; position: absolute; height: 3px; z-index: 1;`;
|
||||
const sectionClass = "section-wrapper-content";
|
||||
|
||||
let currentDroppable = null;
|
||||
let droppableSeparator = null;
|
||||
let isDragActive = false;
|
||||
|
||||
const SectionBodyContent = (props) => {
|
||||
@ -71,6 +75,8 @@ const SectionBodyContent = (props) => {
|
||||
isEmptyPage,
|
||||
movingInProgress,
|
||||
currentDeviceType,
|
||||
isIndexEditingMode,
|
||||
changeIndex,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
@ -203,7 +209,23 @@ const SectionBodyContent = (props) => {
|
||||
return;
|
||||
}
|
||||
|
||||
droppableSeparator && droppableSeparator.remove();
|
||||
|
||||
const droppable = wrapperElement.closest(".droppable");
|
||||
const tableItem = wrapperElement.closest(".table-list-item");
|
||||
const styles = tableItem && window.getComputedStyle(tableItem);
|
||||
const indexSeparatorNode = document.createElement("div");
|
||||
indexSeparatorNode.classList.add("indexing-separator");
|
||||
|
||||
const parent = document.querySelector(
|
||||
".ReactVirtualized__Grid__innerScrollContainer",
|
||||
);
|
||||
|
||||
if (styles) {
|
||||
indexSeparatorNode.setAttribute("style", separatorStyles);
|
||||
indexSeparatorNode.style.top = styles.top;
|
||||
}
|
||||
|
||||
if (currentDroppable !== droppable) {
|
||||
if (currentDroppable) {
|
||||
if (viewAs === "table") {
|
||||
@ -213,12 +235,15 @@ const SectionBodyContent = (props) => {
|
||||
for (let cl of classElements) {
|
||||
cl.classList.remove("droppable-hover");
|
||||
}
|
||||
if (isIndexEditingMode) {
|
||||
droppableSeparator.remove();
|
||||
}
|
||||
} else {
|
||||
currentDroppable.classList.remove("droppable-hover");
|
||||
}
|
||||
}
|
||||
currentDroppable = droppable;
|
||||
|
||||
droppableSeparator = indexSeparatorNode;
|
||||
if (currentDroppable) {
|
||||
if (viewAs === "table") {
|
||||
const value = currentDroppable.getAttribute("value");
|
||||
@ -231,17 +256,38 @@ const SectionBodyContent = (props) => {
|
||||
cl.classList.add("droppable-hover");
|
||||
}
|
||||
}
|
||||
if (isIndexEditingMode) {
|
||||
parent.insertBefore(indexSeparatorNode, tableItem);
|
||||
}
|
||||
} else {
|
||||
currentDroppable.classList.add("droppable-hover");
|
||||
currentDroppable = droppable;
|
||||
droppableSeparator = indexSeparatorNode;
|
||||
}
|
||||
}
|
||||
} else if (isIndexEditingMode) {
|
||||
droppableSeparator && droppableSeparator.remove();
|
||||
|
||||
const wrappedClass = wrapperElement && wrapperElement.className;
|
||||
droppableSeparator = indexSeparatorNode;
|
||||
|
||||
if (wrappedClass === sectionClass) {
|
||||
indexSeparatorNode.setAttribute(
|
||||
"style",
|
||||
separatorStyles + "bottom: 0px;",
|
||||
);
|
||||
return parent.append(indexSeparatorNode);
|
||||
}
|
||||
|
||||
parent.insertBefore(indexSeparatorNode, tableItem);
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = (e) => {
|
||||
setStartDrag(false);
|
||||
|
||||
droppableSeparator && droppableSeparator.remove();
|
||||
|
||||
setTimeout(() => {
|
||||
isDragActive = false;
|
||||
setDragging(false);
|
||||
@ -254,17 +300,48 @@ const SectionBodyContent = (props) => {
|
||||
const isDragging = splitValue && splitValue.includes("dragging");
|
||||
const treeValue = isDragging ? splitValue[0] : null;
|
||||
|
||||
const elem = e.target.closest(".droppable");
|
||||
const elem = isIndexEditingMode
|
||||
? e.target.closest(".files-item") || e.target.closest(`.${sectionClass}`)
|
||||
: e.target.closest(".droppable");
|
||||
|
||||
const title = elem && elem.dataset.title;
|
||||
const value = elem && elem.getAttribute("value");
|
||||
if ((!value && !treeValue) || isRecycleBinFolder || !isDragActive) {
|
||||
if (
|
||||
((!value && !treeValue) || isRecycleBinFolder || !isDragActive) &&
|
||||
!isIndexEditingMode
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const folderId = value
|
||||
? value.split("_").slice(1, -3).join("_")
|
||||
: treeValue;
|
||||
onMoveTo(folderId, title);
|
||||
|
||||
if (!isIndexEditingMode) return onMoveTo(folderId, title);
|
||||
if (filesList.length === 1) return;
|
||||
|
||||
const replaceableItemId = isNaN(+folderId) ? folderId : +folderId;
|
||||
|
||||
const replaceableItemType = value && value.split("_").slice(0, 1).join("_");
|
||||
const isSectionTarget = elem && elem.className === sectionClass;
|
||||
|
||||
let replaceable;
|
||||
const item = isSectionTarget
|
||||
? filesList[filesList.length - 1]
|
||||
: filesList.find((i) =>
|
||||
replaceableItemType === "file"
|
||||
? i.id === replaceableItemId && i.fileExst
|
||||
: i.id === replaceableItemId,
|
||||
);
|
||||
|
||||
replaceable = item;
|
||||
if (item === filesList[filesList.length - 1] && !isSectionTarget) {
|
||||
replaceable = filesList[filesList.length - 2];
|
||||
}
|
||||
|
||||
if (!replaceable) return;
|
||||
|
||||
changeIndex(VDRIndexingAction.MoveIndex, replaceable, t);
|
||||
return;
|
||||
};
|
||||
|
||||
@ -340,6 +417,7 @@ export default inject(
|
||||
treeFoldersStore,
|
||||
filesActionsStore,
|
||||
uploadDataStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const {
|
||||
isEmptyFilesList,
|
||||
@ -372,6 +450,7 @@ export default inject(
|
||||
setTooltipPosition,
|
||||
isRecycleBinFolder: treeFoldersStore.isRecycleBinFolder,
|
||||
moveDragItems: filesActionsStore.moveDragItems,
|
||||
changeIndex: filesActionsStore.changeIndex,
|
||||
viewAs,
|
||||
setSelection,
|
||||
setBufferSelection,
|
||||
@ -387,6 +466,7 @@ export default inject(
|
||||
movingInProgress,
|
||||
currentDeviceType: settingsStore.currentDeviceType,
|
||||
isEmptyPage,
|
||||
isIndexEditingMode: indexingStore.isIndexEditingMode,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -316,6 +316,8 @@ const SectionFilterContent = ({
|
||||
isTrash,
|
||||
userId,
|
||||
isPersonalRoom,
|
||||
isIndexing,
|
||||
isIndexEditingMode,
|
||||
|
||||
providers,
|
||||
|
||||
@ -2663,6 +2665,8 @@ const SectionFilterContent = ({
|
||||
isPeopleAccounts={isPeopleAccounts}
|
||||
isGroupsAccounts={isGroupsAccounts}
|
||||
isInsideGroup={isInsideGroup}
|
||||
isIndexing={isIndexing}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
disableThirdParty={isTrash}
|
||||
/>
|
||||
);
|
||||
@ -2681,6 +2685,7 @@ export default inject(
|
||||
userStore,
|
||||
settingsStore,
|
||||
currentQuotaStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const {
|
||||
filter,
|
||||
@ -2720,6 +2725,7 @@ export default inject(
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
const { showStorageInfo, isDefaultRoomsQuotaSet } = currentQuotaStore;
|
||||
|
||||
const { isIndexing, isIndexEditingMode } = indexingStore;
|
||||
const {
|
||||
filterStore,
|
||||
|
||||
@ -2759,6 +2765,8 @@ export default inject(
|
||||
isRooms,
|
||||
isTrash,
|
||||
isArchiveFolder,
|
||||
isIndexing,
|
||||
isIndexEditingMode,
|
||||
|
||||
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
|
||||
showFilterLoader: clientLoadingStore.showFilterLoader,
|
||||
|
@ -51,6 +51,7 @@ import {
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
import TariffBar from "SRC_DIR/components/TariffBar";
|
||||
import IndexMenu from "../IndexHeader";
|
||||
import { getLifetimePeriodTranslation } from "@docspace/shared/utils/common";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -172,6 +173,7 @@ const SectionHeaderContent = (props) => {
|
||||
t,
|
||||
isRoomsFolder,
|
||||
security,
|
||||
setIsIndexEditingMode,
|
||||
tReady,
|
||||
isInfoPanelVisible,
|
||||
isRootFolder,
|
||||
@ -185,6 +187,7 @@ const SectionHeaderContent = (props) => {
|
||||
isArchiveFolder,
|
||||
isEmptyFilesList,
|
||||
isHeaderVisible,
|
||||
isIndexEditingMode,
|
||||
isHeaderChecked,
|
||||
isHeaderIndeterminate,
|
||||
showText,
|
||||
@ -238,11 +241,13 @@ const SectionHeaderContent = (props) => {
|
||||
onCreateAndCopySharedLink,
|
||||
showNavigationButton,
|
||||
startUpload,
|
||||
reorder,
|
||||
getFolderModel,
|
||||
onCreateRoom,
|
||||
onEmptyTrashAction,
|
||||
getHeaderOptions,
|
||||
setBufferSelection,
|
||||
setReorderDialogVisible,
|
||||
} = props;
|
||||
|
||||
const location = useLocation();
|
||||
@ -407,6 +412,12 @@ const SectionHeaderContent = (props) => {
|
||||
isMobileView: currentDeviceType === DeviceType.mobile,
|
||||
};
|
||||
|
||||
const indexMenuProps = {
|
||||
setIsIndexEditingMode,
|
||||
t,
|
||||
setReorderDialogVisible,
|
||||
};
|
||||
|
||||
if (isAccountsPage && !(isGroupsPage && isRoomAdmin)) {
|
||||
tableGroupMenuVisible =
|
||||
(!isGroupsPage ? isAccountsHeaderVisible : isGroupsHeaderVisible) &&
|
||||
@ -517,6 +528,8 @@ const SectionHeaderContent = (props) => {
|
||||
>
|
||||
{tableGroupMenuVisible ? (
|
||||
<TableGroupMenu {...tableGroupMenuProps} withComboBox />
|
||||
) : isIndexEditingMode ? (
|
||||
<IndexMenu {...indexMenuProps} />
|
||||
) : (
|
||||
<div className="header-container">
|
||||
<Navigation
|
||||
@ -624,6 +637,8 @@ export default inject(
|
||||
userStore,
|
||||
settingsStore,
|
||||
uploadDataStore,
|
||||
indexingStore,
|
||||
dialogsStore,
|
||||
}) => {
|
||||
const { startUpload } = uploadDataStore;
|
||||
const isRoomAdmin = userStore.user?.isRoomAdmin;
|
||||
@ -662,12 +677,15 @@ export default inject(
|
||||
const { isRecycleBinFolder, isRoomsFolder, isArchiveFolder } =
|
||||
treeFoldersStore;
|
||||
|
||||
const { setReorderDialogVisible } = dialogsStore;
|
||||
|
||||
const {
|
||||
getHeaderMenu,
|
||||
isGroupMenuBlocked,
|
||||
moveToRoomsPage,
|
||||
onClickBack,
|
||||
moveToPublicRoom,
|
||||
reorder,
|
||||
} = filesActionsStore;
|
||||
|
||||
const { setIsVisible, isVisible } = infoPanelStore;
|
||||
@ -731,6 +749,7 @@ export default inject(
|
||||
getCheckboxItemLabel: getAccountsCheckboxItemLabel,
|
||||
} = headerMenuStore;
|
||||
|
||||
const { isIndexEditingMode, setIsIndexEditingMode } = indexingStore;
|
||||
const { setSelected: setAccountsSelected } = selectionStore;
|
||||
const { isPublicRoom } = publicRoomStore;
|
||||
|
||||
@ -773,6 +792,8 @@ export default inject(
|
||||
setIsInfoPanelVisible: setIsVisible,
|
||||
isInfoPanelVisible: isVisible,
|
||||
isHeaderVisible,
|
||||
isIndexEditingMode,
|
||||
setIsIndexEditingMode,
|
||||
isHeaderIndeterminate,
|
||||
isHeaderChecked,
|
||||
isTabletView: settingsStore.isTabletView,
|
||||
@ -835,11 +856,13 @@ export default inject(
|
||||
onCreateAndCopySharedLink,
|
||||
showNavigationButton,
|
||||
startUpload,
|
||||
reorder,
|
||||
getFolderModel,
|
||||
onCreateRoom,
|
||||
onEmptyTrashAction,
|
||||
getHeaderOptions,
|
||||
setBufferSelection,
|
||||
setReorderDialogVisible,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -0,0 +1,142 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
mobile,
|
||||
tablet,
|
||||
getCorrectBorderRadius,
|
||||
getCorrectFourValuesStyle,
|
||||
} from "@docspace/shared/utils";
|
||||
|
||||
const StyledTableIndexMenu = styled.div`
|
||||
position: relative;
|
||||
|
||||
background: ${(props) => props.theme.tableContainer.groupMenu.background};
|
||||
border-bottom: ${(props) =>
|
||||
props.theme.tableContainer.groupMenu.borderBottom};
|
||||
box-shadow: ${(props) => props.theme.tableContainer.groupMenu.boxShadow};
|
||||
border-radius: ${({ theme }) =>
|
||||
getCorrectBorderRadius("0px 0px 6px 6px", theme.interfaceDirection)};
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
width: 100%;
|
||||
margin: 0px 0px 0px -20px;
|
||||
padding: 0 20px 0 20px;
|
||||
height: 68px;
|
||||
|
||||
z-index: 199;
|
||||
|
||||
@media ${tablet} {
|
||||
height: 60px;
|
||||
}
|
||||
@media ${mobile} {
|
||||
height: 48px;
|
||||
padding: 0px 18px;
|
||||
}
|
||||
|
||||
.table-header_index-separator {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? `border-left: ${props.theme.tableContainer.groupMenu.borderRight};`
|
||||
: `border-right: ${props.theme.tableContainer.groupMenu.borderRight};`}
|
||||
width: 1px;
|
||||
height: 21px;
|
||||
margin: ${({ theme }) =>
|
||||
getCorrectFourValuesStyle("0 16px 0 20px", theme.interfaceDirection)};
|
||||
|
||||
@media ${tablet} {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.table-header_reorder-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.table-header_index-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.table-header_reorder-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.table-header_reorder-container {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.table-header_reorder-icon {
|
||||
svg {
|
||||
path[fill] {
|
||||
fill: ${(props) => props.theme.button.color.base};
|
||||
}
|
||||
|
||||
path[stroke] {
|
||||
stroke: ${(props) => props.theme.button.color.base};
|
||||
}
|
||||
}
|
||||
|
||||
:hover {
|
||||
svg {
|
||||
path[fill] {
|
||||
fill: ${(props) => props.theme.button.color.baseHover};
|
||||
}
|
||||
|
||||
path[stroke] {
|
||||
stroke: ${(props) => props.theme.button.color.baseHover};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:active {
|
||||
svg {
|
||||
path[fill] {
|
||||
fill: ${(props) => props.theme.button.color.baseActive};
|
||||
}
|
||||
|
||||
path[stroke] {
|
||||
stroke: ${(props) => props.theme.button.color.baseActive};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledTableIndexMenu };
|
82
packages/client/src/pages/Home/Section/IndexHeader/index.tsx
Normal file
82
packages/client/src/pages/Home/Section/IndexHeader/index.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { TTranslation } from "@docspace/shared/types";
|
||||
import RoundedArrowSvgUrl from "PUBLIC_DIR/images/rounded arrow.react.svg?url";
|
||||
import CrossIconSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { StyledTableIndexMenu } from "./StyledIndexHeader";
|
||||
|
||||
export interface IndexMenuProps {
|
||||
setIsIndexEditingMode: (mode: boolean) => void;
|
||||
setReorderDialogVisible: (visible: boolean) => void;
|
||||
t: TTranslation;
|
||||
}
|
||||
|
||||
const IndexMenu = ({
|
||||
setIsIndexEditingMode,
|
||||
t,
|
||||
setReorderDialogVisible,
|
||||
}: IndexMenuProps) => {
|
||||
return (
|
||||
<StyledTableIndexMenu>
|
||||
<div className="table-header_index-container">
|
||||
<Text fontSize="14px" lineHeight="16px" fontWeight={600}>
|
||||
{t("Common:SortingIndex")}
|
||||
</Text>
|
||||
|
||||
<div className="table-header_index-separator" />
|
||||
<div
|
||||
className="table-header_reorder-container"
|
||||
onClick={() => setReorderDialogVisible(true)}
|
||||
>
|
||||
<IconButton
|
||||
className="table-header_reorder-icon"
|
||||
size={16}
|
||||
onClick={() => {}}
|
||||
iconName={RoundedArrowSvgUrl}
|
||||
isFill
|
||||
isClickable={false}
|
||||
/>
|
||||
<Text fontSize="12px" lineHeight="16px" fontWeight={600}>
|
||||
{t("Files:Reorder")}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<IconButton
|
||||
className="table-header_cross-icon"
|
||||
size={16}
|
||||
onClick={() => setIsIndexEditingMode(false)}
|
||||
iconName={CrossIconSvgUrl}
|
||||
isFill
|
||||
isClickable={false}
|
||||
/>
|
||||
</StyledTableIndexMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default IndexMenu;
|
@ -39,6 +39,7 @@ const SelectionArea = (props) => {
|
||||
foldersLength,
|
||||
filesLength,
|
||||
isInfoPanelVisible,
|
||||
isIndexEditingMode,
|
||||
} = props;
|
||||
|
||||
const [countTilesInRow, setCountTilesInRow] = useState(getCountTilesInRow());
|
||||
@ -87,7 +88,7 @@ const SelectionArea = (props) => {
|
||||
},
|
||||
];
|
||||
|
||||
return isMobile || dragging ? (
|
||||
return isMobile || dragging || isIndexEditingMode ? (
|
||||
<></>
|
||||
) : (
|
||||
<SelectionAreaComponent
|
||||
@ -107,28 +108,32 @@ const SelectionArea = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ filesStore, treeFoldersStore, infoPanelStore }) => {
|
||||
const {
|
||||
dragging,
|
||||
viewAs,
|
||||
setSelections,
|
||||
getCountTilesInRow,
|
||||
folders,
|
||||
files,
|
||||
} = filesStore;
|
||||
const { isRoomsFolder, isArchiveFolder } = treeFoldersStore;
|
||||
const { isVisible: isInfoPanelVisible } = infoPanelStore;
|
||||
export default inject(
|
||||
({ filesStore, treeFoldersStore, infoPanelStore, indexingStore }) => {
|
||||
const {
|
||||
dragging,
|
||||
viewAs,
|
||||
setSelections,
|
||||
getCountTilesInRow,
|
||||
folders,
|
||||
files,
|
||||
} = filesStore;
|
||||
const { isRoomsFolder, isArchiveFolder } = treeFoldersStore;
|
||||
const { isVisible: isInfoPanelVisible } = infoPanelStore;
|
||||
const { isIndexEditingMode } = indexingStore;
|
||||
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
|
||||
return {
|
||||
dragging,
|
||||
viewAs,
|
||||
setSelections,
|
||||
getCountTilesInRow,
|
||||
isRooms,
|
||||
foldersLength: folders.length,
|
||||
filesLength: files.length,
|
||||
isInfoPanelVisible,
|
||||
};
|
||||
})(observer(SelectionArea));
|
||||
return {
|
||||
dragging,
|
||||
viewAs,
|
||||
setSelections,
|
||||
getCountTilesInRow,
|
||||
isRooms,
|
||||
foldersLength: folders.length,
|
||||
filesLength: files.length,
|
||||
isInfoPanelVisible,
|
||||
isIndexEditingMode,
|
||||
};
|
||||
},
|
||||
)(observer(SelectionArea));
|
||||
|
@ -115,6 +115,7 @@ const PureHome = (props) => {
|
||||
isPrivacyFolder,
|
||||
isRecycleBinFolder,
|
||||
isErrorRoomNotAvailable,
|
||||
isIndexEditingMode,
|
||||
|
||||
primaryProgressDataPercent,
|
||||
primaryProgressDataIcon,
|
||||
@ -351,6 +352,7 @@ const PureHome = (props) => {
|
||||
sectionProps.secondaryProgressBarIcon = secondaryProgressDataStoreIcon;
|
||||
sectionProps.showSecondaryButtonAlert = secondaryProgressDataStoreAlert;
|
||||
sectionProps.getContextModel = getContextModel;
|
||||
sectionProps.isIndexEditingMode = isIndexEditingMode;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -439,6 +441,7 @@ export default inject(
|
||||
currentTariffStatusStore,
|
||||
settingsStore,
|
||||
contextOptionsStore,
|
||||
indexingStore,
|
||||
}) => {
|
||||
const { setSelectedFolder, security: folderSecurity } = selectedFolderStore;
|
||||
const {
|
||||
@ -605,6 +608,7 @@ export default inject(
|
||||
isErrorRoomNotAvailable,
|
||||
isRoomsFolder,
|
||||
isArchiveFolder,
|
||||
isIndexEditingMode: indexingStore.isIndexEditingMode,
|
||||
|
||||
disableDrag,
|
||||
|
||||
|
@ -56,6 +56,7 @@ import UnmuteReactSvgUrl from "PUBLIC_DIR/images/unmute.react.svg?url";
|
||||
import MuteReactSvgUrl from "PUBLIC_DIR/images/icons/16/mute.react.svg?url";
|
||||
import ShareReactSvgUrl from "PUBLIC_DIR/images/share.react.svg?url";
|
||||
import InvitationLinkReactSvgUrl from "PUBLIC_DIR/images/invitation.link.react.svg?url";
|
||||
import EditIndexReactSvgUrl from "PUBLIC_DIR/images/edit.index.react.svg?url";
|
||||
import TabletLinkReactSvgUrl from "PUBLIC_DIR/images/tablet-link.react.svg?url";
|
||||
import MailReactSvgUrl from "PUBLIC_DIR/images/mail.react.svg?url";
|
||||
import RoomArchiveSvgUrl from "PUBLIC_DIR/images/room.archive.svg?url";
|
||||
@ -133,6 +134,7 @@ class ContextOptionsStore {
|
||||
infoPanelStore;
|
||||
currentTariffStatusStore;
|
||||
userStore;
|
||||
indexingStore;
|
||||
clientLoadingStore;
|
||||
|
||||
linksIsLoading = false;
|
||||
@ -154,6 +156,7 @@ class ContextOptionsStore {
|
||||
infoPanelStore,
|
||||
currentTariffStatusStore,
|
||||
userStore,
|
||||
indexingStore,
|
||||
clientLoadingStore,
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
@ -173,6 +176,7 @@ class ContextOptionsStore {
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
this.currentTariffStatusStore = currentTariffStatusStore;
|
||||
this.userStore = userStore;
|
||||
this.indexingStore = indexingStore;
|
||||
this.clientLoadingStore = clientLoadingStore;
|
||||
}
|
||||
|
||||
@ -918,6 +922,10 @@ class ContextOptionsStore {
|
||||
this.filesActionsStore.exportRoomIndex(t, roomId);
|
||||
};
|
||||
|
||||
onEditIndex = () => {
|
||||
this.indexingStore.setIsIndexEditingMode(true);
|
||||
};
|
||||
|
||||
onClickRemoveFromRecent = (item) => {
|
||||
this.filesActionsStore.removeFilesFromRecent([item.id]);
|
||||
};
|
||||
@ -1406,6 +1414,17 @@ class ContextOptionsStore {
|
||||
const isArchive = item.rootFolderType === FolderType.Archive;
|
||||
const isShared = shared || navigationPath.findIndex((r) => r.shared) > -1;
|
||||
|
||||
const { isIndexing } = this.indexingStore;
|
||||
|
||||
const indexOptions = {
|
||||
id: "option_edit-index",
|
||||
key: "edit-index",
|
||||
label: t("Common:EditIndex"),
|
||||
icon: EditIndexReactSvgUrl,
|
||||
onClick: () => this.onEditIndex(),
|
||||
disabled: !isIndexing && item.security?.Edit,
|
||||
};
|
||||
|
||||
const optionsModel = [
|
||||
{
|
||||
id: "option_select",
|
||||
@ -1716,6 +1735,7 @@ class ContextOptionsStore {
|
||||
onClick: this.onRestoreAction,
|
||||
disabled: false,
|
||||
},
|
||||
indexOptions,
|
||||
{
|
||||
id: "option_rename",
|
||||
key: "rename",
|
||||
@ -1797,7 +1817,6 @@ class ContextOptionsStore {
|
||||
disabled: !this.treeFoldersStore.isRecentTab,
|
||||
},
|
||||
];
|
||||
|
||||
const options = this.filterModel(optionsModel, contextOptions);
|
||||
|
||||
const pluginItems = this.onLoadPlugins(item);
|
||||
|
@ -43,6 +43,7 @@ class DialogsStore {
|
||||
ownerPanelVisible = false;
|
||||
moveToPanelVisible = false;
|
||||
restorePanelVisible = false;
|
||||
reorderDialogVisible = false;
|
||||
copyPanelVisible = false;
|
||||
deleteThirdPartyDialogVisible = false;
|
||||
connectDialogVisible = false;
|
||||
@ -519,6 +520,10 @@ class DialogsStore {
|
||||
this.pdfFormEditVisible = visible;
|
||||
this.pdfFormEditData = data;
|
||||
};
|
||||
|
||||
setReorderDialogVisible = (visible) => {
|
||||
this.reorderDialogVisible = visible;
|
||||
};
|
||||
}
|
||||
|
||||
export default DialogsStore;
|
||||
|
@ -54,6 +54,8 @@ import {
|
||||
moveToFolder,
|
||||
getFolder,
|
||||
deleteFilesFromRecent,
|
||||
changeIndex,
|
||||
reorder,
|
||||
} from "@docspace/shared/api/files";
|
||||
import {
|
||||
ConflictResolveType,
|
||||
@ -64,6 +66,7 @@ import {
|
||||
FolderType,
|
||||
RoomsType,
|
||||
ShareAccessRights,
|
||||
VDRIndexingAction,
|
||||
} from "@docspace/shared/enums";
|
||||
import { makeAutoObservable } from "mobx";
|
||||
|
||||
@ -106,6 +109,7 @@ class FilesActionStore {
|
||||
publicRoomStore;
|
||||
infoPanelStore;
|
||||
peopleStore;
|
||||
indexingStore;
|
||||
userStore = null;
|
||||
currentTariffStatusStore = null;
|
||||
currentQuotaStore = null;
|
||||
@ -134,6 +138,7 @@ class FilesActionStore {
|
||||
currentTariffStatusStore,
|
||||
peopleStore,
|
||||
currentQuotaStore,
|
||||
indexingStore,
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
this.settingsStore = settingsStore;
|
||||
@ -153,6 +158,7 @@ class FilesActionStore {
|
||||
this.currentTariffStatusStore = currentTariffStatusStore;
|
||||
this.peopleStore = peopleStore;
|
||||
this.currentQuotaStore = currentQuotaStore;
|
||||
this.indexingStore = indexingStore;
|
||||
}
|
||||
|
||||
setIsBulkDownload = (isBulkDownload) => {
|
||||
@ -2757,6 +2763,71 @@ class FilesActionStore {
|
||||
.itemOperationToFolder(operationData)
|
||||
.catch((error) => toastr.error(error));
|
||||
};
|
||||
changeIndex = async (action, item, t) => {
|
||||
const { filesList } = this.filesStore;
|
||||
|
||||
const index = filesList.findIndex(
|
||||
(elem) => elem.id === item?.id && elem.fileExst === item?.fileExst,
|
||||
);
|
||||
|
||||
if (
|
||||
(action === VDRIndexingAction.HigherIndex && index === 0) ||
|
||||
(action === VDRIndexingAction.LowerIndex &&
|
||||
index === filesList.length - 1)
|
||||
)
|
||||
return;
|
||||
|
||||
const { bufferSelection } = this.filesStore;
|
||||
|
||||
let selection = this.filesStore.selection.length
|
||||
? this.filesStore.selection
|
||||
: [bufferSelection];
|
||||
|
||||
const { id } = this.selectedFolderStore;
|
||||
const { setUpdateItems } = this.indexingStore;
|
||||
|
||||
let replaceable;
|
||||
let current = item;
|
||||
|
||||
switch (action) {
|
||||
case VDRIndexingAction.HigherIndex:
|
||||
replaceable = filesList[index - 1];
|
||||
break;
|
||||
|
||||
case VDRIndexingAction.LowerIndex:
|
||||
replaceable = filesList[index + 1];
|
||||
break;
|
||||
|
||||
default:
|
||||
current = selection[0];
|
||||
replaceable = item;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!replaceable) return;
|
||||
|
||||
try {
|
||||
await changeIndex(current?.id, replaceable.order, current?.isFolder);
|
||||
|
||||
const items = [current, replaceable];
|
||||
setUpdateItems(items);
|
||||
|
||||
const operationId = uniqueid("operation_");
|
||||
this.updateCurrentFolder(null, [id], true, operationId);
|
||||
} catch (e) {
|
||||
toastr.error(t("Files:ErrorChangeIndex"));
|
||||
}
|
||||
};
|
||||
|
||||
reorder = async (id, t) => {
|
||||
try {
|
||||
const operationId = uniqueid("operation_");
|
||||
await reorder(id);
|
||||
this.updateCurrentFolder(null, [id], true, operationId);
|
||||
} catch (e) {
|
||||
toastr.error(t("Files:ErrorChangeIndex"));
|
||||
}
|
||||
};
|
||||
|
||||
checkExportRoomIndexProgress = async () => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
|
@ -96,6 +96,7 @@ class FilesStore {
|
||||
publicRoomStore;
|
||||
settingsStore;
|
||||
currentQuotaStore;
|
||||
indexingStore;
|
||||
|
||||
pluginStore;
|
||||
|
||||
@ -200,6 +201,7 @@ class FilesStore {
|
||||
userStore,
|
||||
currentTariffStatusStore,
|
||||
settingsStore,
|
||||
indexingStore,
|
||||
) {
|
||||
const pathname = window.location.pathname.toLowerCase();
|
||||
this.isEditor = pathname.indexOf("doceditor") !== -1;
|
||||
@ -218,6 +220,7 @@ class FilesStore {
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
this.currentTariffStatusStore = currentTariffStatusStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.indexingStore = indexingStore;
|
||||
|
||||
this.roomsController = new AbortController();
|
||||
this.filesController = new AbortController();
|
||||
@ -1440,7 +1443,6 @@ class FilesStore {
|
||||
`${url}?${RoomsFilter.getDefault().toUrlParams()}`,
|
||||
);
|
||||
}
|
||||
|
||||
this.setIsErrorRoomNotAvailable(false);
|
||||
this.setIsLoadedFetchFiles(false);
|
||||
|
||||
@ -1450,7 +1452,6 @@ class FilesStore {
|
||||
|
||||
if (filterStorageItem && !filter) {
|
||||
const splitFilter = filterStorageItem.split(",");
|
||||
|
||||
filterData.sortBy = splitFilter[0];
|
||||
filterData.pageCount = +splitFilter[1];
|
||||
filterData.sortOrder = splitFilter[2];
|
||||
@ -1501,12 +1502,17 @@ class FilesStore {
|
||||
await this.publicRoomStore.getExternalLinks(data.current.id);
|
||||
}
|
||||
|
||||
if (data.current.indexing || data.current.order) {
|
||||
this.indexingStore.setIsIndexing(true);
|
||||
} else if (data.current.rootFolderId !== FolderType.COMMON) {
|
||||
this.indexingStore.setIsIndexing(false);
|
||||
}
|
||||
|
||||
if (newTotal > 0) {
|
||||
const lastPage = filterData.getLastPage();
|
||||
|
||||
if (filterData.page > lastPage) {
|
||||
filterData.page = lastPage;
|
||||
|
||||
return this.fetchFiles(
|
||||
folderId,
|
||||
filterData,
|
||||
@ -1748,6 +1754,9 @@ class FilesStore {
|
||||
withFilterLocalStorage = false,
|
||||
) => {
|
||||
const { setSelectedNode, roomsFolderId } = this.treeFoldersStore;
|
||||
const { setIsIndexing, isIndexing } = this.indexingStore;
|
||||
|
||||
if (isIndexing) setIsIndexing(false);
|
||||
|
||||
if (this.clientLoadingStore.isLoading) {
|
||||
this.abortAllFetch();
|
||||
@ -2093,6 +2102,7 @@ class FilesStore {
|
||||
"copy",
|
||||
"restore",
|
||||
"rename",
|
||||
"edit-index",
|
||||
"separator2",
|
||||
// "unsubscribe",
|
||||
"delete",
|
||||
@ -2501,6 +2511,7 @@ class FilesStore {
|
||||
"copy-to",
|
||||
"mark-read",
|
||||
"restore",
|
||||
"edit-index",
|
||||
"rename",
|
||||
// "change-thirdparty-info",
|
||||
"separator2",
|
||||
@ -3243,6 +3254,7 @@ class FilesStore {
|
||||
usedSpace,
|
||||
isCustomQuota,
|
||||
providerId,
|
||||
order,
|
||||
startFilling,
|
||||
draftLocation,
|
||||
expired,
|
||||
@ -3419,6 +3431,7 @@ class FilesStore {
|
||||
usedSpace,
|
||||
isCustomQuota,
|
||||
providerId,
|
||||
order,
|
||||
startFilling,
|
||||
draftLocation,
|
||||
expired,
|
||||
@ -3429,6 +3442,22 @@ class FilesStore {
|
||||
//return [...this.folders, ...this.files];
|
||||
|
||||
const newFolders = [...this.folders];
|
||||
const orderItems = [...this.folders, ...this.files].filter((x) => x.order);
|
||||
|
||||
if (orderItems.length > 0) {
|
||||
orderItems.sort((a, b) => {
|
||||
if (a.order.includes(".")) {
|
||||
return (
|
||||
Number(a.order.split(".").at(-1)) -
|
||||
Number(b.order.split(".").at(-1))
|
||||
);
|
||||
}
|
||||
|
||||
return Number(a.order) - Number(b.order);
|
||||
});
|
||||
|
||||
return this.getFilesListItems(orderItems);
|
||||
}
|
||||
|
||||
newFolders.sort((a, b) => {
|
||||
const firstValue = a.roomType ? 1 : 0;
|
||||
@ -4050,6 +4079,15 @@ class FilesStore {
|
||||
return this.filter.total;
|
||||
}
|
||||
|
||||
get indexColumnSize() {
|
||||
if (!this.indexingStore.isIndexing) return;
|
||||
|
||||
let minWidth = 36;
|
||||
const lastFile = this.filesList[this.filesList.length - 1];
|
||||
|
||||
return minWidth + lastFile?.order?.length * 3;
|
||||
}
|
||||
|
||||
get hasMoreFiles() {
|
||||
const { isRoomsFolder, isArchiveFolder } = this.treeFoldersStore;
|
||||
|
||||
|
85
packages/client/src/store/IndexingStore.ts
Normal file
85
packages/client/src/store/IndexingStore.ts
Normal file
@ -0,0 +1,85 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import InfoPanelStore from "SRC_DIR/store/InfoPanelStore";
|
||||
|
||||
class IndexingStore {
|
||||
infoPanelStore;
|
||||
|
||||
isIndexEditingMode: boolean = false;
|
||||
|
||||
isIndexing: boolean = false;
|
||||
|
||||
updateSelection: any[] = [];
|
||||
|
||||
constructor(infoPanelStore: InfoPanelStore) {
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
setIsIndexing = (indexing: boolean) => {
|
||||
// turn off the mode if we are no longer in indexed folders
|
||||
const { setIsVisible } = this.infoPanelStore;
|
||||
if (!indexing && this.isIndexEditingMode) this.setIsIndexEditingMode(false);
|
||||
if (!indexing) setIsVisible(false);
|
||||
|
||||
this.isIndexing = indexing;
|
||||
};
|
||||
|
||||
setUpdateSelection = (selection: any[]) => {
|
||||
this.updateSelection = selection;
|
||||
};
|
||||
|
||||
setUpdateItems = (items: any) => {
|
||||
const newSelection = [...this.updateSelection];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const item of items) {
|
||||
const exist = this.updateSelection.find(
|
||||
(selectionItem) =>
|
||||
selectionItem.id === item.id &&
|
||||
selectionItem.fileExst === item.fileExst,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-continue
|
||||
if (exist) continue;
|
||||
newSelection.push(item);
|
||||
}
|
||||
this.setUpdateSelection(newSelection);
|
||||
};
|
||||
|
||||
setIsIndexEditingMode = (mode: boolean) => {
|
||||
if (!mode) {
|
||||
this.setUpdateSelection([]);
|
||||
}
|
||||
const { setIsVisible } = this.infoPanelStore;
|
||||
setIsVisible(false);
|
||||
this.isIndexEditingMode = mode;
|
||||
};
|
||||
}
|
||||
|
||||
export default IndexingStore;
|
@ -149,6 +149,8 @@ class SelectedFolderStore {
|
||||
|
||||
lifetime: TRoomLifetime | null = null;
|
||||
|
||||
indexing = false;
|
||||
|
||||
constructor(settingsStore: SettingsStore) {
|
||||
makeAutoObservable(this);
|
||||
this.settingsStore = settingsStore;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { TableVersions } from "SRC_DIR/helpers/constants";
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
|
||||
const TABLE_COLUMNS = `filesTableColumns_ver-${TableVersions.Files}`;
|
||||
const TABLE_ACCOUNTS_PEOPLE_COLUMNS = `peopleTableColumns_ver-${TableVersions.People}`;
|
||||
@ -34,11 +35,13 @@ const TABLE_ACCOUNTS_INSIDE_GROUP_COLUMNS = `insideGroupTableColumns_ver-${Table
|
||||
const TABLE_ROOMS_COLUMNS = `roomsTableColumns_ver-${TableVersions.Rooms}`;
|
||||
const TABLE_TRASH_COLUMNS = `trashTableColumns_ver-${TableVersions.Trash}`;
|
||||
const TABLE_RECENT_COLUMNS = `recentTableColumns_ver-${TableVersions.Recent}`;
|
||||
const TABLE_VDR_INDEXING_COLUMNS = `vdrIndexingColumns_ver-${TableVersions.Rooms}`;
|
||||
|
||||
const COLUMNS_SIZE = `filesColumnsSize_ver-${TableVersions.Files}`;
|
||||
const COLUMNS_ROOMS_SIZE = `roomsColumnsSize_ver-${TableVersions.Rooms}`;
|
||||
const COLUMNS_TRASH_SIZE = `trashColumnsSize_ver-${TableVersions.Trash}`;
|
||||
const COLUMNS_RECENT_SIZE = `recentColumnsSize_ver-${TableVersions.Recent}`;
|
||||
const COLUMNS_VDR_INDEXING_SIZE = `vdrIndexingColumnsSize_ver-${TableVersions.Rooms}`;
|
||||
|
||||
const COLUMNS_SIZE_INFO_PANEL = `filesColumnsSizeInfoPanel_ver-${TableVersions.Files}`;
|
||||
const COLUMNS_ROOMS_SIZE_INFO_PANEL = `roomsColumnsSizeInfoPanel_ver-${TableVersions.Rooms}`;
|
||||
@ -50,6 +53,7 @@ class TableStore {
|
||||
treeFoldersStore;
|
||||
userStore;
|
||||
settingsStore;
|
||||
selectedFolderStore;
|
||||
|
||||
roomColumnNameIsEnabled = true; // always true
|
||||
roomColumnTypeIsEnabled = false;
|
||||
@ -66,6 +70,7 @@ class TableStore {
|
||||
createdColumnIsEnabled = true;
|
||||
modifiedColumnIsEnabled = true;
|
||||
sizeColumnIsEnabled = true;
|
||||
indexColumnIsEnabled = true;
|
||||
typeColumnIsEnabled = true;
|
||||
quickButtonsColumnIsEnabled = true;
|
||||
lastOpenedColumnIsEnabled = true;
|
||||
@ -86,13 +91,20 @@ class TableStore {
|
||||
groupAccountsInsideGroupColumnIsEnabled = true;
|
||||
emailAccountsInsideGroupColumnIsEnabled = true;
|
||||
|
||||
constructor(authStore, treeFoldersStore, userStore, settingsStore) {
|
||||
constructor(
|
||||
authStore,
|
||||
treeFoldersStore,
|
||||
userStore,
|
||||
settingsStore,
|
||||
indexingStore,
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
|
||||
this.authStore = authStore;
|
||||
this.treeFoldersStore = treeFoldersStore;
|
||||
this.userStore = userStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.indexingStore = indexingStore;
|
||||
}
|
||||
|
||||
setRoomColumnType = (enable) => {
|
||||
@ -139,6 +151,10 @@ class TableStore {
|
||||
this.sizeColumnIsEnabled = enable;
|
||||
};
|
||||
|
||||
setIndexColumn = (enable) => {
|
||||
this.indexColumnIsEnabled = enable;
|
||||
};
|
||||
|
||||
setTypeColumn = (enable) => {
|
||||
this.typeColumnIsEnabled = enable;
|
||||
};
|
||||
@ -240,6 +256,7 @@ class TableStore {
|
||||
this.setAuthorColumn(splitColumns.includes("Author"));
|
||||
this.setCreatedColumn(splitColumns.includes("Created"));
|
||||
this.setSizeColumn(splitColumns.includes("Size"));
|
||||
this.setIndexColumn(splitColumns.includes("Index"));
|
||||
this.setTypeColumn(splitColumns.includes("Type"));
|
||||
this.setQuickButtonsColumn(splitColumns.includes("QuickButtons"));
|
||||
this.setLastOpenedColumn(splitColumns.includes("LastOpened"));
|
||||
@ -292,6 +309,10 @@ class TableStore {
|
||||
this.setErasureColumn(!this.erasureColumnIsEnabled);
|
||||
return;
|
||||
|
||||
case "Index":
|
||||
this.setIndexColumn(!this.indexColumnIsEnabled);
|
||||
return;
|
||||
|
||||
case "Size":
|
||||
this.setSizeColumn(!this.sizeColumnIsEnabled);
|
||||
return;
|
||||
@ -403,6 +424,7 @@ class TableStore {
|
||||
getIsAccountsInsideGroup,
|
||||
} = this.treeFoldersStore;
|
||||
|
||||
const { isIndexing } = this.indexingStore;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const userId = this.userStore.user?.id;
|
||||
const isFrame = this.settingsStore.isFrame;
|
||||
@ -419,7 +441,9 @@ class TableStore {
|
||||
? `${TABLE_TRASH_COLUMNS}=${userId}`
|
||||
: isRecentTab
|
||||
? `${TABLE_RECENT_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`;
|
||||
: isIndexing
|
||||
? `${TABLE_VDR_INDEXING_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`;
|
||||
|
||||
return isFrame ? `SDK_${tableStorageName}` : tableStorageName;
|
||||
}
|
||||
@ -428,6 +452,7 @@ class TableStore {
|
||||
get columnStorageName() {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isRecentTab } =
|
||||
this.treeFoldersStore;
|
||||
const { isIndexing } = this.indexingStore;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const userId = this.userStore.user?.id;
|
||||
const isFrame = this.settingsStore.isFrame;
|
||||
@ -438,7 +463,9 @@ class TableStore {
|
||||
? `${COLUMNS_TRASH_SIZE}=${userId}`
|
||||
: isRecentTab
|
||||
? `${COLUMNS_RECENT_SIZE}=${userId}`
|
||||
: `${COLUMNS_SIZE}=${userId}`;
|
||||
: isIndexing
|
||||
? `${COLUMNS_VDR_INDEXING_SIZE}=${userId}`
|
||||
: `${COLUMNS_SIZE}=${userId}`;
|
||||
|
||||
return isFrame ? `SDK_${columnStorageName}` : columnStorageName;
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ import ImportAccountsStore from "./ImportAccountsStore";
|
||||
import PluginStore from "./PluginStore";
|
||||
import InfoPanelStore from "./InfoPanelStore";
|
||||
import CampaignsStore from "./CampaignsStore";
|
||||
import IndexingStore from "./IndexingStore";
|
||||
|
||||
const selectedFolderStore = new SelectedFolderStore(settingsStore);
|
||||
|
||||
@ -115,6 +116,7 @@ const clientLoadingStore = new ClientLoadingStore();
|
||||
const publicRoomStore = new PublicRoomStore(clientLoadingStore);
|
||||
|
||||
const infoPanelStore = new InfoPanelStore(userStore);
|
||||
const indexingStore = new IndexingStore(infoPanelStore);
|
||||
|
||||
const treeFoldersStore = new TreeFoldersStore(
|
||||
selectedFolderStore,
|
||||
@ -151,6 +153,7 @@ const filesStore = new FilesStore(
|
||||
userStore,
|
||||
currentTariffStatusStore,
|
||||
settingsStore,
|
||||
indexingStore,
|
||||
);
|
||||
|
||||
const mediaViewerDataStore = new MediaViewerDataStore(
|
||||
@ -214,6 +217,7 @@ const filesActionsStore = new FilesActionsStore(
|
||||
currentTariffStatusStore,
|
||||
peopleStore,
|
||||
currentQuotaStore,
|
||||
indexingStore,
|
||||
);
|
||||
|
||||
const contextOptionsStore = new ContextOptionsStore(
|
||||
@ -233,6 +237,7 @@ const contextOptionsStore = new ContextOptionsStore(
|
||||
infoPanelStore,
|
||||
currentTariffStatusStore,
|
||||
userStore,
|
||||
indexingStore,
|
||||
clientLoadingStore,
|
||||
);
|
||||
|
||||
@ -264,6 +269,7 @@ const tableStore = new TableStore(
|
||||
treeFoldersStore,
|
||||
userStore,
|
||||
settingsStore,
|
||||
indexingStore,
|
||||
);
|
||||
|
||||
infoPanelStore.filesSettingsStore = filesSettingsStore;
|
||||
@ -351,6 +357,7 @@ const store = {
|
||||
pluginStore,
|
||||
storageManagement,
|
||||
campaignsStore,
|
||||
indexingStore,
|
||||
};
|
||||
|
||||
export default store;
|
||||
|
@ -1435,6 +1435,26 @@ export async function startFilling(fileId: string | number): Promise<void> {
|
||||
await request(options);
|
||||
}
|
||||
|
||||
export async function changeIndex(
|
||||
id: number,
|
||||
order: number,
|
||||
isFolder: boolean,
|
||||
) {
|
||||
const url = isFolder ? `/files/folder/${id}/order` : `/files/${id}/order`;
|
||||
return request({
|
||||
method: "put",
|
||||
url,
|
||||
data: { order },
|
||||
});
|
||||
}
|
||||
|
||||
export async function reorder(id: number) {
|
||||
return request({
|
||||
method: "put",
|
||||
url: `/files/rooms/${id}/reorder`,
|
||||
});
|
||||
}
|
||||
|
||||
export async function checkIsPDFForm(fileId: string | number) {
|
||||
return request({
|
||||
method: "get",
|
||||
|
@ -39,4 +39,5 @@ export const enum ThemeId {
|
||||
IndicatorLoader = "indicatorLoader",
|
||||
Progress = "progress",
|
||||
SubmenuText = "submenuText",
|
||||
IndexIconButton = "indexIconButton",
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import LoadingButton from "./styled-components/loadingButton";
|
||||
import ProgressColorTheme from "./styled-components/progress";
|
||||
import VersionBadgeTheme from "./styled-components/versionBadge";
|
||||
import SubmenuTextTheme from "./styled-components/submenuText";
|
||||
import StyledIndexWrapper from "./sub-components/StyledIndexWrapper";
|
||||
|
||||
const ColorTheme = forwardRef<
|
||||
HTMLDivElement,
|
||||
@ -76,6 +77,20 @@ const ColorTheme = forwardRef<
|
||||
/>
|
||||
);
|
||||
}
|
||||
case ThemeId.IndexIconButton: {
|
||||
return (
|
||||
<StyledIndexWrapper
|
||||
$currentColorScheme={currentColorScheme}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<IconButtonTheme
|
||||
{...props}
|
||||
themeId={themeId}
|
||||
$currentColorScheme={currentColorScheme}
|
||||
/>
|
||||
</StyledIndexWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
case ThemeId.IconButtonMute: {
|
||||
return (
|
||||
|
@ -77,6 +77,10 @@ export interface IndicatorFilterButtonColorTheme
|
||||
themeId: ThemeId.IndicatorFilterButton;
|
||||
}
|
||||
|
||||
export interface IndexIconButton extends DefaultColorThemeProps {
|
||||
themeId: ThemeId.IndexIconButton;
|
||||
}
|
||||
|
||||
export interface IndicatorLoaderColorTheme extends DefaultColorThemeProps {
|
||||
themeId: ThemeId.IndicatorLoader;
|
||||
}
|
||||
@ -132,4 +136,5 @@ export type ColorThemeProps =
|
||||
| ProgressColorTheme
|
||||
| VersionBadgeTheme
|
||||
| LinkColorTheme
|
||||
| IndexIconButton
|
||||
| SubmenuTextTheme;
|
||||
|
@ -0,0 +1,73 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Base, TColorScheme } from "../../../themes";
|
||||
|
||||
const StyledIndexWrapper = styled.div<{
|
||||
$currentColorScheme: TColorScheme | undefined;
|
||||
}>`
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
|
||||
.index-up-icon {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.index-down-icon {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
props.theme.filesSection.tableView.row.indexBackgroundButtonHover};
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.theme.filesSection.tableView.row
|
||||
.indexArrowButtonHover} !important;
|
||||
}
|
||||
|
||||
circle {
|
||||
stroke: ${(props) =>
|
||||
props.theme.filesSection.tableView.row
|
||||
.indexArrowButtonHover} !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledIndexWrapper.defaultProps = { theme: Base };
|
||||
|
||||
export default StyledIndexWrapper;
|
@ -233,6 +233,9 @@ export interface FilterProps {
|
||||
isPeopleAccounts: boolean;
|
||||
isGroupsAccounts: boolean;
|
||||
isInsideGroup: boolean;
|
||||
isIndexing: boolean;
|
||||
isIndexEditingMode: boolean;
|
||||
|
||||
filterTitle: string;
|
||||
sortByTitle: string;
|
||||
|
||||
|
@ -71,6 +71,9 @@ const FilterInput = React.memo(
|
||||
isPeopleAccounts,
|
||||
isGroupsAccounts,
|
||||
isInsideGroup,
|
||||
isIndexing,
|
||||
isIndexEditingMode,
|
||||
|
||||
filterTitle,
|
||||
sortByTitle,
|
||||
|
||||
@ -208,43 +211,49 @@ const FilterInput = React.memo(
|
||||
onClearSearch={onClearSearch}
|
||||
id="filter_search-input"
|
||||
size={InputSize.base}
|
||||
isDisabled={isIndexEditingMode}
|
||||
onFocus={onInputFocus}
|
||||
/>
|
||||
<FilterButton
|
||||
id="filter-button"
|
||||
onFilter={onFilter}
|
||||
getFilterData={getFilterData}
|
||||
selectedFilterValue={selectedFilterValue}
|
||||
filterHeader={filterHeader}
|
||||
selectorLabel={selectorLabel}
|
||||
isRooms={isRooms}
|
||||
isAccounts={isAccounts}
|
||||
isPeopleAccounts={isPeopleAccounts}
|
||||
isGroupsAccounts={isGroupsAccounts}
|
||||
isInsideGroup={isInsideGroup}
|
||||
title={filterTitle}
|
||||
userId={userId}
|
||||
disableThirdParty={disableThirdParty}
|
||||
/>
|
||||
<SortButton
|
||||
id="sort-by-button"
|
||||
onSort={onSort}
|
||||
getSortData={getSortData}
|
||||
getSelectedSortData={getSelectedSortData}
|
||||
view={view}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
onChangeViewAs={onChangeViewAs}
|
||||
onSortButtonClick={onSortButtonClick}
|
||||
viewSelectorVisible={
|
||||
viewSettings &&
|
||||
viewSelectorVisible &&
|
||||
currentDeviceType !== DeviceType.desktop
|
||||
}
|
||||
title={sortByTitle}
|
||||
/>
|
||||
{!isIndexEditingMode && (
|
||||
<FilterButton
|
||||
id="filter-button"
|
||||
onFilter={onFilter}
|
||||
getFilterData={getFilterData}
|
||||
selectedFilterValue={selectedFilterValue}
|
||||
filterHeader={filterHeader}
|
||||
selectorLabel={selectorLabel}
|
||||
isRooms={isRooms}
|
||||
isAccounts={isAccounts}
|
||||
isPeopleAccounts={isPeopleAccounts}
|
||||
isGroupsAccounts={isGroupsAccounts}
|
||||
isInsideGroup={isInsideGroup}
|
||||
title={filterTitle}
|
||||
userId={userId}
|
||||
disableThirdParty={disableThirdParty}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isIndexing && (
|
||||
<SortButton
|
||||
id="sort-by-button"
|
||||
onSort={onSort}
|
||||
getSortData={getSortData}
|
||||
getSelectedSortData={getSelectedSortData}
|
||||
view={view}
|
||||
viewAs={viewAs === "table" ? "row" : viewAs}
|
||||
viewSettings={viewSettings}
|
||||
onChangeViewAs={onChangeViewAs}
|
||||
onSortButtonClick={onSortButtonClick}
|
||||
viewSelectorVisible={
|
||||
viewSettings &&
|
||||
viewSelectorVisible &&
|
||||
currentDeviceType !== DeviceType.desktop
|
||||
}
|
||||
title={sortByTitle}
|
||||
/>
|
||||
)}
|
||||
{viewSettings &&
|
||||
!isIndexing &&
|
||||
currentDeviceType === DeviceType.desktop &&
|
||||
viewSelectorVisible && (
|
||||
<ViewSelector
|
||||
|
@ -14,6 +14,8 @@ export const getRoomTypeTitleTranslation = (
|
||||
// return t("Common:ReviewRoomTitle");
|
||||
// case RoomsType.ReadOnlyRoom:
|
||||
// return t("Common:ViewOnlyRoomTitle");
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("Common:VirtualDataRoom");
|
||||
case RoomsType.CustomRoom:
|
||||
return t("Common:CustomRoomTitle");
|
||||
case RoomsType.PublicRoom:
|
||||
@ -40,6 +42,8 @@ export const getRoomTypeDescriptionTranslation = (
|
||||
// return t("Common:ReviewRoomDescription");
|
||||
// case RoomsType.ReadOnlyRoom:
|
||||
// return t("Common:ViewOnlyRoomDescription");
|
||||
case RoomsType.VirtualDataRoom:
|
||||
return t("Common:VirtualDataRoomDescription");
|
||||
case RoomsType.CustomRoom:
|
||||
return t("Common:CustomRoomDescription");
|
||||
case RoomsType.PublicRoom:
|
||||
|
@ -25,11 +25,13 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useRef } from "react";
|
||||
|
||||
import ArrowReactSvgUrl from "PUBLIC_DIR/images/arrow2.react.svg?url";
|
||||
import { isMobile } from "react-device-detect"; // TODO: isDesktop=true for IOS(Firefox & Safari)
|
||||
import { VDRIndexingAction } from "../../enums";
|
||||
import { isMobile as isMobileUtils } from "../../utils/device";
|
||||
|
||||
import { Checkbox } from "../checkbox";
|
||||
import { ColorTheme, ThemeId } from "../color-theme";
|
||||
import {
|
||||
ContextMenuButton,
|
||||
ContextMenuButtonDisplayType,
|
||||
@ -58,6 +60,7 @@ const Row = (props: RowProps) => {
|
||||
onSelect,
|
||||
onRowClick,
|
||||
onContextClick,
|
||||
onChangeIndex,
|
||||
|
||||
getContextModel,
|
||||
isRoom,
|
||||
@ -71,6 +74,7 @@ const Row = (props: RowProps) => {
|
||||
className,
|
||||
badgeUrl,
|
||||
isDisabled,
|
||||
isIndexEditingMode,
|
||||
} = props;
|
||||
|
||||
const cm = useRef<null | {
|
||||
@ -143,6 +147,11 @@ const Row = (props: RowProps) => {
|
||||
onSelect?.(true, data);
|
||||
};
|
||||
|
||||
const changeIndex = (e, action) => {
|
||||
e.stopPropagation();
|
||||
onChangeIndex(action);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledRow
|
||||
ref={row}
|
||||
@ -213,30 +222,51 @@ const Row = (props: RowProps) => {
|
||||
{renderContentElement && (
|
||||
<StyledContentElement>{contentElement}</StyledContentElement>
|
||||
)}
|
||||
{renderContext ? (
|
||||
<ContextMenuButton
|
||||
isFill
|
||||
className="expandButton"
|
||||
getData={getOptions}
|
||||
directionX="right"
|
||||
displayType={ContextMenuButtonDisplayType.toggle}
|
||||
onClick={onContextMenu}
|
||||
title={contextTitle}
|
||||
/>
|
||||
{isIndexEditingMode ? (
|
||||
<>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IndexIconButton}
|
||||
iconName={ArrowReactSvgUrl}
|
||||
className="index-up-icon"
|
||||
size="small"
|
||||
onClick={(e) => changeIndex(e, VDRIndexingAction.HigherIndex)}
|
||||
/>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IndexIconButton}
|
||||
iconName={ArrowReactSvgUrl}
|
||||
className="index-down-icon"
|
||||
size="small"
|
||||
onClick={(e) => changeIndex(e, VDRIndexingAction.LowerIndex)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div className="expandButton"> </div>
|
||||
<>
|
||||
{renderContext ? (
|
||||
<ContextMenuButton
|
||||
isFill
|
||||
className="expandButton"
|
||||
getData={getOptions}
|
||||
directionX="right"
|
||||
displayType={ContextMenuButtonDisplayType.toggle}
|
||||
onClick={onContextMenu}
|
||||
title={contextTitle}
|
||||
/>
|
||||
) : (
|
||||
<div className="expandButton"> </div>
|
||||
)}
|
||||
<ContextMenu
|
||||
getContextModel={getContextModel}
|
||||
model={contextData.contextOptions || []}
|
||||
ref={cm}
|
||||
header={contextMenuHeader}
|
||||
withBackdrop={isMobileUtils()}
|
||||
onHide={rowContextClose}
|
||||
isRoom={isRoom}
|
||||
isArchive={isArchive}
|
||||
badgeUrl={badgeUrl}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<ContextMenu
|
||||
getContextModel={getContextModel}
|
||||
model={contextData.contextOptions || []}
|
||||
ref={cm}
|
||||
header={contextMenuHeader}
|
||||
withBackdrop={isMobileUtils()}
|
||||
onHide={rowContextClose}
|
||||
isRoom={isRoom}
|
||||
isArchive={isArchive}
|
||||
badgeUrl={badgeUrl}
|
||||
/>
|
||||
</StyledOptionButton>
|
||||
</StyledRow>
|
||||
);
|
||||
|
@ -69,6 +69,7 @@ export interface RowProps {
|
||||
mode?: TMode;
|
||||
/** Removes the borders */
|
||||
withoutBorder?: boolean;
|
||||
isIndexEditingMode: boolean;
|
||||
isRoom?: boolean;
|
||||
contextTitle?: string;
|
||||
badgesComponent?: React.ReactNode;
|
||||
|
@ -66,6 +66,7 @@ export interface SectionBodyProps {
|
||||
settingsStudio: boolean;
|
||||
isFormGallery?: boolean;
|
||||
isDesktop?: boolean;
|
||||
isIndexEditingMode?: boolean;
|
||||
currentDeviceType?: DeviceType;
|
||||
getContextModel?: () => ContextMenuModel[];
|
||||
}
|
||||
@ -144,4 +145,5 @@ export interface SectionProps {
|
||||
anotherDialogOpen?: boolean;
|
||||
isDesktop?: boolean;
|
||||
getContextModel?: () => ContextMenuModel[];
|
||||
isIndexEditingMode?: boolean;
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ const Section = (props: SectionProps) => {
|
||||
canDisplay,
|
||||
anotherDialogOpen,
|
||||
getContextModel,
|
||||
isIndexEditingMode,
|
||||
} = props;
|
||||
|
||||
const [sectionSize, setSectionSize] = React.useState<{
|
||||
@ -243,6 +244,7 @@ const Section = (props: SectionProps) => {
|
||||
isFormGallery={isFormGallery}
|
||||
currentDeviceType={currentDeviceType}
|
||||
getContextModel={getContextModel}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
>
|
||||
{isSectionHeaderAvailable &&
|
||||
currentDeviceType === DeviceType.mobile && (
|
||||
|
@ -51,6 +51,7 @@ const SectionBody = React.memo(
|
||||
isDesktop,
|
||||
settingsStudio = false,
|
||||
getContextModel,
|
||||
isIndexEditingMode,
|
||||
}: SectionBodyProps) => {
|
||||
const focusRef = React.useRef<HTMLDivElement | null>(null);
|
||||
const cmRef = React.useRef<null | {
|
||||
@ -65,6 +66,7 @@ const SectionBody = React.memo(
|
||||
|
||||
const onContextMenu = React.useCallback(
|
||||
(e: MouseEvent | React.MouseEvent<Element, MouseEvent>) => {
|
||||
if (isIndexEditingMode) return;
|
||||
const bodyElem = document.getElementsByClassName(
|
||||
"section-body",
|
||||
)[0] as HTMLDivElement;
|
||||
@ -89,7 +91,7 @@ const SectionBody = React.memo(
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
},
|
||||
[getContextModel, isOpen],
|
||||
[getContextModel, isOpen, isIndexEditingMode],
|
||||
);
|
||||
|
||||
const onHide = () => {
|
||||
|
@ -59,6 +59,11 @@ const StyledTableContainer = styled.div<{ useReactWindow?: boolean }>`
|
||||
min-width: 10%;
|
||||
}
|
||||
|
||||
.indexing-separator {
|
||||
background-color: ${(props) =>
|
||||
props.theme.tableContainer.indexingSeparator};
|
||||
}
|
||||
|
||||
.resize-handle {
|
||||
display: block;
|
||||
cursor: ew-resize;
|
||||
@ -443,7 +448,10 @@ const StyledTableBody = styled.div<{
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTableRow = styled.div<{ dragging?: boolean }>`
|
||||
const StyledTableRow = styled.div<{
|
||||
dragging?: boolean;
|
||||
isIndexEditingMode?: boolean;
|
||||
}>`
|
||||
display: contents;
|
||||
|
||||
.table-container_header-checkbox {
|
||||
@ -458,7 +466,7 @@ const StyledTableRow = styled.div<{ dragging?: boolean }>`
|
||||
|
||||
.droppable-hover {
|
||||
background: ${(props) =>
|
||||
props.dragging
|
||||
props.dragging && !props.isIndexEditingMode
|
||||
? `${props.theme.dragAndDrop.acceptBackground} !important`
|
||||
: "none"};
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ export type TTableColumn = {
|
||||
defaultSize?: number;
|
||||
default?: boolean;
|
||||
resizable?: boolean;
|
||||
isShort?: boolean;
|
||||
checkbox?: {
|
||||
value: boolean;
|
||||
isIndeterminate: boolean;
|
||||
@ -108,6 +109,7 @@ export interface TableBodyProps {
|
||||
useReactWindow: boolean;
|
||||
onScroll: () => void;
|
||||
infoPanelVisible: boolean;
|
||||
isIndexEditingMode: boolean;
|
||||
}
|
||||
|
||||
export interface TableRowProps {
|
||||
@ -121,6 +123,7 @@ export interface TableRowProps {
|
||||
title: string;
|
||||
getContextModel: () => ContextMenuModel[];
|
||||
badgeUrl: string;
|
||||
isIndexEditingMode: boolean;
|
||||
}
|
||||
|
||||
export interface TableCellProps {
|
||||
|
@ -44,6 +44,7 @@ const TableBodyPure = (props: TableBodyProps) => {
|
||||
useReactWindow = true,
|
||||
onScroll,
|
||||
infoPanelVisible = false,
|
||||
isIndexEditingMode = false,
|
||||
} = props;
|
||||
|
||||
return useReactWindow ? (
|
||||
@ -64,6 +65,7 @@ const TableBodyPure = (props: TableBodyProps) => {
|
||||
itemSize={itemHeight}
|
||||
onScroll={onScroll}
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
>
|
||||
{children}
|
||||
</InfiniteLoaderComponent>
|
||||
|
@ -43,7 +43,7 @@ import { checkingForUnfixedSize, getSubstring } from "./Table.utils";
|
||||
const defaultMinColumnSize = 110;
|
||||
const settingsSize = 24;
|
||||
|
||||
const minSizeFirstColumn = 210;
|
||||
const minSizeFirstColumn = 75;
|
||||
const handleOffset = 8;
|
||||
|
||||
class TableHeader extends React.Component<
|
||||
@ -322,6 +322,7 @@ class TableHeader extends React.Component<
|
||||
columns,
|
||||
setHideColumns,
|
||||
tableStorageName,
|
||||
isIndexEditingMode,
|
||||
} = this.props;
|
||||
|
||||
const enabledColumns = columns.filter((col) => col.enable);
|
||||
@ -354,6 +355,9 @@ class TableHeader extends React.Component<
|
||||
const defaultSize =
|
||||
columns.find((col) => col.defaultSize && col.enable)?.defaultSize || 0;
|
||||
|
||||
const shortSize =
|
||||
columns.find((col) => col.isShort && col.enable)?.minWidth || 0;
|
||||
|
||||
// TODO: Fixed columns size if something went wrong
|
||||
if (storageSize) {
|
||||
const splitStorage = storageSize.split(" ");
|
||||
@ -409,6 +413,9 @@ class TableHeader extends React.Component<
|
||||
|
||||
const containerWidth = +container.clientWidth;
|
||||
|
||||
const indexColumnDifference = shortSize
|
||||
? Number(tableContainer[0].split("px")[0]) - shortSize
|
||||
: 0;
|
||||
const defaultWidth = tableContainer
|
||||
.map((column) => getSubstring(column))
|
||||
.reduce((x, y) => x + y);
|
||||
@ -417,7 +424,8 @@ class TableHeader extends React.Component<
|
||||
.map((column) => getSubstring(column))
|
||||
.reduce((x, y) => x + y);
|
||||
|
||||
const oldWidth = defaultWidth - defaultSize - settingsSize;
|
||||
const oldWidth =
|
||||
defaultWidth - defaultSize - settingsSize - indexColumnDifference;
|
||||
|
||||
const isDifferentWindowSize = infoPanelVisible
|
||||
? Math.round(defaultInfoWidth) !== Math.round(containerWidth)
|
||||
@ -494,13 +502,24 @@ class TableHeader extends React.Component<
|
||||
}
|
||||
|
||||
if (hideColumnsConst) {
|
||||
const shortColumnSize =
|
||||
columns.find((col) => col.isShort && col.enable)?.minWidth || 0;
|
||||
|
||||
tableInfoPanelContainer.forEach((item, index) => {
|
||||
const column = document.getElementById(`column_${index}`);
|
||||
const isQuickButtonColumn =
|
||||
Number(index) === tableInfoPanelContainer.length - 2;
|
||||
|
||||
if (isIndexEditingMode && isQuickButtonColumn) {
|
||||
gridTemplateColumns.push("24px");
|
||||
}
|
||||
|
||||
if (column?.dataset?.minWidth && column?.dataset?.default) {
|
||||
gridTemplateColumns.push(
|
||||
`${containerWidth - defaultSize - settingsSize}px`,
|
||||
`${containerWidth - defaultSize - shortColumnSize - settingsSize}px`,
|
||||
);
|
||||
} else if (column?.dataset?.minWidth && column?.dataset?.shortColum) {
|
||||
gridTemplateColumns.push(`${column?.dataset?.minWidth}px`);
|
||||
} else if (
|
||||
item === `${defaultSize}px` ||
|
||||
item === `${settingsSize}px`
|
||||
@ -665,6 +684,12 @@ class TableHeader extends React.Component<
|
||||
+index === tableContainer.length - 1 ||
|
||||
(column ? column.dataset.enable === "true" : item !== "0px");
|
||||
const defaultColumnSize = column && column.dataset.defaultSize;
|
||||
const shortColumSize =
|
||||
column?.dataset?.shortColum && column.dataset.minWidth;
|
||||
|
||||
const isSettingColumn = Number(index) === tableContainer.length - 1;
|
||||
const isQuickButtonColumn =
|
||||
Number(index) === tableContainer.length - 2;
|
||||
|
||||
const isActiveNow = item === "0px" && enable;
|
||||
if (isActiveNow && column) activeColumnIndex = index;
|
||||
@ -684,6 +709,11 @@ class TableHeader extends React.Component<
|
||||
getSubstring(gridTemplateColumns[+index - colIndex]) +
|
||||
getSubstring(item)
|
||||
}px`;
|
||||
} else if (isSettingColumn) {
|
||||
let newSettingsSize = isIndexEditingMode ? 75 : settingsSize;
|
||||
gridTemplateColumns.push(`${newSettingsSize}px`);
|
||||
} else if (shortColumSize) {
|
||||
gridTemplateColumns.push(`${shortColumSize}px`);
|
||||
} else if (item !== `${settingsSize}px`) {
|
||||
const percent = (getSubstring(item) / oldWidth) * 100;
|
||||
|
||||
@ -898,6 +928,8 @@ class TableHeader extends React.Component<
|
||||
for (const col of columns) {
|
||||
if (col.default) {
|
||||
str += `${wideColumnSize} `;
|
||||
} else if (col.isShort) {
|
||||
str += `${col.minWidth}px `;
|
||||
} else
|
||||
str += col.enable
|
||||
? col.defaultSize
|
||||
|
@ -25,6 +25,8 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useRef } from "react";
|
||||
import ArrowReactSvgUrl from "PUBLIC_DIR/images/arrow2.react.svg?url";
|
||||
import { VDRIndexingAction } from "../../enums";
|
||||
|
||||
import { ContextMenu } from "../context-menu";
|
||||
import {
|
||||
@ -36,6 +38,7 @@ import { StyledTableRow } from "./Table.styled";
|
||||
import { TableRowProps } from "./Table.types";
|
||||
|
||||
import { TableCell } from "./sub-components/TableCell";
|
||||
import { ColorTheme, ThemeId } from "../color-theme";
|
||||
|
||||
const TableRow = (props: TableRowProps) => {
|
||||
const {
|
||||
@ -49,6 +52,8 @@ const TableRow = (props: TableRowProps) => {
|
||||
title,
|
||||
getContextModel,
|
||||
badgeUrl,
|
||||
isIndexEditingMode,
|
||||
onChangeIndex,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@ -82,9 +87,15 @@ const TableRow = (props: TableRowProps) => {
|
||||
return contextOptions;
|
||||
};
|
||||
|
||||
const changeIndex = (e, action) => {
|
||||
e.stopPropagation();
|
||||
onChangeIndex(action);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledTableRow
|
||||
onContextMenu={onContextMenu}
|
||||
isIndexEditingMode={isIndexEditingMode}
|
||||
className={`${className} table-container_row`}
|
||||
{...rest}
|
||||
>
|
||||
@ -96,27 +107,48 @@ const TableRow = (props: TableRowProps) => {
|
||||
forwardedRef={row}
|
||||
className={`${selectionProp?.className} table-container_row-context-menu-wrapper`}
|
||||
>
|
||||
<ContextMenu
|
||||
onHide={onHideContextMenu}
|
||||
ref={cm}
|
||||
model={contextOptions}
|
||||
getContextModel={getContextModel}
|
||||
withBackdrop
|
||||
badgeUrl={badgeUrl}
|
||||
/>
|
||||
{renderContext ? (
|
||||
<ContextMenuButton
|
||||
isFill
|
||||
className="expandButton"
|
||||
getData={getOptions}
|
||||
directionX="right"
|
||||
displayType={ContextMenuButtonDisplayType.toggle}
|
||||
onClick={onContextMenu}
|
||||
onClose={onHideContextMenu}
|
||||
title={title}
|
||||
/>
|
||||
{isIndexEditingMode ? (
|
||||
<>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IndexIconButton}
|
||||
iconName={ArrowReactSvgUrl}
|
||||
className="index-up-icon"
|
||||
size="small"
|
||||
onClick={(e) => changeIndex(e, VDRIndexingAction.HigherIndex)}
|
||||
/>
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IndexIconButton}
|
||||
iconName={ArrowReactSvgUrl}
|
||||
className="index-down-icon"
|
||||
size="small"
|
||||
onClick={(e) => changeIndex(e, VDRIndexingAction.LowerIndex)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div className="expandButton"> </div>
|
||||
<>
|
||||
<ContextMenu
|
||||
onHide={onHideContextMenu}
|
||||
ref={cm}
|
||||
model={contextOptions}
|
||||
getContextModel={getContextModel}
|
||||
withBackdrop
|
||||
badgeUrl={badgeUrl}
|
||||
/>
|
||||
{renderContext ? (
|
||||
<ContextMenuButton
|
||||
isFill
|
||||
className="expandButton"
|
||||
getData={getOptions}
|
||||
directionX="right"
|
||||
displayType={ContextMenuButtonDisplayType.toggle}
|
||||
onClick={onContextMenu}
|
||||
onClose={onHideContextMenu}
|
||||
title={title}
|
||||
/>
|
||||
) : (
|
||||
<div className="expandButton"> </div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</TableCell>
|
||||
</div>
|
||||
|
@ -55,6 +55,7 @@ const TableHeaderCell = ({
|
||||
withTagRef,
|
||||
default: isDefault,
|
||||
checkbox,
|
||||
isShort,
|
||||
} = column;
|
||||
|
||||
const isActive = (sortBy && column.sortBy === sortBy) || active;
|
||||
@ -82,6 +83,7 @@ const TableHeaderCell = ({
|
||||
data-default={isDefault}
|
||||
data-enable={enable}
|
||||
data-min-width={minWidth}
|
||||
data-short-colum={isShort}
|
||||
data-default-size={defaultSize}
|
||||
sortingVisible={sortingVisible}
|
||||
ref={tagRef}
|
||||
@ -120,6 +122,7 @@ const TableHeaderCell = ({
|
||||
id={`column_${index}`}
|
||||
data-enable={enable}
|
||||
data-default={isDefault}
|
||||
data-short-colum={isShort}
|
||||
data-min-width={minWidth}
|
||||
data-default-size={defaultSize}
|
||||
sortingVisible={sortingVisible}
|
||||
|
@ -76,7 +76,7 @@ export const ROOMS_TYPE_TRANSLATIONS = Object.freeze({
|
||||
5: "Files:CustomRooms",
|
||||
6: "Files:PublicRoom",
|
||||
|
||||
8: "Files:VirtualDataRoom",
|
||||
8: "Common:VirtualDataRoom",
|
||||
});
|
||||
|
||||
export const ROOMS_PROVIDER_TYPE_NAME = Object.freeze({
|
||||
|
@ -567,6 +567,12 @@ export const enum RoomsStorageFilter {
|
||||
thirdparty = 2,
|
||||
}
|
||||
|
||||
export const enum VDRIndexingAction {
|
||||
HigherIndex = "HigherIndex",
|
||||
LowerIndex = "LowerIndex",
|
||||
MoveIndex = "MoveIndex",
|
||||
}
|
||||
|
||||
export const enum LDAPOperation {
|
||||
SaveAndSync = "Save",
|
||||
Sync = "Sync",
|
||||
|
@ -2229,6 +2229,8 @@ export const getBaseTheme = () => {
|
||||
hoverBorderColor: grayMain,
|
||||
tableCellBorder: `1px solid ${grayLightMid}`,
|
||||
|
||||
indexingSeparator: "#4781D1",
|
||||
|
||||
groupMenu: {
|
||||
background: white,
|
||||
borderBottom: "1px solid transparent",
|
||||
@ -2298,6 +2300,11 @@ export const getBaseTheme = () => {
|
||||
contextMenuWrapperDraggingHover: `linear-gradient(to left,rgb(239, 239, 178) 24px,${grayLightMid} 24px)`,
|
||||
|
||||
backgroundActive: `#F3F4F4`,
|
||||
indexUpdate: `#F2F6FC`,
|
||||
indexActive: `#E4ECF8`,
|
||||
|
||||
indexBackgroundButtonHover: `#BED3EF`,
|
||||
indexArrowButtonHover: `#4781D1`,
|
||||
|
||||
borderImageCheckbox: `linear-gradient(to right, ${white} 24px, ${grayLightMid} 24px)`,
|
||||
borderImageContextMenu: `linear-gradient(to left, ${white} 24px, ${grayLightMid} 24px)`,
|
||||
|
6
public/images/edit.index.react.svg
Normal file
6
public/images/edit.index.react.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="1" width="16" height="2" rx="1" fill="#333333"/>
|
||||
<rect y="5" width="13" height="2" rx="1" fill="#333333"/>
|
||||
<rect y="9" width="10" height="2" rx="1" fill="#333333"/>
|
||||
<rect y="13" width="7" height="2" rx="1" fill="#333333"/>
|
||||
</svg>
|
After Width: | Height: | Size: 335 B |
10
public/images/rounded arrow.react.svg
Normal file
10
public/images/rounded arrow.react.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2269_37870)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75736 3.75736C4.84424 2.67048 6.34287 2 8 2C11.3137 2 14 4.68629 14 8H16C16 3.58172 12.4183 0 8 0C5.79413 0 3.79519 0.894098 2.34903 2.33727L2.34682 2.33941L2.3235 2.36228C2.30404 2.38149 2.27684 2.40861 2.24255 2.44351C2.18243 2.50467 2.10045 2.58976 2 2.69795L2 1L0 1L0 5C0 5.55228 0.447715 6 1 6L5 6V4L3.52058 4C3.58201 3.93468 3.632 3.88303 3.66896 3.84542C3.696 3.81791 3.71606 3.79793 3.72851 3.78563L3.7414 3.77298L3.74296 3.77147L3.74328 3.77116L3.74331 3.77114L3.74343 3.77102L3.74997 3.76475L3.75736 3.75736ZM8 14C4.68629 14 2 11.3137 2 8H0C0 12.4183 3.58172 16 8 16C10.3903 16 12.535 14.9513 14 13.2915V15H16L16 11C16 10.4477 15.5523 10 15 10H11V12H12.4724C11.3728 13.2286 9.77618 14 8 14Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2269_37870">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1022 B |
@ -143,6 +143,7 @@
|
||||
"EditButton": "Edit",
|
||||
"Editing": "Editing",
|
||||
"Editor": "Editor",
|
||||
"EditIndex": "Edit index",
|
||||
"EditPDFForm": "Edit PDF form",
|
||||
"Email": "Email",
|
||||
"EmptyDescription": "The list of users previously invited to {{productName}} or separate rooms will appear here. You will be able to invite these users for collaboration at any time.",
|
||||
@ -356,6 +357,7 @@
|
||||
"ReloadPage": "Reload page",
|
||||
"Remember": "Remember me",
|
||||
"Remove": "Remove",
|
||||
"Reorder": "Reorder",
|
||||
"Rename": "Rename",
|
||||
"RenewSubscription": "Renew subscription?",
|
||||
"RepeatInvitation": "Repeat invitation",
|
||||
@ -432,6 +434,7 @@
|
||||
"SkipTitle": "Skip",
|
||||
"SomethingWentWrong": "Something went wrong.",
|
||||
"SortBy": "Sort by",
|
||||
"SortingIndex": "Sorting Index",
|
||||
"SpaceManagement": "Space Management",
|
||||
"Spaces": "Spaces",
|
||||
"SpacesInLocalPart": "Local part can't contain spaces",
|
||||
@ -488,12 +491,27 @@
|
||||
"Website": "Website",
|
||||
"Yes": "Yes",
|
||||
"Yesterday": "Yesterday",
|
||||
"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."
|
||||
"FormFilingRoomDescription": "Invite users to fill out a ready PDF form. Check the complete forms and analyze data automatically collected in a spreadsheet.",
|
||||
"PublicRoomDescription": "Invite users via external links to view documents without registration. You can also embed this room into any web interface.",
|
||||
"FillingFormsRoomTitle": "Filling forms room",
|
||||
"CollaborationRoomTitle": "Collaboration room",
|
||||
"CustomRoomDescription": "Apply your own settings to use this room for any custom purpose.",
|
||||
"ReviewRoomTitle": "Review room",
|
||||
"ViewOnlyRoomDescription": "Share any ready documents, reports, documentation, and other files for viewing.",
|
||||
"ViewOnlyRoomTitle": "View-only room",
|
||||
"ReviewRoomDescription": "Request a review or comments on the documents",
|
||||
"CustomRoomTitle": "Custom room",
|
||||
"CollaborationRoomDescription": "Collaborate on one or multiple documents with your team",
|
||||
"FormFilingRoomTitle": "Form Filling Room",
|
||||
"FillingFormsRoomDescription": "Build, share and fill document templates or work with the ready presets to quickly create documents of any type.",
|
||||
"PublicRoom": "Public room",
|
||||
"FillingFormRooms": "Filling form",
|
||||
"CollaborationRooms": "Collaboration",
|
||||
"ViewOnlyRooms": "View-only",
|
||||
"CustomRooms": "Custom",
|
||||
"FormRoom": "Form room",
|
||||
"NewRoom": "New 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.",
|
||||
"VirtualDataRoom": "Virtual Data Room"
|
||||
}
|
||||
|
@ -136,6 +136,7 @@
|
||||
"DropzoneTitleSecondary": "или перетащите файл сюда",
|
||||
"Duplicate": "Дублировать",
|
||||
"EditButton": "Редактировать",
|
||||
"EditIndex": "Редактировать индекс",
|
||||
"Editing": "Редактирование",
|
||||
"Editor": "Редактор",
|
||||
"Email": "Email",
|
||||
@ -411,6 +412,7 @@
|
||||
"SkipTitle": "Пропустить",
|
||||
"SomethingWentWrong": "Что-то пошло не так.",
|
||||
"SortBy": "Сортировать по",
|
||||
"SortingIndex": "Сортировать индекс",
|
||||
"SpaceManagement": "Управление Пространством",
|
||||
"Spaces": "Пространства",
|
||||
"SpacesInLocalPart": "Имя почтового ящика содержит пробелы",
|
||||
|
Loading…
Reference in New Issue
Block a user