Web: Files: refactoring FilesRowContent, withContentActions
This commit is contained in:
parent
0131520988
commit
6381a0c524
@ -1,77 +1,24 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { withRouter } from "react-router";
|
import { withRouter } from "react-router";
|
||||||
import { Trans, withTranslation } from "react-i18next";
|
import { withTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { isMobile } from "react-device-detect";
|
||||||
|
|
||||||
import Link from "@appserver/components/link";
|
import Link from "@appserver/components/link";
|
||||||
import Text from "@appserver/components/text";
|
import Text from "@appserver/components/text";
|
||||||
import RowContent from "@appserver/components/row-content";
|
import RowContent from "@appserver/components/row-content";
|
||||||
import IconButton from "@appserver/components/icon-button";
|
import IconButton from "@appserver/components/icon-button";
|
||||||
import Badge from "@appserver/components/badge";
|
import Badge from "@appserver/components/badge";
|
||||||
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
|
|
||||||
|
import withContentActions from "../hoc/withContentActions";
|
||||||
import {
|
import {
|
||||||
convertFile,
|
StyledFavoriteIcon,
|
||||||
getFileConversationProgress,
|
StyledFileActionsConvertEditDocIcon,
|
||||||
} from "@appserver/common/api/files";
|
StyledFileActionsLockedIcon,
|
||||||
import {
|
} from "../sub-components/icons";
|
||||||
AppServerConfig,
|
|
||||||
FileAction,
|
|
||||||
ShareAccessRights,
|
|
||||||
} from "@appserver/common/constants";
|
|
||||||
import toastr from "studio/toastr";
|
|
||||||
import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg";
|
|
||||||
import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg";
|
|
||||||
import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg";
|
|
||||||
import CheckIcon from "../../../../../../../public/images/check.react.svg";
|
|
||||||
import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg";
|
|
||||||
import { TIMEOUT } from "../../../../../../helpers/constants";
|
|
||||||
import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers";
|
|
||||||
import { ConvertDialog } from "../../../../../dialogs";
|
|
||||||
import EditingWrapperComponent from "../sub-components/EditingWrapperComponent";
|
|
||||||
import { isMobile } from "react-device-detect";
|
|
||||||
import { observer, inject } from "mobx-react";
|
|
||||||
import config from "../../../../../../../package.json";
|
|
||||||
import { combineUrl } from "@appserver/common/utils";
|
|
||||||
|
|
||||||
const sideColor = "#A3A9AE";
|
const sideColor = "#A3A9AE";
|
||||||
const StyledCheckIcon = styled(CheckIcon)`
|
|
||||||
${commonIconsStyles}
|
|
||||||
path {
|
|
||||||
fill: #a3a9ae;
|
|
||||||
}
|
|
||||||
:hover {
|
|
||||||
fill: #657077;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledCrossIcon = styled(CrossIcon)`
|
|
||||||
${commonIconsStyles}
|
|
||||||
path {
|
|
||||||
fill: #a3a9ae;
|
|
||||||
}
|
|
||||||
:hover {
|
|
||||||
fill: #657077;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledFavoriteIcon = styled(FavoriteIcon)`
|
|
||||||
${commonIconsStyles}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledFileActionsConvertEditDocIcon = styled(
|
|
||||||
FileActionsConvertEditDocIcon
|
|
||||||
)`
|
|
||||||
${commonIconsStyles}
|
|
||||||
path {
|
|
||||||
fill: #3b72a7;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledFileActionsLockedIcon = styled(FileActionsLockedIcon)`
|
|
||||||
${commonIconsStyles}
|
|
||||||
path {
|
|
||||||
fill: #3b72a7;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const SimpleFilesRowContent = styled(RowContent)`
|
const SimpleFilesRowContent = styled(RowContent)`
|
||||||
.badge-ext {
|
.badge-ext {
|
||||||
margin-left: -8px;
|
margin-left: -8px;
|
||||||
@ -107,427 +54,29 @@ const SimpleFilesRowContent = styled(RowContent)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const okIcon = <StyledCheckIcon className="edit-ok-icon" size="scale" />;
|
const FilesRowContent = ({
|
||||||
|
|
||||||
const cancelIcon = (
|
|
||||||
<StyledCrossIcon className="edit-cancel-icon" size="scale" />
|
|
||||||
);
|
|
||||||
|
|
||||||
class FilesRowContent extends React.PureComponent {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
let titleWithoutExt = getTitleWithoutExst(props.item);
|
|
||||||
|
|
||||||
if (props.fileActionId === -1) {
|
|
||||||
titleWithoutExt = this.getDefaultName(props.fileActionExt);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
itemTitle: titleWithoutExt,
|
|
||||||
showConvertDialog: false,
|
|
||||||
//loading: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
completeAction = (id) => {
|
|
||||||
const isCancel =
|
|
||||||
(id.currentTarget && id.currentTarget.dataset.action === "cancel") ||
|
|
||||||
id.keyCode === 27;
|
|
||||||
this.props.editCompleteAction(id, this.props.item, isCancel);
|
|
||||||
};
|
|
||||||
|
|
||||||
updateItem = () => {
|
|
||||||
const {
|
|
||||||
updateFile,
|
|
||||||
renameFolder,
|
|
||||||
item,
|
|
||||||
setIsLoading,
|
|
||||||
fileActionId,
|
|
||||||
editCompleteAction,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { itemTitle } = this.state;
|
|
||||||
const originalTitle = getTitleWithoutExst(item);
|
|
||||||
|
|
||||||
setIsLoading(true);
|
|
||||||
const isSameTitle =
|
|
||||||
originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === "";
|
|
||||||
if (isSameTitle) {
|
|
||||||
this.setState({
|
|
||||||
itemTitle: originalTitle,
|
|
||||||
});
|
|
||||||
return editCompleteAction(fileActionId, item, isSameTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
item.fileExst || item.contentLength
|
|
||||||
? updateFile(fileActionId, itemTitle)
|
|
||||||
.then(() => this.completeAction(fileActionId))
|
|
||||||
.finally(() => setIsLoading(false))
|
|
||||||
: renameFolder(fileActionId, itemTitle)
|
|
||||||
.then(() => this.completeAction(fileActionId))
|
|
||||||
.finally(() => setIsLoading(false));
|
|
||||||
};
|
|
||||||
|
|
||||||
createItem = (e) => {
|
|
||||||
const {
|
|
||||||
createFile,
|
|
||||||
item,
|
|
||||||
setIsLoading,
|
|
||||||
openDocEditor,
|
|
||||||
isPrivacy,
|
|
||||||
isDesktop,
|
|
||||||
replaceFileStream,
|
|
||||||
t,
|
|
||||||
setEncryptionAccess,
|
|
||||||
createFolder,
|
|
||||||
} = this.props;
|
|
||||||
const { itemTitle } = this.state;
|
|
||||||
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
const itemId = e.currentTarget.dataset.itemid;
|
|
||||||
|
|
||||||
if (itemTitle.trim() === "") {
|
|
||||||
toastr.warning(this.props.t("CreateWithEmptyTitle"));
|
|
||||||
return this.completeAction(itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tab =
|
|
||||||
!isDesktop && item.fileExst
|
|
||||||
? window.open(
|
|
||||||
combineUrl(
|
|
||||||
AppServerConfig.proxyURL,
|
|
||||||
config.homepage,
|
|
||||||
"/products/files/doceditor"
|
|
||||||
),
|
|
||||||
"_blank"
|
|
||||||
)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
!item.fileExst && !item.contentLength
|
|
||||||
? createFolder(item.parentId, itemTitle)
|
|
||||||
.then(() => this.completeAction(itemId))
|
|
||||||
.then(() =>
|
|
||||||
toastr.success(
|
|
||||||
<Trans t={t} i18nKey="FolderCreated" ns="Home">
|
|
||||||
New folder {{ itemTitle }} is created
|
|
||||||
</Trans>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.catch((e) => toastr.error(e))
|
|
||||||
.finally(() => {
|
|
||||||
return setIsLoading(false);
|
|
||||||
})
|
|
||||||
: createFile(item.parentId, `${itemTitle}.${item.fileExst}`)
|
|
||||||
.then((file) => {
|
|
||||||
if (isPrivacy) {
|
|
||||||
return setEncryptionAccess(file).then((encryptedFile) => {
|
|
||||||
if (!encryptedFile) return Promise.resolve();
|
|
||||||
toastr.info(t("EncryptedFileSaving"));
|
|
||||||
return replaceFileStream(
|
|
||||||
file.id,
|
|
||||||
encryptedFile,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
).then(() =>
|
|
||||||
openDocEditor(file.id, file.providerKey, tab, file.webUrl)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return openDocEditor(file.id, file.providerKey, tab, file.webUrl);
|
|
||||||
})
|
|
||||||
.then(() => this.completeAction(itemId))
|
|
||||||
.then(() => {
|
|
||||||
const exst = item.fileExst;
|
|
||||||
return toastr.success(
|
|
||||||
<Trans i18nKey="FileCreated" ns="Home">
|
|
||||||
New file {{ itemTitle }}.{{ exst }} is created
|
|
||||||
</Trans>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch((e) => toastr.error(e))
|
|
||||||
.finally(() => {
|
|
||||||
return setIsLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
const { fileActionId, fileActionExt } = this.props;
|
|
||||||
if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) {
|
|
||||||
const itemTitle = this.getDefaultName(fileActionExt);
|
|
||||||
this.setState({ itemTitle });
|
|
||||||
}
|
|
||||||
// if (fileAction) {
|
|
||||||
// if (fileActionId !== prevProps.fileActionId) {
|
|
||||||
// this.setState({ editingId: fileActionId });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
renameTitle = (e) => {
|
|
||||||
let title = e.target.value;
|
|
||||||
//const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate
|
|
||||||
const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim");
|
|
||||||
if (title.match(regexp)) {
|
|
||||||
toastr.warning(this.props.t("ContainsSpecCharacter"));
|
|
||||||
}
|
|
||||||
title = title.replace(regexp, "_");
|
|
||||||
return this.setState({ itemTitle: title });
|
|
||||||
};
|
|
||||||
|
|
||||||
cancelUpdateItem = (e) => {
|
|
||||||
const originalTitle = getTitleWithoutExst(this.props.item);
|
|
||||||
this.setState({
|
|
||||||
itemTitle: originalTitle,
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.completeAction(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
onClickUpdateItem = (e) => {
|
|
||||||
this.props.fileActionType === FileAction.Create
|
|
||||||
? this.createItem(e)
|
|
||||||
: this.updateItem(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
onFilesClick = () => {
|
|
||||||
const {
|
|
||||||
filter,
|
|
||||||
parentFolder,
|
|
||||||
setIsLoading,
|
|
||||||
fetchFiles,
|
|
||||||
isImage,
|
|
||||||
isSound,
|
|
||||||
isVideo,
|
|
||||||
canWebEdit,
|
|
||||||
item,
|
|
||||||
isTrashFolder,
|
|
||||||
openDocEditor,
|
|
||||||
expandedKeys,
|
|
||||||
addExpandedKeys,
|
|
||||||
setMediaViewerData,
|
|
||||||
} = this.props;
|
|
||||||
const { id, fileExst, viewUrl, providerKey, contentLength } = item;
|
|
||||||
|
|
||||||
if (isTrashFolder) return;
|
|
||||||
|
|
||||||
if (!fileExst && !contentLength) {
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
if (!expandedKeys.includes(parentFolder + "")) {
|
|
||||||
addExpandedKeys(parentFolder + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchFiles(id, filter)
|
|
||||||
.catch((err) => {
|
|
||||||
toastr.error(err);
|
|
||||||
setIsLoading(false);
|
|
||||||
})
|
|
||||||
.finally(() => setIsLoading(false));
|
|
||||||
} else {
|
|
||||||
if (canWebEdit) {
|
|
||||||
return openDocEditor(id, providerKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isImage || isSound || isVideo) {
|
|
||||||
setMediaViewerData({ visible: true, id });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window.open(viewUrl, "_blank");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMobileRowClick = () => {
|
|
||||||
if (this.props.isTrashFolder || window.innerWidth > 1024) return;
|
|
||||||
this.onFilesClick();
|
|
||||||
};
|
|
||||||
|
|
||||||
getStatusByDate = () => {
|
|
||||||
const { culture, t, item, sectionWidth } = this.props;
|
|
||||||
const { created, updated, version, fileExst } = item;
|
|
||||||
|
|
||||||
const title =
|
|
||||||
version > 1
|
|
||||||
? t("TitleModified")
|
|
||||||
: fileExst
|
|
||||||
? t("TitleUploaded")
|
|
||||||
: t("TitleCreated");
|
|
||||||
|
|
||||||
const date = fileExst ? updated : created;
|
|
||||||
const dateLabel = new Date(date).toLocaleString(culture);
|
|
||||||
const mobile = (sectionWidth && sectionWidth <= 375) || isMobile;
|
|
||||||
|
|
||||||
return mobile ? dateLabel : `${title}: ${dateLabel}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
getDefaultName = (format) => {
|
|
||||||
const { t } = this.props;
|
|
||||||
|
|
||||||
switch (format) {
|
|
||||||
case "docx":
|
|
||||||
return t("NewDocument");
|
|
||||||
case "xlsx":
|
|
||||||
return t("NewSpreadsheet");
|
|
||||||
case "pptx":
|
|
||||||
return t("NewPresentation");
|
|
||||||
default:
|
|
||||||
return t("NewFolder");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onShowVersionHistory = () => {
|
|
||||||
const {
|
|
||||||
homepage,
|
|
||||||
isTabletView,
|
|
||||||
item,
|
|
||||||
setIsVerHistoryPanel,
|
|
||||||
fetchFileVersions,
|
|
||||||
history,
|
|
||||||
isTrashFolder,
|
|
||||||
} = this.props;
|
|
||||||
if (isTrashFolder) return;
|
|
||||||
|
|
||||||
if (!isTabletView) {
|
|
||||||
fetchFileVersions(item.id + "");
|
|
||||||
setIsVerHistoryPanel(true);
|
|
||||||
} else {
|
|
||||||
history.push(
|
|
||||||
combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onBadgeClick = () => {
|
|
||||||
const {
|
|
||||||
item,
|
|
||||||
selectedFolderPathParts,
|
|
||||||
markAsRead,
|
|
||||||
setNewFilesPanelVisible,
|
|
||||||
setNewFilesIds,
|
|
||||||
updateRootBadge,
|
|
||||||
updateFileBadge,
|
|
||||||
} = this.props;
|
|
||||||
if (item.fileExst) {
|
|
||||||
markAsRead([], [item.id])
|
|
||||||
.then(() => {
|
|
||||||
updateRootBadge(selectedFolderPathParts[0], 1);
|
|
||||||
updateFileBadge(item.id);
|
|
||||||
})
|
|
||||||
.catch((err) => toastr.error(err));
|
|
||||||
} else {
|
|
||||||
setNewFilesPanelVisible(true);
|
|
||||||
const newFolderIds = this.props.selectedFolderPathParts;
|
|
||||||
newFolderIds.push(item.id);
|
|
||||||
setNewFilesIds(newFolderIds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setConvertDialogVisible = () =>
|
|
||||||
this.setState({ showConvertDialog: !this.state.showConvertDialog });
|
|
||||||
|
|
||||||
getConvertProgress = (fileId) => {
|
|
||||||
const {
|
|
||||||
selectedFolderId,
|
|
||||||
filter,
|
|
||||||
setIsLoading,
|
|
||||||
setSecondaryProgressBarData,
|
|
||||||
t,
|
|
||||||
clearSecondaryProgressData,
|
|
||||||
fetchFiles,
|
|
||||||
} = this.props;
|
|
||||||
getFileConversationProgress(fileId).then((res) => {
|
|
||||||
if (res && res[0] && res[0].progress !== 100) {
|
|
||||||
setSecondaryProgressBarData({
|
|
||||||
icon: "file",
|
|
||||||
visible: true,
|
|
||||||
percent: res[0].progress,
|
|
||||||
label: t("Convert"),
|
|
||||||
alert: false,
|
|
||||||
});
|
|
||||||
setTimeout(() => this.getConvertProgress(fileId), 1000);
|
|
||||||
} else {
|
|
||||||
if (res[0].error) {
|
|
||||||
setSecondaryProgressBarData({
|
|
||||||
visible: true,
|
|
||||||
alert: true,
|
|
||||||
});
|
|
||||||
toastr.error(res[0].error);
|
|
||||||
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
|
||||||
} else {
|
|
||||||
setSecondaryProgressBarData({
|
|
||||||
icon: "file",
|
|
||||||
visible: true,
|
|
||||||
percent: 100,
|
|
||||||
label: t("Convert"),
|
|
||||||
alert: false,
|
|
||||||
});
|
|
||||||
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
|
||||||
const newFilter = filter.clone();
|
|
||||||
fetchFiles(selectedFolderId, newFilter)
|
|
||||||
.catch((err) => {
|
|
||||||
setSecondaryProgressBarData({
|
|
||||||
visible: true,
|
|
||||||
alert: true,
|
|
||||||
});
|
|
||||||
//toastr.error(err);
|
|
||||||
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
|
||||||
})
|
|
||||||
.finally(() => setIsLoading(false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onConvert = () => {
|
|
||||||
const { item, t, setSecondaryProgressBarData } = this.props;
|
|
||||||
setSecondaryProgressBarData({
|
|
||||||
icon: "file",
|
|
||||||
visible: true,
|
|
||||||
percent: 0,
|
|
||||||
label: t("Convert"),
|
|
||||||
alert: false,
|
|
||||||
});
|
|
||||||
this.setState({ showConvertDialog: false }, () =>
|
|
||||||
convertFile(item.id).then((convertRes) => {
|
|
||||||
if (convertRes && convertRes[0] && convertRes[0].progress !== 100) {
|
|
||||||
this.getConvertProgress(item.id);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onClickLock = () => {
|
|
||||||
const { item } = this.props;
|
|
||||||
const { locked, id } = item;
|
|
||||||
this.props.lockFileAction(id, !locked).catch((err) => toastr.error(err));
|
|
||||||
};
|
|
||||||
|
|
||||||
onClickFavorite = () => {
|
|
||||||
const { t, item } = this.props;
|
|
||||||
this.props
|
|
||||||
.setFavoriteAction("remove", item.id)
|
|
||||||
.then(() => toastr.success(t("RemovedFromFavorites")))
|
|
||||||
.catch((err) => toastr.error(err));
|
|
||||||
};
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
t,
|
t,
|
||||||
item,
|
item,
|
||||||
isTrashFolder,
|
sectionWidth,
|
||||||
isLoading,
|
titleWithoutExt,
|
||||||
isMobile,
|
updatedDate,
|
||||||
|
fileOwner,
|
||||||
|
accessToEdit,
|
||||||
|
linkStyles,
|
||||||
|
newItems,
|
||||||
|
showNew,
|
||||||
canWebEdit,
|
canWebEdit,
|
||||||
/* canConvert,*/
|
/* canConvert,*/
|
||||||
sectionWidth,
|
isTrashFolder,
|
||||||
fileActionId,
|
onFilesClick,
|
||||||
fileActionExt,
|
onShowVersionHistory,
|
||||||
} = this.props;
|
onBadgeClick,
|
||||||
const { itemTitle, showConvertDialog } = this.state;
|
onClickLock,
|
||||||
|
onClickFavorite,
|
||||||
|
/*setConvertDialogVisible*/
|
||||||
|
}) => {
|
||||||
const {
|
const {
|
||||||
contentLength,
|
contentLength,
|
||||||
updated,
|
|
||||||
createdBy,
|
|
||||||
fileExst,
|
fileExst,
|
||||||
filesCount,
|
filesCount,
|
||||||
foldersCount,
|
foldersCount,
|
||||||
@ -537,51 +86,20 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
locked,
|
locked,
|
||||||
providerKey,
|
providerKey,
|
||||||
} = item;
|
} = item;
|
||||||
const titleWithoutExt = getTitleWithoutExst(item);
|
|
||||||
const fileOwner =
|
|
||||||
createdBy &&
|
|
||||||
((this.props.viewer.id === createdBy.id && t("AuthorMe")) ||
|
|
||||||
createdBy.displayName);
|
|
||||||
const updatedDate = updated && this.getStatusByDate();
|
|
||||||
|
|
||||||
const accessToEdit =
|
const onMobileRowClick = () => {
|
||||||
item.access === ShareAccessRights.FullAccess ||
|
if (isTrashFolder || window.innerWidth > 1024) return;
|
||||||
item.access === ShareAccessRights.None; // TODO: fix access type for owner (now - None)
|
onFilesClick();
|
||||||
const isEdit = id === fileActionId && fileExst === fileActionExt;
|
};
|
||||||
|
|
||||||
const linkStyles = isTrashFolder //|| window.innerWidth <= 1024
|
return (
|
||||||
? { noHover: true }
|
|
||||||
: { onClick: this.onFilesClick };
|
|
||||||
|
|
||||||
const newItems = item.new || fileStatus === 2;
|
|
||||||
const showNew = !!newItems;
|
|
||||||
|
|
||||||
return isEdit ? (
|
|
||||||
<EditingWrapperComponent
|
|
||||||
itemTitle={itemTitle}
|
|
||||||
okIcon={okIcon}
|
|
||||||
cancelIcon={cancelIcon}
|
|
||||||
renameTitle={this.renameTitle}
|
|
||||||
onClickUpdateItem={this.onClickUpdateItem}
|
|
||||||
cancelUpdateItem={this.cancelUpdateItem}
|
|
||||||
itemId={id}
|
|
||||||
isLoading={isLoading}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
{showConvertDialog && (
|
|
||||||
<ConvertDialog
|
|
||||||
visible={showConvertDialog}
|
|
||||||
onClose={this.setConvertDialogVisible}
|
|
||||||
onConvert={this.onConvert}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<SimpleFilesRowContent
|
<SimpleFilesRowContent
|
||||||
sectionWidth={sectionWidth}
|
sectionWidth={sectionWidth}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
sideColor={sideColor}
|
sideColor={sideColor}
|
||||||
isFile={fileExst || contentLength}
|
isFile={fileExst || contentLength}
|
||||||
//onClick={this.onMobileRowClick}
|
//onClick={onMobileRowClick}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
containerWidth="55%"
|
containerWidth="55%"
|
||||||
@ -611,7 +129,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
</Text>
|
</Text>
|
||||||
{/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && (
|
{/* TODO: Uncomment after fix conversation {canConvert && !isTrashFolder && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={this.setConvertDialogVisible}
|
onClick={setConvertDialogVisible}
|
||||||
iconName="FileActionsConvertIcon"
|
iconName="FileActionsConvertIcon"
|
||||||
className="badge"
|
className="badge"
|
||||||
size="small"
|
size="small"
|
||||||
@ -622,7 +140,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
)} */}
|
)} */}
|
||||||
{canWebEdit && !isTrashFolder && accessToEdit && (
|
{canWebEdit && !isTrashFolder && accessToEdit && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={this.onFilesClick}
|
onClick={onFilesClick}
|
||||||
iconName="/static/images/access.edit.react.svg"
|
iconName="/static/images/access.edit.react.svg"
|
||||||
className="badge"
|
className="badge"
|
||||||
size="small"
|
size="small"
|
||||||
@ -637,7 +155,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
size="small"
|
size="small"
|
||||||
data-id={item.id}
|
data-id={item.id}
|
||||||
data-locked={true}
|
data-locked={true}
|
||||||
onClick={this.onClickLock}
|
onClick={onClickLock}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{fileStatus === 32 && !isTrashFolder && (
|
{fileStatus === 32 && !isTrashFolder && (
|
||||||
@ -647,7 +165,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
data-action="remove"
|
data-action="remove"
|
||||||
data-id={item.id}
|
data-id={item.id}
|
||||||
data-title={item.title}
|
data-title={item.title}
|
||||||
onClick={this.onClickFavorite}
|
onClick={onClickFavorite}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{fileStatus === 1 && (
|
{fileStatus === 1 && (
|
||||||
@ -668,7 +186,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
version: versionGroup,
|
version: versionGroup,
|
||||||
})}
|
})}
|
||||||
maxWidth="50px"
|
maxWidth="50px"
|
||||||
onClick={this.onShowVersionHistory}
|
onClick={onShowVersionHistory}
|
||||||
padding="0 5px"
|
padding="0 5px"
|
||||||
data-id={id}
|
data-id={id}
|
||||||
/>
|
/>
|
||||||
@ -683,7 +201,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
fontWeight={800}
|
fontWeight={800}
|
||||||
label={t("New")}
|
label={t("New")}
|
||||||
maxWidth="50px"
|
maxWidth="50px"
|
||||||
onClick={this.onBadgeClick}
|
onClick={onBadgeClick}
|
||||||
padding="0 5px"
|
padding="0 5px"
|
||||||
data-id={id}
|
data-id={id}
|
||||||
/>
|
/>
|
||||||
@ -701,7 +219,7 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
fontWeight={800}
|
fontWeight={800}
|
||||||
label={newItems}
|
label={newItems}
|
||||||
maxWidth="50px"
|
maxWidth="50px"
|
||||||
onClick={this.onBadgeClick}
|
onClick={onBadgeClick}
|
||||||
padding="0 5px"
|
padding="0 5px"
|
||||||
data-id={id}
|
data-id={id}
|
||||||
/>
|
/>
|
||||||
@ -755,129 +273,8 @@ class FilesRowContent extends React.PureComponent {
|
|||||||
</SimpleFilesRowContent>
|
</SimpleFilesRowContent>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default inject(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
auth,
|
|
||||||
filesStore,
|
|
||||||
formatsStore,
|
|
||||||
uploadDataStore,
|
|
||||||
treeFoldersStore,
|
|
||||||
selectedFolderStore,
|
|
||||||
filesActionsStore,
|
|
||||||
mediaViewerDataStore,
|
|
||||||
versionHistoryStore,
|
|
||||||
dialogsStore,
|
|
||||||
},
|
|
||||||
{ item }
|
|
||||||
) => {
|
|
||||||
const { replaceFileStream, setEncryptionAccess } = auth;
|
|
||||||
const { culture, isDesktopClient, isTabletView } = auth.settingsStore;
|
|
||||||
const { secondaryProgressDataStore } = uploadDataStore;
|
|
||||||
const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore;
|
|
||||||
const {
|
|
||||||
iconFormatsStore,
|
|
||||||
mediaViewersFormatsStore,
|
|
||||||
docserviceStore,
|
|
||||||
} = formatsStore;
|
|
||||||
|
|
||||||
const {
|
|
||||||
fetchFiles,
|
|
||||||
filter,
|
|
||||||
createFile,
|
|
||||||
updateFile,
|
|
||||||
renameFolder,
|
|
||||||
createFolder,
|
|
||||||
openDocEditor,
|
|
||||||
setIsLoading,
|
|
||||||
isLoading,
|
|
||||||
updateFileBadge,
|
|
||||||
} = filesStore;
|
|
||||||
|
|
||||||
const {
|
|
||||||
isRecycleBinFolder,
|
|
||||||
isPrivacyFolder,
|
|
||||||
expandedKeys,
|
|
||||||
addExpandedKeys,
|
|
||||||
updateRootBadge,
|
|
||||||
} = treeFoldersStore;
|
|
||||||
|
|
||||||
const {
|
|
||||||
type: fileActionType,
|
|
||||||
extension: fileActionExt,
|
|
||||||
id: fileActionId,
|
|
||||||
} = filesStore.fileActionStore;
|
|
||||||
|
|
||||||
const {
|
|
||||||
setSecondaryProgressBarData,
|
|
||||||
clearSecondaryProgressData,
|
|
||||||
} = secondaryProgressDataStore;
|
|
||||||
|
|
||||||
const canWebEdit = docserviceStore.canWebEdit(item.fileExst);
|
|
||||||
const canConvert = docserviceStore.canConvert(item.fileExst);
|
|
||||||
const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst);
|
|
||||||
const isImage = iconFormatsStore.isImage(item.fileExst);
|
|
||||||
const isSound = iconFormatsStore.isSound(item.fileExst);
|
|
||||||
|
|
||||||
const { setMediaViewerData } = mediaViewerDataStore;
|
|
||||||
const {
|
|
||||||
editCompleteAction,
|
|
||||||
lockFileAction,
|
|
||||||
setFavoriteAction,
|
|
||||||
markAsRead,
|
|
||||||
} = filesActionsStore;
|
|
||||||
|
|
||||||
const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore;
|
|
||||||
|
|
||||||
return {
|
|
||||||
isDesktop: isDesktopClient,
|
|
||||||
isTabletView,
|
|
||||||
homepage: config.homepage,
|
|
||||||
viewer: auth.userStore.user,
|
|
||||||
culture,
|
|
||||||
fileActionId,
|
|
||||||
fileActionType,
|
|
||||||
fileActionExt,
|
|
||||||
selectedFolderId: selectedFolderStore.id,
|
|
||||||
selectedFolderPathParts: selectedFolderStore.pathParts,
|
|
||||||
parentFolder: selectedFolderStore.parentId,
|
|
||||||
isLoading,
|
|
||||||
isTrashFolder: isRecycleBinFolder,
|
|
||||||
isPrivacy: isPrivacyFolder,
|
|
||||||
filter,
|
|
||||||
canWebEdit,
|
|
||||||
canConvert,
|
|
||||||
isVideo,
|
|
||||||
isImage,
|
|
||||||
isSound,
|
|
||||||
expandedKeys,
|
|
||||||
|
|
||||||
setIsLoading,
|
|
||||||
fetchFiles,
|
|
||||||
setSecondaryProgressBarData,
|
|
||||||
clearSecondaryProgressData,
|
|
||||||
createFile,
|
|
||||||
createFolder,
|
|
||||||
updateFile,
|
|
||||||
renameFolder,
|
|
||||||
replaceFileStream,
|
|
||||||
setEncryptionAccess,
|
|
||||||
addExpandedKeys,
|
|
||||||
openDocEditor,
|
|
||||||
editCompleteAction,
|
|
||||||
lockFileAction,
|
|
||||||
setFavoriteAction,
|
|
||||||
setMediaViewerData,
|
|
||||||
setIsVerHistoryPanel,
|
|
||||||
fetchFileVersions,
|
|
||||||
markAsRead,
|
|
||||||
setNewFilesPanelVisible,
|
|
||||||
setNewFilesIds,
|
|
||||||
updateRootBadge,
|
|
||||||
updateFileBadge,
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
)(withRouter(withTranslation("Home")(observer(FilesRowContent))));
|
export default withRouter(
|
||||||
|
withTranslation("Home")(withContentActions(FilesRowContent))
|
||||||
|
);
|
||||||
|
@ -0,0 +1,624 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { inject, observer } from "mobx-react";
|
||||||
|
import { Trans } from "react-i18next";
|
||||||
|
import { isMobile } from "react-device-detect";
|
||||||
|
|
||||||
|
import toastr from "studio/toastr";
|
||||||
|
import {
|
||||||
|
AppServerConfig,
|
||||||
|
FileAction,
|
||||||
|
ShareAccessRights,
|
||||||
|
} from "@appserver/common/constants";
|
||||||
|
import { combineUrl } from "@appserver/common/utils";
|
||||||
|
import {
|
||||||
|
convertFile,
|
||||||
|
getFileConversationProgress,
|
||||||
|
} from "@appserver/common/api/files";
|
||||||
|
|
||||||
|
import config from "../../../../../../../package.json";
|
||||||
|
import EditingWrapperComponent from "../sub-components/EditingWrapperComponent";
|
||||||
|
import { getTitleWithoutExst } from "../../../../../../helpers/files-helpers";
|
||||||
|
import { cancelIcon, okIcon } from "../sub-components/icons";
|
||||||
|
import { ConvertDialog } from "../../../../../dialogs";
|
||||||
|
|
||||||
|
export default function withContentActions(WrappedContent) {
|
||||||
|
class WithContentActions extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
let titleWithoutExt = getTitleWithoutExst(props.item);
|
||||||
|
|
||||||
|
if (props.fileActionId === -1) {
|
||||||
|
titleWithoutExt = this.getDefaultName(props.fileActionExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
itemTitle: titleWithoutExt,
|
||||||
|
showConvertDialog: false,
|
||||||
|
//loading: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { fileActionId, fileActionExt } = this.props;
|
||||||
|
if (fileActionId === -1 && fileActionExt !== prevProps.fileActionExt) {
|
||||||
|
const itemTitle = this.getDefaultName(fileActionExt);
|
||||||
|
this.setState({ itemTitle });
|
||||||
|
}
|
||||||
|
// if (fileAction) {
|
||||||
|
// if (fileActionId !== prevProps.fileActionId) {
|
||||||
|
// this.setState({ editingId: fileActionId });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultName = (format) => {
|
||||||
|
const { t } = this.props;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case "docx":
|
||||||
|
return t("NewDocument");
|
||||||
|
case "xlsx":
|
||||||
|
return t("NewSpreadsheet");
|
||||||
|
case "pptx":
|
||||||
|
return t("NewPresentation");
|
||||||
|
default:
|
||||||
|
return t("NewFolder");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
completeAction = (id) => {
|
||||||
|
const { editCompleteAction, item } = this.props;
|
||||||
|
|
||||||
|
const isCancel =
|
||||||
|
(id.currentTarget && id.currentTarget.dataset.action === "cancel") ||
|
||||||
|
id.keyCode === 27;
|
||||||
|
editCompleteAction(id, item, isCancel);
|
||||||
|
};
|
||||||
|
|
||||||
|
onFilesClick = () => {
|
||||||
|
const {
|
||||||
|
filter,
|
||||||
|
parentFolder,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
isImage,
|
||||||
|
isSound,
|
||||||
|
isVideo,
|
||||||
|
canWebEdit,
|
||||||
|
item,
|
||||||
|
isTrashFolder,
|
||||||
|
openDocEditor,
|
||||||
|
expandedKeys,
|
||||||
|
addExpandedKeys,
|
||||||
|
setMediaViewerData,
|
||||||
|
} = this.props;
|
||||||
|
const { id, fileExst, viewUrl, providerKey, contentLength } = item;
|
||||||
|
|
||||||
|
if (isTrashFolder) return;
|
||||||
|
|
||||||
|
if (!fileExst && !contentLength) {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
if (!expandedKeys.includes(parentFolder + "")) {
|
||||||
|
addExpandedKeys(parentFolder + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchFiles(id, filter)
|
||||||
|
.catch((err) => {
|
||||||
|
toastr.error(err);
|
||||||
|
setIsLoading(false);
|
||||||
|
})
|
||||||
|
.finally(() => setIsLoading(false));
|
||||||
|
} else {
|
||||||
|
if (canWebEdit) {
|
||||||
|
return openDocEditor(id, providerKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isImage || isSound || isVideo) {
|
||||||
|
setMediaViewerData({ visible: true, id });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.open(viewUrl, "_blank");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateItem = () => {
|
||||||
|
const {
|
||||||
|
updateFile,
|
||||||
|
renameFolder,
|
||||||
|
item,
|
||||||
|
setIsLoading,
|
||||||
|
fileActionId,
|
||||||
|
editCompleteAction,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const { itemTitle } = this.state;
|
||||||
|
const originalTitle = getTitleWithoutExst(item);
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
const isSameTitle =
|
||||||
|
originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === "";
|
||||||
|
if (isSameTitle) {
|
||||||
|
this.setState({
|
||||||
|
itemTitle: originalTitle,
|
||||||
|
});
|
||||||
|
return editCompleteAction(fileActionId, item, isSameTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
item.fileExst || item.contentLength
|
||||||
|
? updateFile(fileActionId, itemTitle)
|
||||||
|
.then(() => this.completeAction(fileActionId))
|
||||||
|
.finally(() => setIsLoading(false))
|
||||||
|
: renameFolder(fileActionId, itemTitle)
|
||||||
|
.then(() => this.completeAction(fileActionId))
|
||||||
|
.finally(() => setIsLoading(false));
|
||||||
|
};
|
||||||
|
|
||||||
|
cancelUpdateItem = (e) => {
|
||||||
|
const { item } = this.props;
|
||||||
|
|
||||||
|
const originalTitle = getTitleWithoutExst(item);
|
||||||
|
this.setState({
|
||||||
|
itemTitle: originalTitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.completeAction(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
onClickUpdateItem = (e) => {
|
||||||
|
const { fileActionType } = this.props;
|
||||||
|
|
||||||
|
fileActionType === FileAction.Create
|
||||||
|
? this.createItem(e)
|
||||||
|
: this.updateItem(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
createItem = (e) => {
|
||||||
|
const {
|
||||||
|
createFile,
|
||||||
|
item,
|
||||||
|
setIsLoading,
|
||||||
|
openDocEditor,
|
||||||
|
isPrivacy,
|
||||||
|
isDesktop,
|
||||||
|
replaceFileStream,
|
||||||
|
t,
|
||||||
|
setEncryptionAccess,
|
||||||
|
createFolder,
|
||||||
|
} = this.props;
|
||||||
|
const { itemTitle } = this.state;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const itemId = e.currentTarget.dataset.itemid;
|
||||||
|
|
||||||
|
if (itemTitle.trim() === "") {
|
||||||
|
toastr.warning(t("CreateWithEmptyTitle"));
|
||||||
|
return this.completeAction(itemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tab =
|
||||||
|
!isDesktop && item.fileExst
|
||||||
|
? window.open(
|
||||||
|
combineUrl(
|
||||||
|
AppServerConfig.proxyURL,
|
||||||
|
config.homepage,
|
||||||
|
"/products/files/doceditor"
|
||||||
|
),
|
||||||
|
"_blank"
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
!item.fileExst && !item.contentLength
|
||||||
|
? createFolder(item.parentId, itemTitle)
|
||||||
|
.then(() => this.completeAction(itemId))
|
||||||
|
.then(() =>
|
||||||
|
toastr.success(
|
||||||
|
<Trans t={t} i18nKey="FolderCreated" ns="Home">
|
||||||
|
New folder {{ itemTitle }} is created
|
||||||
|
</Trans>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.catch((e) => toastr.error(e))
|
||||||
|
.finally(() => {
|
||||||
|
return setIsLoading(false);
|
||||||
|
})
|
||||||
|
: createFile(item.parentId, `${itemTitle}.${item.fileExst}`)
|
||||||
|
.then((file) => {
|
||||||
|
if (isPrivacy) {
|
||||||
|
return setEncryptionAccess(file).then((encryptedFile) => {
|
||||||
|
if (!encryptedFile) return Promise.resolve();
|
||||||
|
toastr.info(t("EncryptedFileSaving"));
|
||||||
|
return replaceFileStream(
|
||||||
|
file.id,
|
||||||
|
encryptedFile,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
).then(() =>
|
||||||
|
openDocEditor(file.id, file.providerKey, tab, file.webUrl)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return openDocEditor(file.id, file.providerKey, tab, file.webUrl);
|
||||||
|
})
|
||||||
|
.then(() => this.completeAction(itemId))
|
||||||
|
.then(() => {
|
||||||
|
const exst = item.fileExst;
|
||||||
|
return toastr.success(
|
||||||
|
<Trans i18nKey="FileCreated" ns="Home">
|
||||||
|
New file {{ itemTitle }}.{{ exst }} is created
|
||||||
|
</Trans>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((e) => toastr.error(e))
|
||||||
|
.finally(() => {
|
||||||
|
return setIsLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renameTitle = (e) => {
|
||||||
|
const { t } = this.props;
|
||||||
|
|
||||||
|
let title = e.target.value;
|
||||||
|
//const chars = '*+:"<>?|/'; TODO: think how to solve problem with interpolation escape values in i18n translate
|
||||||
|
const regexp = new RegExp('[*+:"<>?|\\\\/]', "gim");
|
||||||
|
if (title.match(regexp)) {
|
||||||
|
toastr.warning(t("ContainsSpecCharacter"));
|
||||||
|
}
|
||||||
|
title = title.replace(regexp, "_");
|
||||||
|
return this.setState({ itemTitle: title });
|
||||||
|
};
|
||||||
|
|
||||||
|
getStatusByDate = () => {
|
||||||
|
const { culture, t, item, sectionWidth } = this.props;
|
||||||
|
const { created, updated, version, fileExst } = item;
|
||||||
|
|
||||||
|
const title =
|
||||||
|
version > 1
|
||||||
|
? t("TitleModified")
|
||||||
|
: fileExst
|
||||||
|
? t("TitleUploaded")
|
||||||
|
: t("TitleCreated");
|
||||||
|
|
||||||
|
const date = fileExst ? updated : created;
|
||||||
|
const dateLabel = new Date(date).toLocaleString(culture);
|
||||||
|
const mobile = (sectionWidth && sectionWidth <= 375) || isMobile;
|
||||||
|
|
||||||
|
return mobile ? dateLabel : `${title}: ${dateLabel}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
onShowVersionHistory = () => {
|
||||||
|
const {
|
||||||
|
homepage,
|
||||||
|
isTabletView,
|
||||||
|
item,
|
||||||
|
setIsVerHistoryPanel,
|
||||||
|
fetchFileVersions,
|
||||||
|
history,
|
||||||
|
isTrashFolder,
|
||||||
|
} = this.props;
|
||||||
|
if (isTrashFolder) return;
|
||||||
|
|
||||||
|
if (!isTabletView) {
|
||||||
|
fetchFileVersions(item.id + "");
|
||||||
|
setIsVerHistoryPanel(true);
|
||||||
|
} else {
|
||||||
|
history.push(
|
||||||
|
combineUrl(AppServerConfig.proxyURL, homepage, `/${item.id}/history`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onBadgeClick = () => {
|
||||||
|
const {
|
||||||
|
item,
|
||||||
|
selectedFolderPathParts,
|
||||||
|
markAsRead,
|
||||||
|
setNewFilesPanelVisible,
|
||||||
|
setNewFilesIds,
|
||||||
|
updateRootBadge,
|
||||||
|
updateFileBadge,
|
||||||
|
} = this.props;
|
||||||
|
if (item.fileExst) {
|
||||||
|
markAsRead([], [item.id])
|
||||||
|
.then(() => {
|
||||||
|
updateRootBadge(selectedFolderPathParts[0], 1);
|
||||||
|
updateFileBadge(item.id);
|
||||||
|
})
|
||||||
|
.catch((err) => toastr.error(err));
|
||||||
|
} else {
|
||||||
|
setNewFilesPanelVisible(true);
|
||||||
|
const newFolderIds = selectedFolderPathParts;
|
||||||
|
newFolderIds.push(item.id);
|
||||||
|
setNewFilesIds(newFolderIds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setConvertDialogVisible = () =>
|
||||||
|
this.setState({ showConvertDialog: !this.state.showConvertDialog });
|
||||||
|
|
||||||
|
onConvert = () => {
|
||||||
|
const { item, t, setSecondaryProgressBarData } = this.props;
|
||||||
|
setSecondaryProgressBarData({
|
||||||
|
icon: "file",
|
||||||
|
visible: true,
|
||||||
|
percent: 0,
|
||||||
|
label: t("Convert"),
|
||||||
|
alert: false,
|
||||||
|
});
|
||||||
|
this.setState({ showConvertDialog: false }, () =>
|
||||||
|
convertFile(item.id).then((convertRes) => {
|
||||||
|
if (convertRes && convertRes[0] && convertRes[0].progress !== 100) {
|
||||||
|
this.getConvertProgress(item.id);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
getConvertProgress = (fileId) => {
|
||||||
|
const {
|
||||||
|
selectedFolderId,
|
||||||
|
filter,
|
||||||
|
setIsLoading,
|
||||||
|
setSecondaryProgressBarData,
|
||||||
|
t,
|
||||||
|
clearSecondaryProgressData,
|
||||||
|
fetchFiles,
|
||||||
|
} = this.props;
|
||||||
|
getFileConversationProgress(fileId).then((res) => {
|
||||||
|
if (res && res[0] && res[0].progress !== 100) {
|
||||||
|
setSecondaryProgressBarData({
|
||||||
|
icon: "file",
|
||||||
|
visible: true,
|
||||||
|
percent: res[0].progress,
|
||||||
|
label: t("Convert"),
|
||||||
|
alert: false,
|
||||||
|
});
|
||||||
|
setTimeout(() => this.getConvertProgress(fileId), 1000);
|
||||||
|
} else {
|
||||||
|
if (res[0].error) {
|
||||||
|
setSecondaryProgressBarData({
|
||||||
|
visible: true,
|
||||||
|
alert: true,
|
||||||
|
});
|
||||||
|
toastr.error(res[0].error);
|
||||||
|
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
||||||
|
} else {
|
||||||
|
setSecondaryProgressBarData({
|
||||||
|
icon: "file",
|
||||||
|
visible: true,
|
||||||
|
percent: 100,
|
||||||
|
label: t("Convert"),
|
||||||
|
alert: false,
|
||||||
|
});
|
||||||
|
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
||||||
|
const newFilter = filter.clone();
|
||||||
|
fetchFiles(selectedFolderId, newFilter)
|
||||||
|
.catch((err) => {
|
||||||
|
setSecondaryProgressBarData({
|
||||||
|
visible: true,
|
||||||
|
alert: true,
|
||||||
|
});
|
||||||
|
//toastr.error(err);
|
||||||
|
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
||||||
|
})
|
||||||
|
.finally(() => setIsLoading(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onClickLock = () => {
|
||||||
|
const { item, lockFileAction } = this.props;
|
||||||
|
const { locked, id } = item;
|
||||||
|
|
||||||
|
lockFileAction(id, !locked).catch((err) => toastr.error(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
onClickFavorite = () => {
|
||||||
|
const { t, item, setFavoriteAction } = this.props;
|
||||||
|
|
||||||
|
setFavoriteAction("remove", item.id)
|
||||||
|
.then(() => toastr.success(t("RemovedFromFavorites")))
|
||||||
|
.catch((err) => toastr.error(err));
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { itemTitle, showConvertDialog } = this.state;
|
||||||
|
const {
|
||||||
|
item,
|
||||||
|
fileActionId,
|
||||||
|
fileActionExt,
|
||||||
|
isLoading,
|
||||||
|
viewer,
|
||||||
|
t,
|
||||||
|
isTrashFolder,
|
||||||
|
canWebEdit,
|
||||||
|
canConvert,
|
||||||
|
} = this.props;
|
||||||
|
const { id, fileExst, updated, createdBy, access, fileStatus } = item;
|
||||||
|
|
||||||
|
const titleWithoutExt = getTitleWithoutExst(item);
|
||||||
|
|
||||||
|
const isEdit = id === fileActionId && fileExst === fileActionExt;
|
||||||
|
|
||||||
|
const updatedDate = updated && this.getStatusByDate();
|
||||||
|
|
||||||
|
const fileOwner =
|
||||||
|
createdBy &&
|
||||||
|
((viewer.id === createdBy.id && t("AuthorMe")) ||
|
||||||
|
createdBy.displayName);
|
||||||
|
|
||||||
|
const accessToEdit =
|
||||||
|
access === ShareAccessRights.FullAccess ||
|
||||||
|
access === ShareAccessRights.None; // TODO: fix access type for owner (now - None)
|
||||||
|
|
||||||
|
const linkStyles = isTrashFolder //|| window.innerWidth <= 1024
|
||||||
|
? { noHover: true }
|
||||||
|
: { onClick: this.onFilesClick };
|
||||||
|
|
||||||
|
const newItems = item.new || fileStatus === 2;
|
||||||
|
const showNew = !!newItems;
|
||||||
|
|
||||||
|
return isEdit ? (
|
||||||
|
<EditingWrapperComponent
|
||||||
|
itemTitle={itemTitle}
|
||||||
|
okIcon={okIcon}
|
||||||
|
cancelIcon={cancelIcon}
|
||||||
|
itemId={id}
|
||||||
|
isLoading={isLoading}
|
||||||
|
renameTitle={this.renameTitle}
|
||||||
|
onClickUpdateItem={this.onClickUpdateItem}
|
||||||
|
cancelUpdateItem={this.cancelUpdateItem}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{showConvertDialog && (
|
||||||
|
<ConvertDialog
|
||||||
|
visible={showConvertDialog}
|
||||||
|
onClose={this.setConvertDialogVisible}
|
||||||
|
onConvert={this.onConvert}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<WrappedContent
|
||||||
|
titleWithoutExt={titleWithoutExt}
|
||||||
|
updatedDate={updatedDate}
|
||||||
|
fileOwner={fileOwner}
|
||||||
|
accessToEdit={accessToEdit}
|
||||||
|
linkStyles={linkStyles}
|
||||||
|
newItems={newItems}
|
||||||
|
showNew={showNew}
|
||||||
|
canWebEdit={canWebEdit}
|
||||||
|
canConvert={canConvert}
|
||||||
|
isTrashFolder={isTrashFolder}
|
||||||
|
onFilesClick={this.onFilesClick}
|
||||||
|
onShowVersionHistory={this.onShowVersionHistory}
|
||||||
|
onBadgeClick={this.onBadgeClick}
|
||||||
|
onClickLock={this.onClickLock}
|
||||||
|
onClickFavorite={this.onClickFavorite}
|
||||||
|
setConvertDialogVisible={this.setConvertDialogVisible}
|
||||||
|
{...this.props}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inject(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
filesActionsStore,
|
||||||
|
filesStore,
|
||||||
|
selectedFolderStore,
|
||||||
|
formatsStore,
|
||||||
|
treeFoldersStore,
|
||||||
|
mediaViewerDataStore,
|
||||||
|
auth,
|
||||||
|
versionHistoryStore,
|
||||||
|
dialogsStore,
|
||||||
|
uploadDataStore,
|
||||||
|
},
|
||||||
|
{ item, t, history }
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
editCompleteAction,
|
||||||
|
markAsRead,
|
||||||
|
lockFileAction,
|
||||||
|
setFavoriteAction,
|
||||||
|
} = filesActionsStore;
|
||||||
|
const {
|
||||||
|
filter,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
openDocEditor,
|
||||||
|
updateFile,
|
||||||
|
renameFolder,
|
||||||
|
createFile,
|
||||||
|
createFolder,
|
||||||
|
isLoading,
|
||||||
|
updateFileBadge,
|
||||||
|
} = filesStore;
|
||||||
|
const {
|
||||||
|
iconFormatsStore,
|
||||||
|
mediaViewersFormatsStore,
|
||||||
|
docserviceStore,
|
||||||
|
} = formatsStore;
|
||||||
|
const {
|
||||||
|
isRecycleBinFolder,
|
||||||
|
expandedKeys,
|
||||||
|
addExpandedKeys,
|
||||||
|
isPrivacyFolder,
|
||||||
|
updateRootBadge,
|
||||||
|
} = treeFoldersStore;
|
||||||
|
const { setMediaViewerData } = mediaViewerDataStore;
|
||||||
|
const {
|
||||||
|
type: fileActionType,
|
||||||
|
extension: fileActionExt,
|
||||||
|
id: fileActionId,
|
||||||
|
} = filesStore.fileActionStore;
|
||||||
|
const { replaceFileStream, setEncryptionAccess } = auth;
|
||||||
|
const { culture, isDesktopClient, isTabletView } = auth.settingsStore;
|
||||||
|
const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore;
|
||||||
|
const { setNewFilesPanelVisible, setNewFilesIds } = dialogsStore;
|
||||||
|
const { secondaryProgressDataStore } = uploadDataStore;
|
||||||
|
|
||||||
|
const {
|
||||||
|
setSecondaryProgressBarData,
|
||||||
|
clearSecondaryProgressData,
|
||||||
|
} = secondaryProgressDataStore;
|
||||||
|
const isImage = iconFormatsStore.isImage(item.fileExst);
|
||||||
|
const isSound = iconFormatsStore.isSound(item.fileExst);
|
||||||
|
const isVideo = mediaViewersFormatsStore.isVideo(item.fileExst);
|
||||||
|
const canWebEdit = docserviceStore.canWebEdit(item.fileExst);
|
||||||
|
return {
|
||||||
|
t,
|
||||||
|
editCompleteAction,
|
||||||
|
filter,
|
||||||
|
parentFolder: selectedFolderStore.parentId,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
isImage,
|
||||||
|
isSound,
|
||||||
|
isVideo,
|
||||||
|
canWebEdit,
|
||||||
|
isTrashFolder: isRecycleBinFolder,
|
||||||
|
openDocEditor,
|
||||||
|
expandedKeys,
|
||||||
|
addExpandedKeys,
|
||||||
|
setMediaViewerData,
|
||||||
|
updateFile,
|
||||||
|
renameFolder,
|
||||||
|
fileActionId,
|
||||||
|
editCompleteAction,
|
||||||
|
fileActionType,
|
||||||
|
createFile,
|
||||||
|
isPrivacy: isPrivacyFolder,
|
||||||
|
isDesktop: isDesktopClient,
|
||||||
|
replaceFileStream,
|
||||||
|
setEncryptionAccess,
|
||||||
|
createFolder,
|
||||||
|
fileActionExt,
|
||||||
|
isLoading,
|
||||||
|
culture,
|
||||||
|
homepage: config.homepage,
|
||||||
|
isTabletView,
|
||||||
|
setIsVerHistoryPanel,
|
||||||
|
fetchFileVersions,
|
||||||
|
history,
|
||||||
|
selectedFolderPathParts: selectedFolderStore.pathParts,
|
||||||
|
markAsRead,
|
||||||
|
setNewFilesPanelVisible,
|
||||||
|
setNewFilesIds,
|
||||||
|
updateRootBadge,
|
||||||
|
updateFileBadge,
|
||||||
|
setSecondaryProgressBarData,
|
||||||
|
clearSecondaryProgressData,
|
||||||
|
selectedFolderId: selectedFolderStore.id,
|
||||||
|
lockFileAction,
|
||||||
|
setFavoriteAction,
|
||||||
|
viewer: auth.userStore.user,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)(observer(WithContentActions));
|
||||||
|
}
|
@ -1,5 +1,14 @@
|
|||||||
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import commonIconsStyles from "@appserver/components/utils/common-icons-style";
|
||||||
|
|
||||||
|
import CheckIcon from "../../../../../../../public/images/check.react.svg";
|
||||||
|
import CrossIcon from "../../../../../../../../../../public/images/cross.react.svg";
|
||||||
|
import FavoriteIcon from "../../../../../../../public/images/favorite.react.svg";
|
||||||
|
import FileActionsConvertEditDocIcon from "../../../../../../../public/images/file.actions.convert.edit.doc.react.svg";
|
||||||
|
import FileActionsLockedIcon from "../../../../../../../public/images/file.actions.locked.react.svg";
|
||||||
|
|
||||||
export const EncryptedFileIcon = styled.div`
|
export const EncryptedFileIcon = styled.div`
|
||||||
background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent;
|
background: url("images/security.svg") no-repeat 0 0 / 16px 16px transparent;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@ -8,3 +17,47 @@ export const EncryptedFileIcon = styled.div`
|
|||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
margin-left: ${(props) => (props.isEdit ? "40px" : "12px")};
|
margin-left: ${(props) => (props.isEdit ? "40px" : "12px")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledCheckIcon = styled(CheckIcon)`
|
||||||
|
${commonIconsStyles}
|
||||||
|
path {
|
||||||
|
fill: #a3a9ae;
|
||||||
|
}
|
||||||
|
:hover {
|
||||||
|
fill: #657077;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const okIcon = <StyledCheckIcon className="edit-ok-icon" size="scale" />;
|
||||||
|
|
||||||
|
const StyledCrossIcon = styled(CrossIcon)`
|
||||||
|
${commonIconsStyles}
|
||||||
|
path {
|
||||||
|
fill: #a3a9ae;
|
||||||
|
}
|
||||||
|
:hover {
|
||||||
|
fill: #657077;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const cancelIcon = (
|
||||||
|
<StyledCrossIcon className="edit-cancel-icon" size="scale" />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const StyledFavoriteIcon = styled(FavoriteIcon)`
|
||||||
|
${commonIconsStyles}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const StyledFileActionsConvertEditDocIcon = styled(
|
||||||
|
FileActionsConvertEditDocIcon
|
||||||
|
)`
|
||||||
|
${commonIconsStyles}
|
||||||
|
path {
|
||||||
|
fill: #3b72a7;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const StyledFileActionsLockedIcon = styled(FileActionsLockedIcon)`
|
||||||
|
${commonIconsStyles}
|
||||||
|
path {
|
||||||
|
fill: #3b72a7;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
Loading…
Reference in New Issue
Block a user