added checkbox menu interaction and new opening mechanics
This commit is contained in:
parent
fd46496544
commit
e77a97e105
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"kafka": {
|
"kafka": {
|
||||||
"BootstrapServers": "localhost:9092"
|
"BootstrapServers": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import IconButton from "@appserver/components/icon-button";
|
import IconButton from "@appserver/components/icon-button";
|
||||||
import { isTablet, mobile, tablet } from "@appserver/components/utils/device";
|
import { isTablet, mobile, tablet } from "@appserver/components/utils/device";
|
||||||
|
import { set } from "mobx";
|
||||||
import { inject } from "mobx-react";
|
import { inject } from "mobx-react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
@ -65,7 +66,10 @@ const StyledCloseButtonWrapper = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const InfoPanel = ({ children, isVisible, setIsVisible }) => {
|
const InfoPanel = ({ children, selectedItems, isVisible, setIsVisible }) => {
|
||||||
|
//if (selectedItems.length > 0) setIsVisible(true);
|
||||||
|
//else setIsVisible(false);
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null;
|
||||||
|
|
||||||
const closeInfoPanel = () => setIsVisible(false);
|
const closeInfoPanel = () => setIsVisible(false);
|
||||||
@ -108,7 +112,8 @@ InfoPanel.propTypes = {
|
|||||||
isVisible: PropTypes.bool,
|
isVisible: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default inject(({ infoPanelStore }) => {
|
export default inject(({ infoPanelStore, filesStore }) => {
|
||||||
|
let selectedItems = [];
|
||||||
let isVisible = false;
|
let isVisible = false;
|
||||||
let setIsVisible = () => {};
|
let setIsVisible = () => {};
|
||||||
|
|
||||||
@ -117,7 +122,12 @@ export default inject(({ infoPanelStore }) => {
|
|||||||
setIsVisible = infoPanelStore.setIsVisible;
|
setIsVisible = infoPanelStore.setIsVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filesStore) {
|
||||||
|
selectedItems = JSON.parse(JSON.stringify(filesStore.selection));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
selectedItems,
|
||||||
isVisible,
|
isVisible,
|
||||||
setIsVisible,
|
setIsVisible,
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,6 @@ const TableGroupMenu = (props) => {
|
|||||||
isChecked,
|
isChecked,
|
||||||
isIndeterminate,
|
isIndeterminate,
|
||||||
headerMenu,
|
headerMenu,
|
||||||
infoPanelToggle,
|
|
||||||
onChange,
|
onChange,
|
||||||
checkboxOptions,
|
checkboxOptions,
|
||||||
checkboxMargin,
|
checkboxMargin,
|
||||||
@ -55,7 +54,6 @@ const TableGroupMenu = (props) => {
|
|||||||
{headerMenu.map((item, index) => (
|
{headerMenu.map((item, index) => (
|
||||||
<GroupMenuItem key={index} item={item} />
|
<GroupMenuItem key={index} item={item} />
|
||||||
))}
|
))}
|
||||||
{infoPanelToggle}
|
|
||||||
</StyledScrollbar>
|
</StyledScrollbar>
|
||||||
</StyledTableGroupMenu>
|
</StyledTableGroupMenu>
|
||||||
</>
|
</>
|
||||||
|
@ -317,7 +317,7 @@ export default function withContextOptions(WrappedComponent) {
|
|||||||
case "show-info":
|
case "show-info":
|
||||||
return {
|
return {
|
||||||
key: option,
|
key: option,
|
||||||
label: t("Show info"),
|
label: t("InfoPanel:Info"),
|
||||||
icon: "images/info.react.svg",
|
icon: "images/info.react.svg",
|
||||||
onClick: this.onSetInfoPanelVisible,
|
onClick: this.onSetInfoPanelVisible,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
@ -1,421 +1,457 @@
|
|||||||
import React from "react";
|
|
||||||
import { inject, observer } from "mobx-react";
|
|
||||||
import toastr from "@appserver/components/toast/toastr";
|
|
||||||
import { checkProtocol } from "../helpers/files-helpers";
|
|
||||||
import { AppServerConfig } from "@appserver/common/constants";
|
import { AppServerConfig } from "@appserver/common/constants";
|
||||||
import { combineUrl } from "@appserver/common/utils";
|
import { combineUrl } from "@appserver/common/utils";
|
||||||
import config from "../../package.json";
|
import toastr from "@appserver/components/toast/toastr";
|
||||||
|
import { inject, observer } from "mobx-react";
|
||||||
|
import React from "react";
|
||||||
import { isMobile } from "react-device-detect";
|
import { isMobile } from "react-device-detect";
|
||||||
|
|
||||||
|
import config from "../../package.json";
|
||||||
|
import { checkProtocol } from "../helpers/files-helpers";
|
||||||
|
|
||||||
export default function withFileActions(WrappedFileItem) {
|
export default function withFileActions(WrappedFileItem) {
|
||||||
class WithFileActions extends React.Component {
|
class WithFileActions extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
onContentFileSelect = (checked, file) => {
|
onContentFileSelect = (checked, file) => {
|
||||||
const { selectRowAction } = this.props;
|
const {
|
||||||
if (!file || file.id === -1) return;
|
selectRowAction,
|
||||||
selectRowAction(checked, file);
|
infoPanelIsVisible,
|
||||||
};
|
showInfoPanel,
|
||||||
|
} = this.props;
|
||||||
|
if (!file || file.id === -1) return;
|
||||||
|
selectRowAction(checked, file);
|
||||||
|
if (!infoPanelIsVisible) showInfoPanel();
|
||||||
|
};
|
||||||
|
|
||||||
fileContextClick = () => {
|
fileContextClick = () => {
|
||||||
const { onSelectItem, item } = this.props;
|
if (!this.props.infoPanelIsVisible) this.props.showInfoPanel();
|
||||||
const { id, isFolder } = item;
|
|
||||||
|
|
||||||
id !== -1 && onSelectItem({ id, isFolder });
|
const { onSelectItem, item } = this.props;
|
||||||
};
|
const { id, isFolder } = item;
|
||||||
|
|
||||||
onHideContextMenu = () => {
|
id !== -1 && onSelectItem({ id, isFolder });
|
||||||
//this.props.setBufferSelection(null);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
onDropZoneUpload = (files, uploadToFolder) => {
|
onHideContextMenu = () => {
|
||||||
const { t, dragging, setDragging, startUpload } = this.props;
|
//this.props.setBufferSelection(null);
|
||||||
|
};
|
||||||
|
|
||||||
dragging && setDragging(false);
|
onDropZoneUpload = (files, uploadToFolder) => {
|
||||||
startUpload(files, uploadToFolder, t);
|
const { t, dragging, setDragging, startUpload } = this.props;
|
||||||
};
|
|
||||||
|
|
||||||
onDrop = (items) => {
|
dragging && setDragging(false);
|
||||||
const { fileExst, id } = this.props.item;
|
startUpload(files, uploadToFolder, t);
|
||||||
|
};
|
||||||
|
|
||||||
if (!fileExst) {
|
onDrop = (items) => {
|
||||||
this.onDropZoneUpload(items, id);
|
const { fileExst, id } = this.props.item;
|
||||||
} else {
|
|
||||||
this.onDropZoneUpload(items);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMouseDown = (e) => {
|
if (!fileExst) {
|
||||||
const {
|
this.onDropZoneUpload(items, id);
|
||||||
draggable,
|
} else {
|
||||||
setTooltipPosition,
|
this.onDropZoneUpload(items);
|
||||||
setStartDrag,
|
}
|
||||||
isPrivacy,
|
};
|
||||||
isTrashFolder,
|
|
||||||
onSelectItem,
|
|
||||||
item,
|
|
||||||
setBufferSelection,
|
|
||||||
isActive,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { id, isFolder, isThirdPartyFolder } = item;
|
onMouseDown = (e) => {
|
||||||
|
const {
|
||||||
|
draggable,
|
||||||
|
setTooltipPosition,
|
||||||
|
setStartDrag,
|
||||||
|
isPrivacy,
|
||||||
|
isTrashFolder,
|
||||||
|
onSelectItem,
|
||||||
|
item,
|
||||||
|
setBufferSelection,
|
||||||
|
isActive,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const notSelectable = e.target.classList.contains("not-selectable");
|
const { id, isFolder, isThirdPartyFolder } = item;
|
||||||
const isFileName = e.target.classList.contains("item-file-name");
|
|
||||||
|
|
||||||
if (
|
const notSelectable = e.target.classList.contains("not-selectable");
|
||||||
isPrivacy ||
|
const isFileName = e.target.classList.contains("item-file-name");
|
||||||
isTrashFolder ||
|
|
||||||
(!draggable && !isFileName && !isActive)
|
|
||||||
)
|
|
||||||
return e;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
window.innerWidth < 1025 ||
|
isPrivacy ||
|
||||||
notSelectable ||
|
isTrashFolder ||
|
||||||
isMobile ||
|
(!draggable && !isFileName && !isActive)
|
||||||
isThirdPartyFolder
|
)
|
||||||
) {
|
return e;
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (!draggable) {
|
if (
|
||||||
// id !== -1 && onSelectItem({ id, isFolder });
|
window.innerWidth < 1025 ||
|
||||||
// }
|
notSelectable ||
|
||||||
|
isMobile ||
|
||||||
|
isThirdPartyFolder
|
||||||
|
) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
const mouseButton = e.which
|
// if (!draggable) {
|
||||||
? e.which !== 1
|
// id !== -1 && onSelectItem({ id, isFolder });
|
||||||
: e.button
|
// }
|
||||||
? e.button !== 0
|
|
||||||
: false;
|
|
||||||
const label = e.currentTarget.getAttribute("label");
|
|
||||||
if (mouseButton || e.currentTarget.tagName !== "DIV" || label) {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
setTooltipPosition(e.pageX, e.pageY);
|
|
||||||
!isFileName && setStartDrag(true);
|
|
||||||
!isActive && setBufferSelection(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMarkAsRead = (id) =>
|
const mouseButton = e.which
|
||||||
this.props.markAsRead([], [`${id}`], this.props.item);
|
? e.which !== 1
|
||||||
|
: e.button
|
||||||
|
? e.button !== 0
|
||||||
|
: false;
|
||||||
|
const label = e.currentTarget.getAttribute("label");
|
||||||
|
if (mouseButton || e.currentTarget.tagName !== "DIV" || label) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
onMouseClick = (e) => {
|
e.preventDefault();
|
||||||
const { viewAs, isItemsSelected } = this.props;
|
setTooltipPosition(e.pageX, e.pageY);
|
||||||
|
!isFileName && setStartDrag(true);
|
||||||
|
!isActive && setBufferSelection(null);
|
||||||
|
};
|
||||||
|
|
||||||
if (
|
onMarkAsRead = (id) =>
|
||||||
e.target.closest(".checkbox") ||
|
this.props.markAsRead([], [`${id}`], this.props.item);
|
||||||
e.target.tagName === "INPUT" ||
|
|
||||||
e.target.tagName === "SPAN" ||
|
onMouseClick = (e) => {
|
||||||
e.target.tagName === "A" ||
|
const {
|
||||||
e.target.closest(".expandButton") ||
|
viewAs,
|
||||||
e.target.closest(".badges") ||
|
isItemsSelected,
|
||||||
e.button !== 0 /* ||
|
infoPanelIsVisible,
|
||||||
|
showInfoPanel,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (
|
||||||
|
e.target.closest(".checkbox") ||
|
||||||
|
e.target.tagName === "INPUT" ||
|
||||||
|
e.target.tagName === "SPAN" ||
|
||||||
|
e.target.tagName === "A" ||
|
||||||
|
e.target.closest(".expandButton") ||
|
||||||
|
e.target.closest(".badges") ||
|
||||||
|
e.button !== 0 /* ||
|
||||||
isItemsSelected */
|
isItemsSelected */
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (viewAs === "tile") {
|
if (viewAs === "tile") {
|
||||||
if (e.target.closest(".edit-button") || e.target.tagName === "IMG")
|
if (
|
||||||
return;
|
e.target.closest(".edit-button") ||
|
||||||
|
e.target.tagName === "IMG"
|
||||||
if (e.detail === 1) this.fileContextClick();
|
|
||||||
} else {
|
|
||||||
this.fileContextClick();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onFilesClick = (e) => {
|
|
||||||
const {
|
|
||||||
isDesktop,
|
|
||||||
//parentFolder,
|
|
||||||
setIsLoading,
|
|
||||||
fetchFiles,
|
|
||||||
isMediaOrImage,
|
|
||||||
canConvert,
|
|
||||||
canWebEdit,
|
|
||||||
canViewedDocs,
|
|
||||||
item,
|
|
||||||
isTrashFolder,
|
|
||||||
isPrivacy,
|
|
||||||
openDocEditor,
|
|
||||||
//addExpandedKeys,
|
|
||||||
setExpandedKeys,
|
|
||||||
createNewExpandedKeys,
|
|
||||||
setMediaViewerData,
|
|
||||||
setConvertItem,
|
|
||||||
setConvertDialogVisible,
|
|
||||||
setNewBadgeCount,
|
|
||||||
} = this.props;
|
|
||||||
const {
|
|
||||||
id,
|
|
||||||
viewUrl,
|
|
||||||
providerKey,
|
|
||||||
fileStatus,
|
|
||||||
encrypted,
|
|
||||||
isFolder,
|
|
||||||
} = item;
|
|
||||||
if (encrypted && isPrivacy) return checkProtocol(item.id, true);
|
|
||||||
|
|
||||||
if (isTrashFolder) return;
|
|
||||||
if ((e && e.target.tagName === "INPUT") || e.target.closest(".badges"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (isFolder) {
|
|
||||||
setIsLoading(true);
|
|
||||||
//addExpandedKeys(parentFolder + "");
|
|
||||||
|
|
||||||
fetchFiles(id, null, true, false)
|
|
||||||
.then((data) => {
|
|
||||||
const pathParts = data.selectedFolder.pathParts;
|
|
||||||
const newExpandedKeys = createNewExpandedKeys(pathParts);
|
|
||||||
setExpandedKeys(newExpandedKeys);
|
|
||||||
|
|
||||||
setNewBadgeCount(item);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
toastr.error(err);
|
|
||||||
setIsLoading(false);
|
|
||||||
})
|
|
||||||
.finally(() => setIsLoading(false));
|
|
||||||
} else {
|
|
||||||
if (canConvert) {
|
|
||||||
setConvertItem(item);
|
|
||||||
setConvertDialogVisible(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileStatus === 2) this.onMarkAsRead(id);
|
|
||||||
|
|
||||||
if (canWebEdit || canViewedDocs) {
|
|
||||||
let tab =
|
|
||||||
!isDesktop && !isFolder
|
|
||||||
? window.open(
|
|
||||||
combineUrl(
|
|
||||||
AppServerConfig.proxyURL,
|
|
||||||
config.homepage,
|
|
||||||
"/doceditor"
|
|
||||||
),
|
|
||||||
"_blank"
|
|
||||||
)
|
)
|
||||||
: null;
|
return;
|
||||||
|
|
||||||
return openDocEditor(id, providerKey, tab);
|
if (e.detail === 1) this.fileContextClick();
|
||||||
|
} else {
|
||||||
|
this.fileContextClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!infoPanelIsVisible) showInfoPanel();
|
||||||
|
};
|
||||||
|
onFilesClick = (e) => {
|
||||||
|
const {
|
||||||
|
isDesktop,
|
||||||
|
//parentFolder,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
isMediaOrImage,
|
||||||
|
canConvert,
|
||||||
|
canWebEdit,
|
||||||
|
canViewedDocs,
|
||||||
|
item,
|
||||||
|
isTrashFolder,
|
||||||
|
isPrivacy,
|
||||||
|
openDocEditor,
|
||||||
|
//addExpandedKeys,
|
||||||
|
setExpandedKeys,
|
||||||
|
createNewExpandedKeys,
|
||||||
|
setMediaViewerData,
|
||||||
|
setConvertItem,
|
||||||
|
setConvertDialogVisible,
|
||||||
|
setNewBadgeCount,
|
||||||
|
} = this.props;
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
viewUrl,
|
||||||
|
providerKey,
|
||||||
|
fileStatus,
|
||||||
|
encrypted,
|
||||||
|
isFolder,
|
||||||
|
} = item;
|
||||||
|
if (encrypted && isPrivacy) return checkProtocol(item.id, true);
|
||||||
|
|
||||||
|
if (isTrashFolder) return;
|
||||||
|
if (
|
||||||
|
(e && e.target.tagName === "INPUT") ||
|
||||||
|
e.target.closest(".badges")
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (isFolder) {
|
||||||
|
setIsLoading(true);
|
||||||
|
//addExpandedKeys(parentFolder + "");
|
||||||
|
|
||||||
|
fetchFiles(id, null, true, false)
|
||||||
|
.then((data) => {
|
||||||
|
const pathParts = data.selectedFolder.pathParts;
|
||||||
|
const newExpandedKeys = createNewExpandedKeys(
|
||||||
|
pathParts
|
||||||
|
);
|
||||||
|
setExpandedKeys(newExpandedKeys);
|
||||||
|
|
||||||
|
setNewBadgeCount(item);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
toastr.error(err);
|
||||||
|
setIsLoading(false);
|
||||||
|
})
|
||||||
|
.finally(() => setIsLoading(false));
|
||||||
|
} else {
|
||||||
|
if (canConvert) {
|
||||||
|
setConvertItem(item);
|
||||||
|
setConvertDialogVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileStatus === 2) this.onMarkAsRead(id);
|
||||||
|
|
||||||
|
if (canWebEdit || canViewedDocs) {
|
||||||
|
let tab =
|
||||||
|
!isDesktop && !isFolder
|
||||||
|
? window.open(
|
||||||
|
combineUrl(
|
||||||
|
AppServerConfig.proxyURL,
|
||||||
|
config.homepage,
|
||||||
|
"/doceditor"
|
||||||
|
),
|
||||||
|
"_blank"
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return openDocEditor(id, providerKey, tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMediaOrImage) {
|
||||||
|
setMediaViewerData({ visible: true, id });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.open(viewUrl, "_self");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
item,
|
||||||
|
isTrashFolder,
|
||||||
|
draggable,
|
||||||
|
allowShareIn,
|
||||||
|
isPrivacy,
|
||||||
|
actionType,
|
||||||
|
actionExtension,
|
||||||
|
actionId,
|
||||||
|
sectionWidth,
|
||||||
|
checked,
|
||||||
|
dragging,
|
||||||
|
isFolder,
|
||||||
|
isDesktop,
|
||||||
|
personal,
|
||||||
|
canWebEdit,
|
||||||
|
canViewedDocs,
|
||||||
|
} = this.props;
|
||||||
|
const { fileExst, access, id } = item;
|
||||||
|
|
||||||
|
const isEdit =
|
||||||
|
actionType !== null &&
|
||||||
|
actionId === id &&
|
||||||
|
fileExst === actionExtension;
|
||||||
|
|
||||||
|
const isDragging =
|
||||||
|
isFolder && access < 2 && !isTrashFolder && !isPrivacy;
|
||||||
|
|
||||||
|
let className = isDragging ? " droppable" : "";
|
||||||
|
if (draggable) className += " draggable";
|
||||||
|
|
||||||
|
let value = !item.isFolder ? `file_${id}` : `folder_${id}`;
|
||||||
|
value += draggable ? "_draggable" : "";
|
||||||
|
|
||||||
|
const isShareable = allowShareIn && item.canShare;
|
||||||
|
|
||||||
|
const isMobileView = sectionWidth < 500;
|
||||||
|
|
||||||
|
const displayShareButton = isMobileView
|
||||||
|
? "26px"
|
||||||
|
: !isShareable
|
||||||
|
? "38px"
|
||||||
|
: "96px";
|
||||||
|
|
||||||
|
const showShare =
|
||||||
|
!isShareable ||
|
||||||
|
isEdit ||
|
||||||
|
(isPrivacy && (!isDesktop || !fileExst)) ||
|
||||||
|
(personal && !canWebEdit && !canViewedDocs)
|
||||||
|
? false
|
||||||
|
: true;
|
||||||
|
|
||||||
|
const checkedProps = isEdit || id <= 0 ? false : checked;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WrappedFileItem
|
||||||
|
onContentFileSelect={this.onContentFileSelect}
|
||||||
|
fileContextClick={this.fileContextClick}
|
||||||
|
onDrop={this.onDrop}
|
||||||
|
onMouseDown={this.onMouseDown}
|
||||||
|
onFilesClick={this.onFilesClick}
|
||||||
|
onMouseClick={this.onMouseClick}
|
||||||
|
onHideContextMenu={this.onHideContextMenu}
|
||||||
|
getClassName={this.getClassName}
|
||||||
|
className={className}
|
||||||
|
isDragging={isDragging}
|
||||||
|
value={value}
|
||||||
|
displayShareButton={displayShareButton}
|
||||||
|
isPrivacy={isPrivacy}
|
||||||
|
showShare={showShare}
|
||||||
|
checkedProps={checkedProps}
|
||||||
|
dragging={dragging}
|
||||||
|
isEdit={isEdit}
|
||||||
|
{...this.props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isMediaOrImage) {
|
return inject(
|
||||||
setMediaViewerData({ visible: true, id });
|
(
|
||||||
return;
|
{
|
||||||
|
auth,
|
||||||
|
filesActionsStore,
|
||||||
|
dialogsStore,
|
||||||
|
treeFoldersStore,
|
||||||
|
//selectedFolderStore,
|
||||||
|
filesStore,
|
||||||
|
uploadDataStore,
|
||||||
|
formatsStore,
|
||||||
|
mediaViewerDataStore,
|
||||||
|
infoPanelStore,
|
||||||
|
},
|
||||||
|
{ item, t, history }
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
selectRowAction,
|
||||||
|
onSelectItem,
|
||||||
|
markAsRead,
|
||||||
|
setNewBadgeCount,
|
||||||
|
} = filesActionsStore;
|
||||||
|
const {
|
||||||
|
setSharingPanelVisible,
|
||||||
|
setConvertDialogVisible,
|
||||||
|
setConvertItem,
|
||||||
|
} = dialogsStore;
|
||||||
|
const {
|
||||||
|
isPrivacyFolder,
|
||||||
|
isRecycleBinFolder,
|
||||||
|
//addExpandedKeys,
|
||||||
|
setExpandedKeys,
|
||||||
|
createNewExpandedKeys,
|
||||||
|
} = treeFoldersStore;
|
||||||
|
const {
|
||||||
|
dragging,
|
||||||
|
setDragging,
|
||||||
|
selection,
|
||||||
|
setTooltipPosition,
|
||||||
|
setStartDrag,
|
||||||
|
fileActionStore,
|
||||||
|
isFileSelected,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
openDocEditor,
|
||||||
|
getFolderInfo,
|
||||||
|
viewAs,
|
||||||
|
bufferSelection,
|
||||||
|
setBufferSelection,
|
||||||
|
} = filesStore;
|
||||||
|
|
||||||
|
const { startUpload } = uploadDataStore;
|
||||||
|
const { type, extension, id } = fileActionStore;
|
||||||
|
const { mediaViewersFormatsStore, docserviceStore } = formatsStore;
|
||||||
|
const { setMediaViewerData } = mediaViewerDataStore;
|
||||||
|
const { isVisible, setVisible } = infoPanelStore;
|
||||||
|
|
||||||
|
const selectedItem = selection.find(
|
||||||
|
(x) => x.id === item.id && x.fileExst === item.fileExst
|
||||||
|
);
|
||||||
|
|
||||||
|
const draggable =
|
||||||
|
!isRecycleBinFolder && selectedItem && selectedItem.id !== id;
|
||||||
|
|
||||||
|
const isFolder = selectedItem
|
||||||
|
? false
|
||||||
|
: !item.isFolder
|
||||||
|
? false
|
||||||
|
: true;
|
||||||
|
|
||||||
|
const isMediaOrImage = mediaViewersFormatsStore.isMediaOrImage(
|
||||||
|
item.fileExst
|
||||||
|
);
|
||||||
|
|
||||||
|
const canWebEdit = docserviceStore.canWebEdit(item.fileExst);
|
||||||
|
const canConvert = docserviceStore.canConvert(item.fileExst);
|
||||||
|
const canViewedDocs = docserviceStore.canViewedDocs(item.fileExst);
|
||||||
|
|
||||||
|
const isActive =
|
||||||
|
bufferSelection &&
|
||||||
|
bufferSelection.id === item.id &&
|
||||||
|
bufferSelection.fileExst === item.fileExst &&
|
||||||
|
!selection.length; // need for select row item
|
||||||
|
|
||||||
|
return {
|
||||||
|
t,
|
||||||
|
item,
|
||||||
|
selectRowAction,
|
||||||
|
onSelectItem,
|
||||||
|
setSharingPanelVisible,
|
||||||
|
isPrivacy: isPrivacyFolder,
|
||||||
|
dragging,
|
||||||
|
setDragging,
|
||||||
|
startUpload,
|
||||||
|
draggable,
|
||||||
|
setTooltipPosition,
|
||||||
|
setStartDrag,
|
||||||
|
history,
|
||||||
|
isFolder,
|
||||||
|
allowShareIn: filesStore.canShare,
|
||||||
|
actionType: type,
|
||||||
|
actionExtension: extension,
|
||||||
|
actionId: id,
|
||||||
|
checked: isFileSelected(item.id, item.parentId),
|
||||||
|
//parentFolder: selectedFolderStore.parentId,
|
||||||
|
setIsLoading,
|
||||||
|
fetchFiles,
|
||||||
|
isMediaOrImage,
|
||||||
|
canWebEdit,
|
||||||
|
canViewedDocs,
|
||||||
|
canConvert,
|
||||||
|
isTrashFolder: isRecycleBinFolder,
|
||||||
|
openDocEditor,
|
||||||
|
//addExpandedKeys,
|
||||||
|
setExpandedKeys,
|
||||||
|
createNewExpandedKeys,
|
||||||
|
setMediaViewerData,
|
||||||
|
getFolderInfo,
|
||||||
|
markAsRead,
|
||||||
|
viewAs,
|
||||||
|
setConvertItem,
|
||||||
|
setConvertDialogVisible,
|
||||||
|
isDesktop: auth.settingsStore.isDesktopClient,
|
||||||
|
personal: auth.settingsStore.personal,
|
||||||
|
isItemsSelected: selection.length > 0,
|
||||||
|
setNewBadgeCount,
|
||||||
|
isActive,
|
||||||
|
setBufferSelection,
|
||||||
|
bufferSelection,
|
||||||
|
isInfoPanelVisible: isVisible,
|
||||||
|
showInfoPanel: setVisible,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
)(observer(WithFileActions));
|
||||||
return window.open(viewUrl, "_self");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
item,
|
|
||||||
isTrashFolder,
|
|
||||||
draggable,
|
|
||||||
allowShareIn,
|
|
||||||
isPrivacy,
|
|
||||||
actionType,
|
|
||||||
actionExtension,
|
|
||||||
actionId,
|
|
||||||
sectionWidth,
|
|
||||||
checked,
|
|
||||||
dragging,
|
|
||||||
isFolder,
|
|
||||||
isDesktop,
|
|
||||||
personal,
|
|
||||||
canWebEdit,
|
|
||||||
canViewedDocs,
|
|
||||||
} = this.props;
|
|
||||||
const { fileExst, access, id } = item;
|
|
||||||
|
|
||||||
const isEdit =
|
|
||||||
actionType !== null && actionId === id && fileExst === actionExtension;
|
|
||||||
|
|
||||||
const isDragging = isFolder && access < 2 && !isTrashFolder && !isPrivacy;
|
|
||||||
|
|
||||||
let className = isDragging ? " droppable" : "";
|
|
||||||
if (draggable) className += " draggable";
|
|
||||||
|
|
||||||
let value = !item.isFolder ? `file_${id}` : `folder_${id}`;
|
|
||||||
value += draggable ? "_draggable" : "";
|
|
||||||
|
|
||||||
const isShareable = allowShareIn && item.canShare;
|
|
||||||
|
|
||||||
const isMobileView = sectionWidth < 500;
|
|
||||||
|
|
||||||
const displayShareButton = isMobileView
|
|
||||||
? "26px"
|
|
||||||
: !isShareable
|
|
||||||
? "38px"
|
|
||||||
: "96px";
|
|
||||||
|
|
||||||
const showShare =
|
|
||||||
!isShareable ||
|
|
||||||
isEdit ||
|
|
||||||
(isPrivacy && (!isDesktop || !fileExst)) ||
|
|
||||||
(personal && !canWebEdit && !canViewedDocs)
|
|
||||||
? false
|
|
||||||
: true;
|
|
||||||
|
|
||||||
const checkedProps = isEdit || id <= 0 ? false : checked;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<WrappedFileItem
|
|
||||||
onContentFileSelect={this.onContentFileSelect}
|
|
||||||
fileContextClick={this.fileContextClick}
|
|
||||||
onDrop={this.onDrop}
|
|
||||||
onMouseDown={this.onMouseDown}
|
|
||||||
onFilesClick={this.onFilesClick}
|
|
||||||
onMouseClick={this.onMouseClick}
|
|
||||||
onHideContextMenu={this.onHideContextMenu}
|
|
||||||
getClassName={this.getClassName}
|
|
||||||
className={className}
|
|
||||||
isDragging={isDragging}
|
|
||||||
value={value}
|
|
||||||
displayShareButton={displayShareButton}
|
|
||||||
isPrivacy={isPrivacy}
|
|
||||||
showShare={showShare}
|
|
||||||
checkedProps={checkedProps}
|
|
||||||
dragging={dragging}
|
|
||||||
isEdit={isEdit}
|
|
||||||
{...this.props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return inject(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
auth,
|
|
||||||
filesActionsStore,
|
|
||||||
dialogsStore,
|
|
||||||
treeFoldersStore,
|
|
||||||
//selectedFolderStore,
|
|
||||||
filesStore,
|
|
||||||
uploadDataStore,
|
|
||||||
formatsStore,
|
|
||||||
mediaViewerDataStore,
|
|
||||||
},
|
|
||||||
{ item, t, history }
|
|
||||||
) => {
|
|
||||||
const {
|
|
||||||
selectRowAction,
|
|
||||||
onSelectItem,
|
|
||||||
markAsRead,
|
|
||||||
setNewBadgeCount,
|
|
||||||
} = filesActionsStore;
|
|
||||||
const {
|
|
||||||
setSharingPanelVisible,
|
|
||||||
setConvertDialogVisible,
|
|
||||||
setConvertItem,
|
|
||||||
} = dialogsStore;
|
|
||||||
const {
|
|
||||||
isPrivacyFolder,
|
|
||||||
isRecycleBinFolder,
|
|
||||||
//addExpandedKeys,
|
|
||||||
setExpandedKeys,
|
|
||||||
createNewExpandedKeys,
|
|
||||||
} = treeFoldersStore;
|
|
||||||
const {
|
|
||||||
dragging,
|
|
||||||
setDragging,
|
|
||||||
selection,
|
|
||||||
setTooltipPosition,
|
|
||||||
setStartDrag,
|
|
||||||
fileActionStore,
|
|
||||||
isFileSelected,
|
|
||||||
setIsLoading,
|
|
||||||
fetchFiles,
|
|
||||||
openDocEditor,
|
|
||||||
getFolderInfo,
|
|
||||||
viewAs,
|
|
||||||
bufferSelection,
|
|
||||||
setBufferSelection,
|
|
||||||
} = filesStore;
|
|
||||||
const { startUpload } = uploadDataStore;
|
|
||||||
const { type, extension, id } = fileActionStore;
|
|
||||||
const { mediaViewersFormatsStore, docserviceStore } = formatsStore;
|
|
||||||
const { setMediaViewerData } = mediaViewerDataStore;
|
|
||||||
|
|
||||||
const selectedItem = selection.find(
|
|
||||||
(x) => x.id === item.id && x.fileExst === item.fileExst
|
|
||||||
);
|
|
||||||
|
|
||||||
const draggable =
|
|
||||||
!isRecycleBinFolder && selectedItem && selectedItem.id !== id;
|
|
||||||
|
|
||||||
const isFolder = selectedItem ? false : !item.isFolder ? false : true;
|
|
||||||
|
|
||||||
const isMediaOrImage = mediaViewersFormatsStore.isMediaOrImage(
|
|
||||||
item.fileExst
|
|
||||||
);
|
|
||||||
|
|
||||||
const canWebEdit = docserviceStore.canWebEdit(item.fileExst);
|
|
||||||
const canConvert = docserviceStore.canConvert(item.fileExst);
|
|
||||||
const canViewedDocs = docserviceStore.canViewedDocs(item.fileExst);
|
|
||||||
|
|
||||||
const isActive =
|
|
||||||
bufferSelection &&
|
|
||||||
bufferSelection.id === item.id &&
|
|
||||||
bufferSelection.fileExst === item.fileExst &&
|
|
||||||
!selection.length; // need for select row item
|
|
||||||
|
|
||||||
return {
|
|
||||||
t,
|
|
||||||
item,
|
|
||||||
selectRowAction,
|
|
||||||
onSelectItem,
|
|
||||||
setSharingPanelVisible,
|
|
||||||
isPrivacy: isPrivacyFolder,
|
|
||||||
dragging,
|
|
||||||
setDragging,
|
|
||||||
startUpload,
|
|
||||||
draggable,
|
|
||||||
setTooltipPosition,
|
|
||||||
setStartDrag,
|
|
||||||
history,
|
|
||||||
isFolder,
|
|
||||||
allowShareIn: filesStore.canShare,
|
|
||||||
actionType: type,
|
|
||||||
actionExtension: extension,
|
|
||||||
actionId: id,
|
|
||||||
checked: isFileSelected(item.id, item.parentId),
|
|
||||||
//parentFolder: selectedFolderStore.parentId,
|
|
||||||
setIsLoading,
|
|
||||||
fetchFiles,
|
|
||||||
isMediaOrImage,
|
|
||||||
canWebEdit,
|
|
||||||
canViewedDocs,
|
|
||||||
canConvert,
|
|
||||||
isTrashFolder: isRecycleBinFolder,
|
|
||||||
openDocEditor,
|
|
||||||
//addExpandedKeys,
|
|
||||||
setExpandedKeys,
|
|
||||||
createNewExpandedKeys,
|
|
||||||
setMediaViewerData,
|
|
||||||
getFolderInfo,
|
|
||||||
markAsRead,
|
|
||||||
viewAs,
|
|
||||||
setConvertItem,
|
|
||||||
setConvertDialogVisible,
|
|
||||||
isDesktop: auth.settingsStore.isDesktopClient,
|
|
||||||
personal: auth.settingsStore.personal,
|
|
||||||
isItemsSelected: selection.length > 0,
|
|
||||||
setNewBadgeCount,
|
|
||||||
isActive,
|
|
||||||
setBufferSelection,
|
|
||||||
bufferSelection,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)(observer(WithFileActions));
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
import {
|
|
||||||
StyledAccess,
|
|
||||||
StyledAccessUser,
|
|
||||||
StyledOpenSharingPanel,
|
|
||||||
StyledProperties,
|
|
||||||
StyledSubtitle,
|
|
||||||
StyledThumbnail,
|
|
||||||
StyledTitle,
|
|
||||||
} from "./styles/styles.js";
|
|
||||||
import RectangleLoader from "@appserver/common/components/Loaders/RectangleLoader";
|
import RectangleLoader from "@appserver/common/components/Loaders/RectangleLoader";
|
||||||
import { FileType } from "@appserver/common/constants";
|
import { FileType } from "@appserver/common/constants";
|
||||||
import Link from "@appserver/components/link";
|
import Link from "@appserver/components/link";
|
||||||
@ -17,6 +8,16 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { withTranslation } from "react-i18next";
|
import { withTranslation } from "react-i18next";
|
||||||
import { ReactSVG } from "react-svg";
|
import { ReactSVG } from "react-svg";
|
||||||
|
|
||||||
|
import {
|
||||||
|
StyledAccess,
|
||||||
|
StyledAccessUser,
|
||||||
|
StyledOpenSharingPanel,
|
||||||
|
StyledProperties,
|
||||||
|
StyledSubtitle,
|
||||||
|
StyledThumbnail,
|
||||||
|
StyledTitle,
|
||||||
|
} from "./styles/styles.js";
|
||||||
|
|
||||||
const SingleItem = (props) => {
|
const SingleItem = (props) => {
|
||||||
const {
|
const {
|
||||||
t,
|
t,
|
||||||
@ -30,6 +31,7 @@ const SingleItem = (props) => {
|
|||||||
getShareUsers,
|
getShareUsers,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
let updateSubscription = true;
|
||||||
const [item, setItem] = useState({
|
const [item, setItem] = useState({
|
||||||
id: "",
|
id: "",
|
||||||
isFolder: false,
|
isFolder: false,
|
||||||
@ -45,7 +47,6 @@ const SingleItem = (props) => {
|
|||||||
others: [],
|
others: [],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isShowAllAccessUsers, setIsShowAllAccessUsers] = useState(false);
|
const [isShowAllAccessUsers, setIsShowAllAccessUsers] = useState(false);
|
||||||
|
|
||||||
const updateItemsInfo = async (selectedItem) => {
|
const updateItemsInfo = async (selectedItem) => {
|
||||||
@ -264,11 +265,12 @@ const SingleItem = (props) => {
|
|||||||
|
|
||||||
const access = await updateLoadedItemAccess(selectedItem);
|
const access = await updateLoadedItemAccess(selectedItem);
|
||||||
|
|
||||||
setItem({
|
if (updateSubscription)
|
||||||
...displayedItem,
|
setItem({
|
||||||
properties: properties,
|
...displayedItem,
|
||||||
access: access,
|
properties: properties,
|
||||||
});
|
access: access,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const showAllAccessUsers = () => {
|
const showAllAccessUsers = () => {
|
||||||
@ -283,7 +285,9 @@ const SingleItem = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedItem.id !== item.id) updateItemsInfo(selectedItem);
|
if (selectedItem.id !== item.id && updateSubscription)
|
||||||
|
updateItemsInfo(selectedItem);
|
||||||
|
return () => (updateSubscription = false);
|
||||||
}, [selectedItem]);
|
}, [selectedItem]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,15 +19,18 @@ const InfoPanelBodyContent = ({
|
|||||||
setSharingPanelVisible,
|
setSharingPanelVisible,
|
||||||
isRecycleBinFolder,
|
isRecycleBinFolder,
|
||||||
}) => {
|
}) => {
|
||||||
|
if (selectedItems.length) {
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledInfoRoomBody>
|
<StyledInfoRoomBody>
|
||||||
{selectedItems.length === 0 ? (
|
{selectedItems.length === 0 && !bufferSelectedItem ? (
|
||||||
<div className="no-item">
|
<div className="no-item">
|
||||||
<h4>{t("NoItemsSelected")}</h4>
|
<h4>{t("NoItemsSelected")}</h4>
|
||||||
</div>
|
</div>
|
||||||
) : selectedItems.length === 1 ? (
|
) : selectedItems.length === 1 || bufferSelectedItem ? (
|
||||||
<SingleItem
|
<SingleItem
|
||||||
selectedItem={selectedItems[0]}
|
selectedItem={selectedItems[0] || bufferSelectedItem}
|
||||||
isRecycleBinFolder={isRecycleBinFolder}
|
isRecycleBinFolder={isRecycleBinFolder}
|
||||||
onSelectItem={onSelectItem}
|
onSelectItem={onSelectItem}
|
||||||
setSharingPanelVisible={setSharingPanelVisible}
|
setSharingPanelVisible={setSharingPanelVisible}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,10 +7,10 @@ import FilesActionsStore from "./FilesActionsStore";
|
|||||||
import FilesStore from "./FilesStore";
|
import FilesStore from "./FilesStore";
|
||||||
import FormatsStore from "./FormatsStore";
|
import FormatsStore from "./FormatsStore";
|
||||||
import iconFormatsStore from "./IconFormatsStore";
|
import iconFormatsStore from "./IconFormatsStore";
|
||||||
|
import InfoPanelStore from "./InfoPanelStore";
|
||||||
import MediaViewerDataStore from "./MediaViewerDataStore";
|
import MediaViewerDataStore from "./MediaViewerDataStore";
|
||||||
import mediaViewersFormatsStore from "./MediaViewersFormatsStore";
|
import mediaViewersFormatsStore from "./MediaViewersFormatsStore";
|
||||||
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
|
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
|
||||||
import InfoPanelStore from "./InfoPanelStore";
|
|
||||||
import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
|
import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
|
||||||
import selectedFilesStore from "./SelectedFilesStore";
|
import selectedFilesStore from "./SelectedFilesStore";
|
||||||
import selectedFolderStore from "./SelectedFolderStore";
|
import selectedFolderStore from "./SelectedFolderStore";
|
||||||
@ -37,8 +37,7 @@ const filesStore = new FilesStore(
|
|||||||
selectedFolderStore,
|
selectedFolderStore,
|
||||||
treeFoldersStore,
|
treeFoldersStore,
|
||||||
formatsStore,
|
formatsStore,
|
||||||
settingsStore,
|
settingsStore
|
||||||
selectedFilesStore
|
|
||||||
);
|
);
|
||||||
const mediaViewerDataStore = new MediaViewerDataStore(filesStore, formatsStore);
|
const mediaViewerDataStore = new MediaViewerDataStore(filesStore, formatsStore);
|
||||||
|
|
||||||
@ -60,6 +59,9 @@ const uploadDataStore = new UploadDataStore(
|
|||||||
dialogsStore,
|
dialogsStore,
|
||||||
settingsStore
|
settingsStore
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const infoPanelStore = new InfoPanelStore();
|
||||||
|
|
||||||
const filesActionsStore = new FilesActionsStore(
|
const filesActionsStore = new FilesActionsStore(
|
||||||
store.auth,
|
store.auth,
|
||||||
uploadDataStore,
|
uploadDataStore,
|
||||||
@ -68,13 +70,12 @@ const filesActionsStore = new FilesActionsStore(
|
|||||||
selectedFolderStore,
|
selectedFolderStore,
|
||||||
settingsStore,
|
settingsStore,
|
||||||
dialogsStore,
|
dialogsStore,
|
||||||
mediaViewerDataStore
|
mediaViewerDataStore,
|
||||||
|
infoPanelStore
|
||||||
);
|
);
|
||||||
|
|
||||||
const versionHistoryStore = new VersionHistoryStore(filesStore);
|
const versionHistoryStore = new VersionHistoryStore(filesStore);
|
||||||
|
|
||||||
const infoPanelStore = new InfoPanelStore();
|
|
||||||
|
|
||||||
//const selectedFilesStore = new SelectedFilesStore(selectedFilesStore);
|
//const selectedFilesStore = new SelectedFilesStore(selectedFilesStore);
|
||||||
const stores = {
|
const stores = {
|
||||||
filesStore,
|
filesStore,
|
||||||
|
12
public/images/info.outline.react.svg
Normal file
12
public/images/info.outline.react.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_21120_56765)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.5 2C5.18629 2 2.5 4.68629 2.5 8C2.5 11.3137 5.18629 14 8.5 14C11.8137 14 14.5 11.3137 14.5 8C14.5 4.68629 11.8137 2 8.5 2ZM0.5 8C0.5 3.58172 4.08172 0 8.5 0C12.9183 0 16.5 3.58172 16.5 8C16.5 12.4183 12.9183 16 8.5 16C4.08172 16 0.5 12.4183 0.5 8Z" fill="#333333"/>
|
||||||
|
<circle cx="8.5" cy="5" r="1" fill="#333333"/>
|
||||||
|
<rect x="7.5" y="7" width="2" height="5" rx="1" fill="#333333"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_21120_56765">
|
||||||
|
<rect width="16" height="16" fill="white" transform="translate(0.5)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 710 B |
Loading…
Reference in New Issue
Block a user