Merge pull request #685 from ONLYOFFICE/feature/group-context-menu
Feature/group context menu
This commit is contained in:
commit
9ba8378cae
@ -16,7 +16,6 @@ import { StyledFilterInput, StyledSearchInput } from "./StyledFilterInput";
|
||||
const FilterInput = React.memo(
|
||||
({
|
||||
t,
|
||||
sectionWidth,
|
||||
getFilterData,
|
||||
getSortData,
|
||||
getViewSettingsData,
|
||||
|
@ -70,7 +70,7 @@ class Row extends React.Component {
|
||||
};
|
||||
|
||||
const onContextMenu = (e) => {
|
||||
rowContextClick && rowContextClick();
|
||||
rowContextClick && rowContextClick(e.button === 2);
|
||||
if (!this.cm.current.menuRef.current) {
|
||||
this.row.current.click(e); //TODO: need fix context menu to global
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ const TableRow = (props) => {
|
||||
const row = useRef();
|
||||
|
||||
const onContextMenu = (e) => {
|
||||
fileContextClick && fileContextClick();
|
||||
fileContextClick && fileContextClick(e.button === 2);
|
||||
if (cm.current && !cm.current.menuRef.current) {
|
||||
row.current.click(e);
|
||||
}
|
||||
|
@ -21,11 +21,12 @@ export default function withFileActions(WrappedFileItem) {
|
||||
id !== -1 && onSelectItem({ id, isFolder });
|
||||
};
|
||||
|
||||
onFileContextClick = () => {
|
||||
onFileContextClick = (isSingleFile) => {
|
||||
const { onSelectItem } = this.props;
|
||||
const { id, isFolder } = this.props.item;
|
||||
|
||||
id !== -1 && onSelectItem({ id, isFolder }, true);
|
||||
id !== -1 &&
|
||||
onSelectItem({ id, isFolder }, false, !isSingleFile || isMobile);
|
||||
};
|
||||
|
||||
onHideContextMenu = () => {
|
||||
|
@ -7,14 +7,6 @@ import CustomScrollbarsVirtualList from "@appserver/components/scrollbar";
|
||||
import { StyledGridWrapper, StyledTileContainer } from "../StyledTileView";
|
||||
|
||||
class TileContainer extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
contextOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
renderTile = memo(({ data, index, style }) => {
|
||||
return <div style={style}>{data[index]}</div>;
|
||||
}, areEqual);
|
||||
|
@ -427,7 +427,7 @@ class Tile extends React.PureComponent {
|
||||
};
|
||||
|
||||
const onContextMenu = (e) => {
|
||||
tileContextClick && tileContextClick();
|
||||
tileContextClick && tileContextClick(e.button === 2);
|
||||
if (!this.cm.current.menuRef.current) {
|
||||
this.tile.current.click(e); //TODO: need fix context menu to global
|
||||
}
|
||||
|
@ -630,7 +630,157 @@ class ContextOptionsStore {
|
||||
return options;
|
||||
};
|
||||
|
||||
getGroupContextOptions = (t) => {
|
||||
const { selection } = this.filesStore;
|
||||
const { setDeleteDialogVisible } = this.dialogsStore;
|
||||
const { isRecycleBinFolder } = this.treeFoldersStore;
|
||||
|
||||
const downloadAs =
|
||||
selection.findIndex((k) => k.contextOptions.includes("download-as")) !==
|
||||
-1;
|
||||
|
||||
const sharingItems = selection.filter(
|
||||
(k) => k.contextOptions.includes("sharing-settings") && k.canShare
|
||||
).length;
|
||||
|
||||
const favoriteItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("mark-as-favorite")
|
||||
);
|
||||
|
||||
const moveItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("move-to")
|
||||
).length;
|
||||
|
||||
const copyItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("copy-to")
|
||||
).length;
|
||||
|
||||
const restoreItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("restore")
|
||||
).length;
|
||||
|
||||
const removeFromFavoriteItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("remove-from-favorites")
|
||||
);
|
||||
|
||||
const deleteItems = selection.filter((k) =>
|
||||
k.contextOptions.includes("delete")
|
||||
).length;
|
||||
|
||||
const isRootThirdPartyFolder = selection.some(
|
||||
(x) => x.providerKey && x.id === x.rootFolderId
|
||||
);
|
||||
|
||||
const favoriteItemsIds = favoriteItems.map((item) => item.id);
|
||||
|
||||
const removeFromFavoriteItemsIds = removeFromFavoriteItems.map(
|
||||
(item) => item.id
|
||||
);
|
||||
|
||||
const options = [
|
||||
{
|
||||
key: "sharing-settings",
|
||||
label: t("SharingSettings"),
|
||||
icon: "/static/images/share.react.svg",
|
||||
onClick: this.onClickShare,
|
||||
disabled: !sharingItems,
|
||||
},
|
||||
{
|
||||
key: "separator0",
|
||||
isSeparator: true,
|
||||
disabled: !sharingItems,
|
||||
},
|
||||
{
|
||||
key: "mark-as-favorite",
|
||||
label: t("MarkAsFavorite"),
|
||||
icon: "images/favorites.react.svg",
|
||||
onClick: (e) => this.onClickFavorite(e, favoriteItemsIds, t),
|
||||
disabled: !favoriteItems.length,
|
||||
"data-action": "mark",
|
||||
action: "mark",
|
||||
},
|
||||
{
|
||||
key: "remove-from-favorites",
|
||||
label: t("RemoveFromFavorites"),
|
||||
icon: "images/favorites.react.svg",
|
||||
onClick: (e) => this.onClickFavorite(e, removeFromFavoriteItemsIds, t),
|
||||
disabled: favoriteItems.length || !removeFromFavoriteItems.length,
|
||||
"data-action": "remove",
|
||||
action: "remove",
|
||||
},
|
||||
{
|
||||
key: "download",
|
||||
label: t("Common:Download"),
|
||||
icon: "images/download.react.svg",
|
||||
onClick: () =>
|
||||
this.filesActionsStore
|
||||
.downloadAction(t("Translations:ArchivingData"))
|
||||
.catch((err) => toastr.error(err)),
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
key: "download-as",
|
||||
label: t("Translations:DownloadAs"),
|
||||
icon: "images/download-as.react.svg",
|
||||
onClick: this.onClickDownloadAs,
|
||||
disabled: !downloadAs,
|
||||
},
|
||||
{
|
||||
key: "move-to",
|
||||
label: t("MoveTo"),
|
||||
icon: "images/move.react.svg",
|
||||
onClick: this.onMoveAction,
|
||||
disabled: isRecycleBinFolder || !moveItems,
|
||||
},
|
||||
{
|
||||
key: "copy-to",
|
||||
label: t("Translations:Copy"),
|
||||
icon: "/static/images/copy.react.svg",
|
||||
onClick: this.onCopyAction,
|
||||
disabled: isRecycleBinFolder || !copyItems,
|
||||
},
|
||||
{
|
||||
key: "restore",
|
||||
label: t("Common:Restore"),
|
||||
icon: "images/move.react.svg",
|
||||
onClick: this.onMoveAction,
|
||||
disabled: !isRecycleBinFolder || !restoreItems,
|
||||
},
|
||||
{
|
||||
key: "separator1",
|
||||
isSeparator: true,
|
||||
disabled: !deleteItems || isRootThirdPartyFolder,
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
label: t("Common:Delete"),
|
||||
icon: "images/trash.react.svg",
|
||||
onClick: () => {
|
||||
if (this.settingsStore.confirmDelete) {
|
||||
setDeleteDialogVisible(true);
|
||||
} else {
|
||||
const translations = {
|
||||
deleteOperation: t("Translations:DeleteOperation"),
|
||||
deleteFromTrash: t("Translations:DeleteFromTrash"),
|
||||
deleteSelectedElem: t("Translations:DeleteSelectedElem"),
|
||||
FileRemoved: t("Home:FileRemoved"),
|
||||
FolderRemoved: t("Home:FolderRemoved"),
|
||||
};
|
||||
|
||||
this.filesActionsStore
|
||||
.deleteAction(translations)
|
||||
.catch((err) => toastr.error(err));
|
||||
}
|
||||
},
|
||||
disabled: !deleteItems || isRootThirdPartyFolder,
|
||||
},
|
||||
];
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
getModel = (item, t) => {
|
||||
const { selection } = this.filesStore;
|
||||
const { type, id, extension } = this.filesStore.fileActionStore;
|
||||
const { fileExst, contextOptions } = item;
|
||||
|
||||
@ -638,7 +788,9 @@ class ContextOptionsStore {
|
||||
|
||||
const contextOptionsProps =
|
||||
!isEdit && contextOptions && contextOptions.length > 0
|
||||
? this.getFilesContextOptions(item, t)
|
||||
? selection.length > 1
|
||||
? this.getGroupContextOptions(t)
|
||||
: this.getFilesContextOptions(item, t)
|
||||
: [];
|
||||
|
||||
return contextOptionsProps;
|
||||
|
@ -185,7 +185,6 @@ class FilesActionStore {
|
||||
const { addActiveItems } = this.filesStore;
|
||||
const {
|
||||
secondaryProgressDataStore,
|
||||
loopFilesOperations,
|
||||
clearActiveOperations,
|
||||
} = this.uploadDataStore;
|
||||
const {
|
||||
@ -472,18 +471,18 @@ class FilesActionStore {
|
||||
}
|
||||
};
|
||||
|
||||
onSelectItem = ({ id, isFolder }, isBuffer = false) => {
|
||||
onSelectItem = ({ id, isFolder }, isBuffer = false, isSingleFile) => {
|
||||
const {
|
||||
setBufferSelection,
|
||||
selected,
|
||||
setSelected,
|
||||
selection,
|
||||
setSelection,
|
||||
setHotkeyCaretStart,
|
||||
setHotkeyCaret,
|
||||
setEnabledHotkeys,
|
||||
filesList,
|
||||
} = this.filesStore;
|
||||
/* selected === "close" && */ setSelected("none");
|
||||
|
||||
if (!id) return;
|
||||
|
||||
@ -495,8 +494,16 @@ class FilesActionStore {
|
||||
if (isBuffer) {
|
||||
setBufferSelection(item);
|
||||
setEnabledHotkeys(false);
|
||||
setSelected("none");
|
||||
} else {
|
||||
setSelection([item]);
|
||||
const isSelected = selection.findIndex(
|
||||
(f) => f.id === id && f.isFolder === isFolder
|
||||
);
|
||||
|
||||
if (isSelected === -1 || isSingleFile) {
|
||||
setSelected("none");
|
||||
setSelection([item]);
|
||||
}
|
||||
setHotkeyCaret(null);
|
||||
setHotkeyCaretStart(null);
|
||||
}
|
||||
@ -636,28 +643,40 @@ class FilesActionStore {
|
||||
);
|
||||
};
|
||||
|
||||
getFilesInfo = (items) => {
|
||||
const requests = [];
|
||||
let i = items.length;
|
||||
while (i !== 0) {
|
||||
requests.push(this.filesStore.getFileInfo(items[i - 1]));
|
||||
i--;
|
||||
}
|
||||
return Promise.all(requests);
|
||||
};
|
||||
|
||||
setFavoriteAction = (action, id) => {
|
||||
const {
|
||||
markItemAsFavorite,
|
||||
removeItemFromFavorite,
|
||||
fetchFavoritesFolder,
|
||||
getFileInfo,
|
||||
setSelected,
|
||||
} = this.filesStore;
|
||||
|
||||
const items = Array.isArray(id) ? id : [id];
|
||||
|
||||
//let data = selection.map(item => item.id)
|
||||
switch (action) {
|
||||
case "mark":
|
||||
return markItemAsFavorite([id]).then(() => getFileInfo(id));
|
||||
return markItemAsFavorite(items)
|
||||
.then(() => {
|
||||
return this.getFilesInfo(items);
|
||||
})
|
||||
.then(() => setSelected("close"));
|
||||
|
||||
case "remove":
|
||||
return removeItemFromFavorite(items)
|
||||
.then(() => {
|
||||
return this.treeFoldersStore.isFavoritesFolder
|
||||
? fetchFavoritesFolder(this.selectedFolderStore.id)
|
||||
: getFileInfo(id);
|
||||
: this.getFilesInfo(items);
|
||||
})
|
||||
.then(() => setSelected("close"));
|
||||
default:
|
||||
|
@ -480,7 +480,7 @@ class FilesStore {
|
||||
}
|
||||
|
||||
this.selected = selected;
|
||||
const files = this.files.concat(this.folders);
|
||||
const files = this.filesList;
|
||||
this.selection = this.getFilesBySelected(files, selected);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user