Merge branch 'release/v1.2' of github.com:ONLYOFFICE/AppServer into feature/ip-security
This commit is contained in:
commit
aa7d285025
File diff suppressed because it is too large
Load Diff
@ -147,6 +147,11 @@ const StyledArticleHeader = styled.div`
|
||||
padding: 16px 16px 17px;
|
||||
margin: 0;
|
||||
justify-content: ${(props) => (props.showText ? "flex-start" : "center")};
|
||||
|
||||
height: 61px;
|
||||
min-height: 61px;
|
||||
max-height: 61px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
@ -204,7 +209,7 @@ const StyledHeading = styled(Heading)`
|
||||
const StyledIconBox = styled.div`
|
||||
display: none;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
height: 20px;
|
||||
|
||||
@media ${tablet} {
|
||||
display: flex;
|
||||
|
@ -42,7 +42,11 @@ const ArticleHeader = ({
|
||||
return (
|
||||
<StyledArticleHeader showText={showText} {...rest}>
|
||||
{isTabletView && (isBurgerLoading || showLoader) ? (
|
||||
<Loaders.ArticleHeader height="20px" />
|
||||
<Loaders.ArticleHeader
|
||||
height="20px"
|
||||
width="20px"
|
||||
style={{ height: "20px" }}
|
||||
/>
|
||||
) : (
|
||||
<StyledIconBox name="article-burger">
|
||||
<StyledMenuIcon onClick={onClick} />
|
||||
|
@ -559,22 +559,19 @@ Section.SectionFilter = SectionFilter;
|
||||
Section.SectionBody = SectionBody;
|
||||
Section.SectionPaging = SectionPaging;
|
||||
|
||||
export default inject(({ auth, infoPanelStore }) => {
|
||||
const { isLoaded, settingsStore } = auth;
|
||||
export default inject(({ auth }) => {
|
||||
const { infoPanelStore, isLoaded, settingsStore } = auth;
|
||||
const {
|
||||
isHeaderVisible,
|
||||
isTabletView,
|
||||
|
||||
isDesktopClient,
|
||||
maintenanceExist,
|
||||
snackbarExist,
|
||||
setMaintenanceExist,
|
||||
|
||||
showText,
|
||||
} = settingsStore;
|
||||
|
||||
let infoPanelIsVisible = false;
|
||||
if (infoPanelStore) infoPanelIsVisible = infoPanelStore.isVisible;
|
||||
const { isVisible: infoPanelIsVisible } = infoPanelStore;
|
||||
|
||||
return {
|
||||
isLoaded,
|
||||
@ -588,6 +585,6 @@ export default inject(({ auth, infoPanelStore }) => {
|
||||
|
||||
showText,
|
||||
|
||||
infoPanelIsVisible: infoPanelIsVisible,
|
||||
infoPanelIsVisible,
|
||||
};
|
||||
})(observer(Section));
|
||||
|
@ -51,9 +51,11 @@ const StyledInfoPanelToggleWrapper = styled.div`
|
||||
`;
|
||||
StyledInfoPanelToggleWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const SubInfoPanelHeader = ({ children, closeInfoPanel }) => {
|
||||
const SubInfoPanelHeader = ({ children, setIsVisible }) => {
|
||||
const content = children?.props?.children;
|
||||
|
||||
const closeInfoPanel = () => setIsVisible(false);
|
||||
|
||||
return (
|
||||
<StyledInfoPanelHeader>
|
||||
<Text className="header-text" fontSize="21px" fontWeight="700">
|
||||
@ -91,10 +93,7 @@ SubInfoPanelHeader.defaultProps = { theme: Base };
|
||||
|
||||
SubInfoPanelHeader.displayName = "SubInfoPanelHeader";
|
||||
|
||||
export default inject(({ infoPanelStore }) => {
|
||||
let closeInfoPanel = () => {};
|
||||
if (infoPanelStore) {
|
||||
closeInfoPanel = () => infoPanelStore.setIsVisible(false);
|
||||
}
|
||||
return { closeInfoPanel };
|
||||
export default inject(({ auth }) => {
|
||||
const { setIsVisible } = auth.infoPanelStore;
|
||||
return { setIsVisible };
|
||||
})(observer(SubInfoPanelHeader));
|
||||
|
@ -182,15 +182,8 @@ StyledInfoPanelWrapper.defaultProps = { theme: Base };
|
||||
StyledInfoPanel.defaultProps = { theme: Base };
|
||||
InfoPanel.defaultProps = { theme: Base };
|
||||
|
||||
export default inject(({ infoPanelStore }) => {
|
||||
let isVisible = false;
|
||||
let setIsVisible = () => {};
|
||||
|
||||
if (infoPanelStore) {
|
||||
isVisible = infoPanelStore.isVisible;
|
||||
setIsVisible = infoPanelStore.setIsVisible;
|
||||
}
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { isVisible, setIsVisible } = auth.infoPanelStore;
|
||||
return {
|
||||
isVisible,
|
||||
setIsVisible,
|
||||
|
@ -6,6 +6,7 @@ import ModuleStore from "./ModuleStore";
|
||||
import SettingsStore from "./SettingsStore";
|
||||
import UserStore from "./UserStore";
|
||||
import TfaStore from "./TfaStore";
|
||||
import InfoPanelStore from "./InfoPanelStore";
|
||||
import { logout as logoutDesktop, desktopConstants } from "../desktop";
|
||||
import { combineUrl, isAdmin } from "../utils";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
@ -17,6 +18,7 @@ class AuthStore {
|
||||
moduleStore = null;
|
||||
settingsStore = null;
|
||||
tfaStore = null;
|
||||
infoPanelStore = null;
|
||||
|
||||
isLoading = false;
|
||||
version = null;
|
||||
@ -29,6 +31,7 @@ class AuthStore {
|
||||
this.moduleStore = new ModuleStore();
|
||||
this.settingsStore = new SettingsStore();
|
||||
this.tfaStore = new TfaStore();
|
||||
this.infoPanelStore = new InfoPanelStore();
|
||||
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
@ -0,0 +1,190 @@
|
||||
function toFileWithPath(file, path) {
|
||||
if (typeof file?.path === "string") return file;
|
||||
|
||||
// on electron, path is already set to the absolute path
|
||||
const { webkitRelativePath } = file;
|
||||
Object.defineProperty(file, "path", {
|
||||
value:
|
||||
typeof path === "string"
|
||||
? path
|
||||
: // If <input webkitdirectory> is set,
|
||||
// the File will have a {webkitRelativePath} property
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory
|
||||
typeof webkitRelativePath === "string" && webkitRelativePath.length > 0
|
||||
? webkitRelativePath
|
||||
: file.name,
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
const FILES_TO_IGNORE = [
|
||||
// Thumbnail cache files for macOS and Windows
|
||||
".DS_Store",
|
||||
"Thumbs.db", // Windows
|
||||
];
|
||||
/**
|
||||
* Convert a DragEvent's DataTrasfer object to a list of File objects
|
||||
* NOTE: If some of the items are folders,
|
||||
* everything will be flattened and placed in the same list but the paths will be kept as a {path} property.
|
||||
* @param evt
|
||||
*/
|
||||
export default async function getFilesFromEvent(evt) {
|
||||
return isDragEvt(evt) && evt.dataTransfer
|
||||
? getDataTransferFiles(evt.dataTransfer, evt.type)
|
||||
: getInputFiles(evt);
|
||||
}
|
||||
|
||||
function isDragEvt(value) {
|
||||
return !!value.dataTransfer;
|
||||
}
|
||||
|
||||
function getInputFiles(evt) {
|
||||
const files = isInput(evt.target)
|
||||
? evt.target.files
|
||||
? fromList(evt.target.files)
|
||||
: []
|
||||
: [];
|
||||
return files.map((file) => toFileWithPath(file));
|
||||
}
|
||||
|
||||
function isInput(value) {
|
||||
return value !== null;
|
||||
}
|
||||
|
||||
async function getDataTransferFiles(dt, type) {
|
||||
// IE11 does not support dataTransfer.items
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/items#Browser_compatibility
|
||||
if (dt.items) {
|
||||
const items = fromList(dt.items).filter((item) => item.kind === "file");
|
||||
// According to https://html.spec.whatwg.org/multipage/dnd.html#dndevents,
|
||||
// only 'dragstart' and 'drop' has access to the data (source node)
|
||||
if (type !== "drop") {
|
||||
return items;
|
||||
}
|
||||
const files = await Promise.all(items.map(toFilePromises));
|
||||
return noIgnoredFiles(flatten(files));
|
||||
}
|
||||
return noIgnoredFiles(fromList(dt.files).map((file) => toFileWithPath(file)));
|
||||
}
|
||||
|
||||
function noIgnoredFiles(files) {
|
||||
return files.filter((file) => FILES_TO_IGNORE.indexOf(file.name) === -1);
|
||||
}
|
||||
|
||||
// IE11 does not support Array.from()
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Browser_compatibility
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileList
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList
|
||||
function fromList(items) {
|
||||
const files = [];
|
||||
// tslint:disable: prefer-for-of
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const file = items[i];
|
||||
files.push(file);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem
|
||||
function toFilePromises(item) {
|
||||
if (typeof item.webkitGetAsEntry !== "function") {
|
||||
return fromDataTransferItem(item);
|
||||
}
|
||||
const entry = item.webkitGetAsEntry();
|
||||
// Safari supports dropping an image node from a different window and can be retrieved using
|
||||
// the DataTransferItem.getAsFile() API
|
||||
// NOTE: FileSystemEntry.file() throws if trying to get the file
|
||||
if (entry && entry.isDirectory) {
|
||||
return fromDirEntry(entry);
|
||||
}
|
||||
return fromDataTransferItem(item);
|
||||
}
|
||||
|
||||
function flatten(items) {
|
||||
return items.reduce(
|
||||
(acc, files) => [
|
||||
...acc,
|
||||
...(Array.isArray(files) ? flatten(files) : [files]),
|
||||
],
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
function fromDataTransferItem(item) {
|
||||
const file = item.getAsFile();
|
||||
if (!file) {
|
||||
return Promise.reject(`${item} is not a File`);
|
||||
}
|
||||
const fwp = toFileWithPath(file);
|
||||
return Promise.resolve(fwp);
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemEntry
|
||||
async function fromEntry(entry) {
|
||||
return entry.isDirectory ? fromDirEntry(entry) : fromFileEntry(entry);
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryEntry
|
||||
function fromDirEntry(entry) {
|
||||
const reader = entry.createReader();
|
||||
return new Promise((resolve, reject) => {
|
||||
const entries = [];
|
||||
let empty = true;
|
||||
function readEntries() {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryEntry/createReader
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryReader/readEntries
|
||||
reader.readEntries(
|
||||
async (batch) => {
|
||||
if (!batch.length) {
|
||||
// Done reading directory
|
||||
try {
|
||||
const files = await Promise.all(entries);
|
||||
if (empty) {
|
||||
files.push([createEmptyDirFile(entry)]);
|
||||
}
|
||||
resolve(files);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
} else {
|
||||
const items = Promise.all(batch.map(fromEntry));
|
||||
entries.push(items);
|
||||
// Continue reading
|
||||
empty = false;
|
||||
readEntries();
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
readEntries();
|
||||
});
|
||||
}
|
||||
|
||||
function createEmptyDirFile(entry) {
|
||||
const file = new File([], entry.name);
|
||||
const fwp = toFileWithPath(file, entry.fullPath + "/");
|
||||
|
||||
Object.defineProperty(fwp, "isEmptyDirectory", {
|
||||
value: true,
|
||||
});
|
||||
return fwp;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry
|
||||
async function fromFileEntry(entry) {
|
||||
return new Promise((resolve, reject) => {
|
||||
entry.file(
|
||||
(file) => {
|
||||
const fwp = toFileWithPath(file, entry.fullPath);
|
||||
resolve(fwp);
|
||||
},
|
||||
(err) => {
|
||||
reject(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import getFilesFromEvent from "./get-files-from-event";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import StyledDragAndDrop from "./styled-drag-and-drop";
|
||||
@ -8,7 +9,7 @@ const DragAndDrop = (props) => {
|
||||
const { isDropZone, children, dragging, className, ...rest } = props;
|
||||
const classNameProp = className ? className : "";
|
||||
|
||||
const onDrop = (acceptedFiles, array) => {
|
||||
const onDrop = (acceptedFiles) => {
|
||||
acceptedFiles.length && props.onDrop && props.onDrop(acceptedFiles);
|
||||
};
|
||||
|
||||
@ -25,6 +26,7 @@ const DragAndDrop = (props) => {
|
||||
onDrop,
|
||||
onDragOver,
|
||||
onDragLeave,
|
||||
getFilesFromEvent: (event) => getFilesFromEvent(event),
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -30,7 +30,7 @@
|
||||
"react-countdown": "2.3.2",
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-device-detect": "^1.17.0",
|
||||
"react-dropzone": "^11.2.4",
|
||||
"react-dropzone": "^11.4.2",
|
||||
"react-lifecycles-compat": "^3.0.4",
|
||||
"react-onclickoutside": "^6.11.2",
|
||||
"react-svg": "^12.1.0",
|
||||
|
@ -78,7 +78,7 @@ class ToggleButton extends Component {
|
||||
//console.log("ToggleButton render");
|
||||
|
||||
return (
|
||||
<Container {...this.props}>
|
||||
<Container id={id} className={className} style={style}>
|
||||
<ToggleButtonContainer
|
||||
id={id}
|
||||
className={className}
|
||||
|
@ -34,10 +34,26 @@ export default function withFileActions(WrappedFileItem) {
|
||||
};
|
||||
|
||||
onDropZoneUpload = (files, uploadToFolder) => {
|
||||
const { t, dragging, setDragging, startUpload } = this.props;
|
||||
const {
|
||||
t,
|
||||
dragging,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
} = this.props;
|
||||
|
||||
dragging && setDragging(false);
|
||||
startUpload(files, uploadToFolder, t);
|
||||
|
||||
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
|
||||
|
||||
if (emptyFolders.length > 0) {
|
||||
uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => {
|
||||
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
|
||||
if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
};
|
||||
|
||||
onDrop = (items) => {
|
||||
@ -247,6 +263,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
onSelectItem,
|
||||
setNewBadgeCount,
|
||||
openFileAction,
|
||||
uploadEmptyFolders,
|
||||
} = filesActionsStore;
|
||||
const { setSharingPanelVisible } = dialogsStore;
|
||||
const {
|
||||
@ -315,6 +332,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
dragging,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
draggable,
|
||||
setTooltipPosition,
|
||||
setStartDrag,
|
||||
|
@ -27,6 +27,7 @@ const Item = ({
|
||||
onBadgeClick,
|
||||
showDragItems,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
setDragging,
|
||||
}) => {
|
||||
const [isDragActive, setIsDragActive] = React.useState(false);
|
||||
@ -41,9 +42,18 @@ const Item = ({
|
||||
const onDropZoneUpload = React.useCallback(
|
||||
(files, uploadToFolder) => {
|
||||
dragging && setDragging(false);
|
||||
startUpload(files, uploadToFolder, t);
|
||||
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
|
||||
|
||||
if (emptyFolders.length > 0) {
|
||||
uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => {
|
||||
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
|
||||
if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
},
|
||||
[t, dragging, setDragging, startUpload]
|
||||
[t, dragging, setDragging, startUpload, uploadEmptyFolders]
|
||||
);
|
||||
|
||||
const onDrop = React.useCallback(
|
||||
@ -118,6 +128,7 @@ const Items = ({
|
||||
dragging,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
|
||||
isAdmin,
|
||||
myId,
|
||||
@ -273,6 +284,7 @@ const Items = ({
|
||||
t={t}
|
||||
setDragging={setDragging}
|
||||
startUpload={startUpload}
|
||||
uploadEmptyFolders={uploadEmptyFolders}
|
||||
item={item}
|
||||
dragging={dragging}
|
||||
getFolderIcon={getFolderIcon}
|
||||
@ -301,6 +313,7 @@ const Items = ({
|
||||
showText,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
]
|
||||
);
|
||||
|
||||
@ -337,7 +350,7 @@ export default inject(
|
||||
} = treeFoldersStore;
|
||||
|
||||
const { id } = selectedFolderStore;
|
||||
|
||||
const { moveDragItems, uploadEmptyFolders } = filesActionsStore;
|
||||
return {
|
||||
isAdmin: auth.isAdmin,
|
||||
myId: myFolderId,
|
||||
@ -352,8 +365,9 @@ export default inject(
|
||||
dragging,
|
||||
setDragging,
|
||||
setStartDrag,
|
||||
moveDragItems: filesActionsStore.moveDragItems,
|
||||
moveDragItems,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
};
|
||||
}
|
||||
)(withTranslation(["Home", "Common", "Translations"])(observer(Items)));
|
||||
|
@ -198,6 +198,8 @@ const EditingWrapperComponent = (props) => {
|
||||
const [CancelIconIsHovered, setIsHoveredCancel] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const inputRef = React.useRef(null);
|
||||
|
||||
const onKeyUpUpdateItem = (e) => {
|
||||
if (isLoading) return;
|
||||
|
||||
@ -228,6 +230,8 @@ const EditingWrapperComponent = (props) => {
|
||||
)
|
||||
return false;
|
||||
|
||||
if (!document.hasFocus() && inputRef.current === e.target) return false;
|
||||
|
||||
!passwordEntryProcess && onClickUpdateItem(e, false);
|
||||
};
|
||||
|
||||
@ -256,6 +260,7 @@ const EditingWrapperComponent = (props) => {
|
||||
isDisabled={isLoading}
|
||||
data-itemid={itemId}
|
||||
withBorder={!isTable}
|
||||
forwardedRef={inputRef}
|
||||
/>
|
||||
)}
|
||||
{!isUpdatingRowItem && (
|
||||
|
@ -33,92 +33,86 @@ const SelectFileDialogAsideView = ({
|
||||
maxInputWidth,
|
||||
newFilter,
|
||||
}) => {
|
||||
const onMouseEvent = (event) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
return (
|
||||
<div onMouseUp={onMouseEvent} onMouseDown={onMouseEvent}>
|
||||
<ModalDialog
|
||||
visible={isPanelVisible}
|
||||
onClose={onClose}
|
||||
contentHeight="100%"
|
||||
contentPaddingBottom="0px"
|
||||
displayType="aside"
|
||||
withoutBodyScroll
|
||||
>
|
||||
<ModalDialog.Header>{dialogName}</ModalDialog.Header>
|
||||
<ModalDialog.Body className="select-file_body-modal-dialog">
|
||||
<StyledAsideBody theme={theme}>
|
||||
<div className="selection-panel_aside-body">
|
||||
<div className="selection-panel_folder-info">
|
||||
<Text
|
||||
className="selection-panel_folder-selection-title"
|
||||
fontWeight={600}
|
||||
>
|
||||
{t("Translations:FolderSelection")}
|
||||
</Text>
|
||||
<ModalDialog
|
||||
visible={isPanelVisible}
|
||||
onClose={onClose}
|
||||
contentHeight="100%"
|
||||
contentPaddingBottom="0px"
|
||||
displayType="aside"
|
||||
withoutBodyScroll
|
||||
>
|
||||
<ModalDialog.Header>{dialogName}</ModalDialog.Header>
|
||||
<ModalDialog.Body className="select-file_body-modal-dialog">
|
||||
<StyledAsideBody theme={theme}>
|
||||
<div className="selection-panel_aside-body">
|
||||
<div className="selection-panel_folder-info">
|
||||
<Text
|
||||
className="selection-panel_folder-selection-title"
|
||||
fontWeight={600}
|
||||
>
|
||||
{t("Translations:FolderSelection")}
|
||||
</Text>
|
||||
|
||||
<SelectFolderInput
|
||||
theme={theme}
|
||||
onClickInput={onClickInput}
|
||||
onClose={onCloseSelectFolderDialog}
|
||||
onSelectFolder={onSelectFolder}
|
||||
isPanelVisible={isFolderPanelVisible}
|
||||
foldersType={foldersType}
|
||||
withoutProvider={withoutProvider}
|
||||
id={folderId}
|
||||
onSelectFile={onSelectFile}
|
||||
displayType="aside"
|
||||
hasNextPage={hasNextPage}
|
||||
isNextPageLoading={isNextPageLoading}
|
||||
loadNextPage={loadNextPage}
|
||||
files={files}
|
||||
folderTree={resultingFolderTree}
|
||||
isFolderTreeLoading={!!!resultingFolderTree}
|
||||
isNeedArrowIcon
|
||||
maxInputWidth={maxInputWidth ? maxInputWidth : "446px"}
|
||||
/>
|
||||
<SelectFolderInput
|
||||
theme={theme}
|
||||
onClickInput={onClickInput}
|
||||
onClose={onCloseSelectFolderDialog}
|
||||
onSelectFolder={onSelectFolder}
|
||||
isPanelVisible={isFolderPanelVisible}
|
||||
foldersType={foldersType}
|
||||
withoutProvider={withoutProvider}
|
||||
id={folderId}
|
||||
onSelectFile={onSelectFile}
|
||||
displayType="aside"
|
||||
hasNextPage={hasNextPage}
|
||||
isNextPageLoading={isNextPageLoading}
|
||||
loadNextPage={loadNextPage}
|
||||
files={files}
|
||||
folderTree={resultingFolderTree}
|
||||
isFolderTreeLoading={!!!resultingFolderTree}
|
||||
isNeedArrowIcon
|
||||
maxInputWidth={maxInputWidth ? maxInputWidth : "446px"}
|
||||
/>
|
||||
|
||||
<Text color="#A3A9AE" className="selection-panel_aside-title">
|
||||
{filesListTitle}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="selection-panel_files">
|
||||
<FilesListWrapper
|
||||
<Text color="#A3A9AE" className="selection-panel_aside-title">
|
||||
{filesListTitle}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="selection-panel_files">
|
||||
<FilesListWrapper
|
||||
theme={theme}
|
||||
onSelectFile={onSelectFile}
|
||||
folderId={folderId}
|
||||
displayType="aside"
|
||||
folderSelection={false}
|
||||
fileId={fileId}
|
||||
newFilter={newFilter}
|
||||
/>
|
||||
</div>
|
||||
<div className="selection-panel_aside-footer">
|
||||
{footer}
|
||||
<div className="selection-panel_aside-buttons">
|
||||
<Button
|
||||
theme={theme}
|
||||
onSelectFile={onSelectFile}
|
||||
folderId={folderId}
|
||||
displayType="aside"
|
||||
folderSelection={false}
|
||||
fileId={fileId}
|
||||
newFilter={newFilter}
|
||||
primary
|
||||
size="normalTouchscreen"
|
||||
label={primaryButtonName}
|
||||
onClick={onButtonClick}
|
||||
isDisabled={!fileId}
|
||||
/>
|
||||
<Button
|
||||
theme={theme}
|
||||
size="normalTouchscreen"
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
<div className="selection-panel_aside-footer">
|
||||
{footer}
|
||||
<div className="selection-panel_aside-buttons">
|
||||
<Button
|
||||
theme={theme}
|
||||
primary
|
||||
size="normalTouchscreen"
|
||||
label={primaryButtonName}
|
||||
onClick={onButtonClick}
|
||||
isDisabled={!fileId}
|
||||
/>
|
||||
<Button
|
||||
theme={theme}
|
||||
size="normalTouchscreen"
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</StyledAsideBody>
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
</div>
|
||||
</div>
|
||||
</StyledAsideBody>
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
);
|
||||
};
|
||||
export default SelectFileDialogAsideView;
|
||||
|
@ -47,119 +47,109 @@ const SelectionPanelBody = ({
|
||||
isDisableButton,
|
||||
parentId,
|
||||
}) => {
|
||||
const onMouseEvent = (event) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
return (
|
||||
<div onMouseUp={onMouseEvent} onMouseDown={onMouseEvent}>
|
||||
<StyledModalDialog
|
||||
theme={theme}
|
||||
visible={isPanelVisible}
|
||||
onClose={onClose}
|
||||
className="select-file-modal-dialog"
|
||||
style={{ maxWidth: "773px" }}
|
||||
displayType="modal"
|
||||
modalBodyPadding="0px"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
<ModalDialog.Header theme={theme}>{dialogName}</ModalDialog.Header>
|
||||
<ModalDialog.Body
|
||||
theme={theme}
|
||||
className="select-file_body-modal-dialog"
|
||||
>
|
||||
<StyledBody header={!!header} footer={!!footer}>
|
||||
<div className="selection-panel_body">
|
||||
<div className="selection-panel_tree-body">
|
||||
<Text
|
||||
fontWeight="700"
|
||||
fontSize="18px"
|
||||
className="selection-panel_folder-title"
|
||||
>
|
||||
{t("Common:Documents")}
|
||||
</Text>
|
||||
<StyledModalDialog
|
||||
theme={theme}
|
||||
visible={isPanelVisible}
|
||||
onClose={onClose}
|
||||
style={{ maxWidth: "773px" }}
|
||||
displayType="modal"
|
||||
modalBodyPadding="0px"
|
||||
isLoading={isLoading}
|
||||
>
|
||||
<ModalDialog.Header theme={theme}>{dialogName}</ModalDialog.Header>
|
||||
<ModalDialog.Body theme={theme} className="select-file_body-modal-dialog">
|
||||
<StyledBody header={!!header} footer={!!footer}>
|
||||
<div className="selection-panel_body">
|
||||
<div className="selection-panel_tree-body">
|
||||
<Text
|
||||
fontWeight="700"
|
||||
fontSize="18px"
|
||||
className="selection-panel_folder-title"
|
||||
>
|
||||
{t("Common:Documents")}
|
||||
</Text>
|
||||
|
||||
{folderId && resultingFolderTree ? (
|
||||
<FolderTreeBody
|
||||
{folderId && resultingFolderTree ? (
|
||||
<FolderTreeBody
|
||||
theme={theme}
|
||||
folderTree={resultingFolderTree}
|
||||
onSelect={onSelectFolder}
|
||||
withoutProvider={withoutProvider}
|
||||
certainFolders
|
||||
isAvailable={isAvailable}
|
||||
selectedKeys={[`${folderId}`]}
|
||||
parentId={parentId}
|
||||
expandedKeys={expandedKeys}
|
||||
isDisableTree={isDisableTree}
|
||||
displayType="modal"
|
||||
/>
|
||||
) : (
|
||||
<Loaders.NewTreeFolders />
|
||||
)}
|
||||
</div>
|
||||
<div className="selection-panel_files-body">
|
||||
<>
|
||||
<div className="selection-panel_files-header">
|
||||
{header}
|
||||
|
||||
<Text
|
||||
color="#A3A9AE"
|
||||
theme={theme}
|
||||
folderTree={resultingFolderTree}
|
||||
onSelect={onSelectFolder}
|
||||
withoutProvider={withoutProvider}
|
||||
certainFolders
|
||||
isAvailable={isAvailable}
|
||||
selectedKeys={[`${folderId}`]}
|
||||
parentId={parentId}
|
||||
expandedKeys={expandedKeys}
|
||||
isDisableTree={isDisableTree}
|
||||
displayType="modal"
|
||||
/>
|
||||
) : (
|
||||
<Loaders.NewTreeFolders />
|
||||
)}
|
||||
</div>
|
||||
<div className="selection-panel_files-body">
|
||||
<>
|
||||
<div className="selection-panel_files-header">
|
||||
{header}
|
||||
|
||||
<Text
|
||||
color="#A3A9AE"
|
||||
theme={theme}
|
||||
className="selection-panel_title"
|
||||
>
|
||||
{folderSelection
|
||||
? t("FolderContents", { folderTitle })
|
||||
: filesListTitle}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<FilesListWrapper
|
||||
theme={theme}
|
||||
onSelectFile={onSelectFile}
|
||||
folderId={folderId}
|
||||
displayType={"modal"}
|
||||
folderSelection={folderSelection}
|
||||
newFilter={newFilter}
|
||||
fileId={fileId}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
|
||||
<div className="selection-panel_footer">
|
||||
<div>{footer}</div>
|
||||
|
||||
<div className="selection-panel_buttons">
|
||||
<Button
|
||||
theme={theme}
|
||||
className="select-file-modal-dialog-buttons-save"
|
||||
primary
|
||||
size="normalTouchscreen"
|
||||
label={primaryButtonName}
|
||||
onClick={onButtonClick}
|
||||
isDisabled={
|
||||
isDisableButton ||
|
||||
isDisableTree ||
|
||||
isLoadingData ||
|
||||
(!fileId && !folderSelection) ||
|
||||
!canCreate
|
||||
}
|
||||
isLoading={isDisableTree}
|
||||
/>
|
||||
<Button
|
||||
theme={theme}
|
||||
className="modal-dialog-button"
|
||||
size="normalTouchscreen"
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={onClose}
|
||||
isDisabled={isLoadingData}
|
||||
/>
|
||||
className="selection-panel_title"
|
||||
>
|
||||
{folderSelection
|
||||
? t("FolderContents", { folderTitle })
|
||||
: filesListTitle}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<FilesListWrapper
|
||||
theme={theme}
|
||||
onSelectFile={onSelectFile}
|
||||
folderId={folderId}
|
||||
displayType={"modal"}
|
||||
folderSelection={folderSelection}
|
||||
newFilter={newFilter}
|
||||
fileId={fileId}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
|
||||
<div className="selection-panel_footer">
|
||||
<div>{footer}</div>
|
||||
|
||||
<div className="selection-panel_buttons">
|
||||
<Button
|
||||
theme={theme}
|
||||
className="select-file-modal-dialog-buttons-save"
|
||||
primary
|
||||
size="normalTouchscreen"
|
||||
label={primaryButtonName}
|
||||
onClick={onButtonClick}
|
||||
isDisabled={
|
||||
isDisableButton ||
|
||||
isDisableTree ||
|
||||
isLoadingData ||
|
||||
(!fileId && !folderSelection) ||
|
||||
!canCreate
|
||||
}
|
||||
isLoading={isDisableTree}
|
||||
/>
|
||||
<Button
|
||||
theme={theme}
|
||||
className="modal-dialog-button"
|
||||
size="normalTouchscreen"
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={onClose}
|
||||
isDisabled={isLoadingData}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</StyledBody>
|
||||
</ModalDialog.Body>
|
||||
</StyledModalDialog>
|
||||
</div>
|
||||
</div>
|
||||
</StyledBody>
|
||||
</ModalDialog.Body>
|
||||
</StyledModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -58,9 +58,8 @@ const SectionHeaderContent = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ infoPanelStore }) => {
|
||||
const { toggleIsVisible, isVisible } = infoPanelStore;
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { toggleIsVisible, isVisible } = auth.infoPanelStore;
|
||||
return {
|
||||
toggleInfoPanel: toggleIsVisible,
|
||||
isInfoPanelVisible: isVisible,
|
||||
|
@ -56,6 +56,11 @@ const StyledContainer = styled.div`
|
||||
const StyledInfoPanelToggleWrapper = styled.div`
|
||||
margin-left: auto;
|
||||
|
||||
display: ${(props) => (props.isInfoPanelVisible ? "none" : "flex")};
|
||||
@media ${tablet} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-panel-toggle-bg {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
@ -208,20 +208,18 @@ Tile.defaultProps = {
|
||||
item: {},
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ filesStore, settingsStore, infoPanelStore }, { item }) => {
|
||||
const { gallerySelected, setGallerySelected } = filesStore;
|
||||
const { getIcon } = settingsStore;
|
||||
const { isVisible, setIsVisible } = infoPanelStore;
|
||||
export default inject(({ filesStore, settingsStore, auth }, { item }) => {
|
||||
const { gallerySelected, setGallerySelected } = filesStore;
|
||||
const { getIcon } = settingsStore;
|
||||
const { isVisible, setIsVisible } = auth.infoPanelStore;
|
||||
|
||||
const isSelected = item.id === gallerySelected?.id;
|
||||
const isSelected = item.id === gallerySelected?.id;
|
||||
|
||||
return {
|
||||
isSelected,
|
||||
setGallerySelected,
|
||||
getIcon,
|
||||
setIsInfoPanelVisible: setIsVisible,
|
||||
isInfoPanelVisible: isVisible,
|
||||
};
|
||||
}
|
||||
)(withTranslation(["FormGallery", "Common"])(withRouter(observer(Tile))));
|
||||
return {
|
||||
isSelected,
|
||||
setGallerySelected,
|
||||
getIcon,
|
||||
setIsInfoPanelVisible: setIsVisible,
|
||||
isInfoPanelVisible: isVisible,
|
||||
};
|
||||
})(withTranslation(["FormGallery", "Common"])(withRouter(observer(Tile))));
|
||||
|
@ -56,7 +56,7 @@ const SingleItem = (props) => {
|
||||
<div className="property">
|
||||
<Text className="property-title">{t("Home:ByLastModifiedDate")}</Text>
|
||||
<Text className="property-content">
|
||||
{parseAndFormatDate(selectedItem.updatedAt)}
|
||||
{parseAndFormatDate(selectedItem.attributes.updatedAt)}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="property">
|
||||
|
@ -69,7 +69,11 @@ const InfoPanelBodyContent = ({
|
||||
<GalleryEmptyScreen />
|
||||
) : (
|
||||
<StyledInfoRoomBody>
|
||||
<GalleryItem selectedItem={gallerySelected} />
|
||||
<GalleryItem
|
||||
selectedItem={gallerySelected}
|
||||
personal={personal}
|
||||
culture={culture}
|
||||
/>
|
||||
</StyledInfoRoomBody>
|
||||
)
|
||||
) : (
|
||||
|
@ -97,10 +97,9 @@ const FilesRowContainer = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ filesStore, infoPanelStore }) => {
|
||||
export default inject(({ filesStore, auth }) => {
|
||||
const { filesList, viewAs, setViewAs } = filesStore;
|
||||
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
|
||||
return {
|
||||
filesList,
|
||||
viewAs,
|
||||
|
@ -163,8 +163,8 @@ const Table = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ filesStore, infoPanelStore, auth }) => {
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
export default inject(({ filesStore, auth }) => {
|
||||
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
filesList,
|
||||
|
@ -228,14 +228,8 @@ class FilesTableHeader extends React.Component {
|
||||
}
|
||||
|
||||
export default inject(
|
||||
({
|
||||
auth,
|
||||
filesStore,
|
||||
selectedFolderStore,
|
||||
treeFoldersStore,
|
||||
infoPanelStore,
|
||||
}) => {
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
({ auth, filesStore, selectedFolderStore, treeFoldersStore }) => {
|
||||
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
isHeaderChecked,
|
||||
|
@ -62,10 +62,15 @@ const StyledTableRow = styled(TableRow)`
|
||||
.table-container_file-name-cell {
|
||||
margin-left: -24px;
|
||||
padding-left: 24px;
|
||||
z-index: 1;
|
||||
}
|
||||
.table-container_row-context-menu-wrapper {
|
||||
margin-right: -20px;
|
||||
padding-right: 18px;
|
||||
|
||||
position: relative !important;
|
||||
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
`}
|
||||
|
@ -351,13 +351,7 @@ const SectionFilterContent = ({
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({
|
||||
auth,
|
||||
filesStore,
|
||||
treeFoldersStore,
|
||||
selectedFolderStore,
|
||||
infoPanelStore,
|
||||
}) => {
|
||||
({ auth, filesStore, treeFoldersStore, selectedFolderStore }) => {
|
||||
const {
|
||||
fetchFiles,
|
||||
filter,
|
||||
@ -382,7 +376,7 @@ export default inject(
|
||||
authorType) &&
|
||||
!(treeFoldersStore.isPrivacyFolder && isMobile);
|
||||
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
const { isVisible: infoPanelVisible } = auth.infoPanelStore;
|
||||
|
||||
return {
|
||||
customNames,
|
||||
|
@ -442,7 +442,6 @@ export default inject(
|
||||
treeFoldersStore,
|
||||
filesActionsStore,
|
||||
settingsStore,
|
||||
infoPanelStore,
|
||||
}) => {
|
||||
const {
|
||||
setSelected,
|
||||
@ -483,7 +482,7 @@ export default inject(
|
||||
backToParentFolder,
|
||||
} = filesActionsStore;
|
||||
|
||||
const { toggleIsVisible, isVisible } = infoPanelStore;
|
||||
const { toggleIsVisible, isVisible } = auth.infoPanelStore;
|
||||
|
||||
return {
|
||||
showText: auth.settingsStore.showText,
|
||||
|
@ -205,9 +205,24 @@ class PureHome extends React.Component {
|
||||
};
|
||||
|
||||
onDrop = (files, uploadToFolder) => {
|
||||
const { t, startUpload, setDragging, dragging } = this.props;
|
||||
const {
|
||||
t,
|
||||
startUpload,
|
||||
setDragging,
|
||||
dragging,
|
||||
uploadEmptyFolders,
|
||||
} = this.props;
|
||||
dragging && setDragging(false);
|
||||
startUpload(files, uploadToFolder, t);
|
||||
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
|
||||
|
||||
if (emptyFolders.length > 0) {
|
||||
uploadEmptyFolders(emptyFolders, uploadToFolder).then(() => {
|
||||
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
|
||||
if (onlyFiles.length > 0) startUpload(onlyFiles, uploadToFolder, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
};
|
||||
|
||||
showOperationToast = (type, qty, title) => {
|
||||
@ -395,6 +410,7 @@ export default inject(
|
||||
treeFoldersStore,
|
||||
mediaViewerDataStore,
|
||||
settingsStore,
|
||||
filesActionsStore,
|
||||
}) => {
|
||||
const {
|
||||
secondaryProgressDataStore,
|
||||
@ -453,6 +469,8 @@ export default inject(
|
||||
converted,
|
||||
} = uploadDataStore;
|
||||
|
||||
const { uploadEmptyFolders } = filesActionsStore;
|
||||
|
||||
const selectionLength = isProgressFinished ? selection.length : null;
|
||||
const selectionTitle = isProgressFinished
|
||||
? filesStore.selectionTitle
|
||||
@ -511,6 +529,7 @@ export default inject(
|
||||
setUploadPanelVisible,
|
||||
setSelections,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
isHeaderVisible: auth.settingsStore.isHeaderVisible,
|
||||
setHeaderVisible: auth.settingsStore.setHeaderVisible,
|
||||
personal: auth.settingsStore.personal,
|
||||
|
@ -21,7 +21,6 @@ class ContextOptionsStore {
|
||||
uploadDataStore;
|
||||
versionHistoryStore;
|
||||
settingsStore;
|
||||
infoPanelStore;
|
||||
filesSettingsStore;
|
||||
|
||||
constructor(
|
||||
@ -33,8 +32,7 @@ class ContextOptionsStore {
|
||||
treeFoldersStore,
|
||||
uploadDataStore,
|
||||
versionHistoryStore,
|
||||
settingsStore,
|
||||
infoPanelStore
|
||||
settingsStore
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
this.authStore = authStore;
|
||||
@ -46,7 +44,6 @@ class ContextOptionsStore {
|
||||
this.uploadDataStore = uploadDataStore;
|
||||
this.versionHistoryStore = versionHistoryStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
}
|
||||
|
||||
onOpenFolder = (item) => {
|
||||
@ -338,7 +335,7 @@ class ContextOptionsStore {
|
||||
};
|
||||
|
||||
onShowInfoPanel = () => {
|
||||
const { setIsVisible } = this.infoPanelStore;
|
||||
const { setIsVisible } = this.authStore.infoPanelStore;
|
||||
setIsVisible(true);
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
markAsRead,
|
||||
removeFiles,
|
||||
removeShareFiles,
|
||||
createFolder,
|
||||
} from "@appserver/common/api/files";
|
||||
import {
|
||||
ConflictResolveType,
|
||||
@ -34,7 +35,6 @@ class FilesActionStore {
|
||||
settingsStore;
|
||||
dialogsStore;
|
||||
mediaViewerDataStore;
|
||||
infoPanelStore;
|
||||
|
||||
constructor(
|
||||
authStore,
|
||||
@ -44,8 +44,7 @@ class FilesActionStore {
|
||||
selectedFolderStore,
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
mediaViewerDataStore,
|
||||
infoPanelStore
|
||||
mediaViewerDataStore
|
||||
) {
|
||||
makeAutoObservable(this);
|
||||
this.authStore = authStore;
|
||||
@ -55,7 +54,6 @@ class FilesActionStore {
|
||||
this.selectedFolderStore = selectedFolderStore;
|
||||
this.settingsStore = settingsStore;
|
||||
this.dialogsStore = dialogsStore;
|
||||
this.infoPanelStore = infoPanelStore;
|
||||
this.mediaViewerDataStore = mediaViewerDataStore;
|
||||
}
|
||||
|
||||
@ -108,6 +106,76 @@ class FilesActionStore {
|
||||
});
|
||||
};
|
||||
|
||||
convertToTree = (folders) => {
|
||||
let result = [];
|
||||
let level = { result };
|
||||
try {
|
||||
folders.forEach((folder) => {
|
||||
folder.path
|
||||
.split("/")
|
||||
.filter((name) => name !== "")
|
||||
.reduce((r, name, i, a) => {
|
||||
if (!r[name]) {
|
||||
r[name] = { result: [] };
|
||||
r.result.push({ name, children: r[name].result });
|
||||
}
|
||||
|
||||
return r[name];
|
||||
}, level);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("convertToTree", e);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
createFolderTree = async (treeList, parentFolderId) => {
|
||||
if (!treeList || !treeList.length) return;
|
||||
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
const treeNode = treeList[i];
|
||||
|
||||
// console.log(
|
||||
// `createFolderTree parent id = ${parentFolderId} name '${treeNode.name}': `,
|
||||
// treeNode.children
|
||||
// );
|
||||
|
||||
const folder = await createFolder(parentFolderId, treeNode.name);
|
||||
const parentId = folder.id;
|
||||
|
||||
if (treeNode.children.length == 0) continue;
|
||||
|
||||
await this.createFolderTree(treeNode.children, parentId);
|
||||
}
|
||||
};
|
||||
|
||||
uploadEmptyFolders = async (emptyFolders, folderId) => {
|
||||
//console.log("uploadEmptyFolders", emptyFolders, folderId);
|
||||
|
||||
const { secondaryProgressDataStore } = this.uploadDataStore;
|
||||
const {
|
||||
setSecondaryProgressBarData,
|
||||
clearSecondaryProgressData,
|
||||
} = secondaryProgressDataStore;
|
||||
|
||||
const toFolderId = folderId ? folderId : this.selectedFolderStore.id;
|
||||
|
||||
setSecondaryProgressBarData({
|
||||
icon: "file",
|
||||
visible: true,
|
||||
percent: 0,
|
||||
label: "",
|
||||
alert: false,
|
||||
});
|
||||
|
||||
const tree = this.convertToTree(emptyFolders);
|
||||
await this.createFolderTree(tree, toFolderId);
|
||||
|
||||
this.updateCurrentFolder(null, [folderId]);
|
||||
|
||||
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
|
||||
};
|
||||
|
||||
deleteAction = async (
|
||||
translations,
|
||||
newSelection = null,
|
||||
@ -854,8 +922,6 @@ class FilesActionStore {
|
||||
setDeleteDialogVisible,
|
||||
} = this.dialogsStore;
|
||||
|
||||
const { toggleIsVisible } = this.infoPanelStore;
|
||||
|
||||
switch (option) {
|
||||
case "share":
|
||||
if (!this.isAvailableOption("share")) return null;
|
||||
|
@ -906,7 +906,7 @@ class FilesStore {
|
||||
"separator2",
|
||||
"delete",
|
||||
]);
|
||||
if (isThirdPartyFolder) {
|
||||
if (isThirdPartyItem) {
|
||||
fileOptions = this.removeOptions(fileOptions, ["rename"]);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import selectFolderDialogStore from "./SelectFolderDialogStore";
|
||||
import ContextOptionsStore from "./ContextOptionsStore";
|
||||
import HotkeyStore from "./HotkeyStore";
|
||||
import store from "studio/store";
|
||||
import InfoPanelStore from "./InfoPanelStore";
|
||||
import selectFileDialogStore from "./SelectFileDialogStore";
|
||||
|
||||
const selectedFolderStore = new SelectedFolderStore(store.auth.settingsStore);
|
||||
@ -56,8 +55,6 @@ const uploadDataStore = new UploadDataStore(
|
||||
settingsStore
|
||||
);
|
||||
|
||||
const infoPanelStore = new InfoPanelStore();
|
||||
|
||||
const filesActionsStore = new FilesActionsStore(
|
||||
store.auth,
|
||||
uploadDataStore,
|
||||
@ -66,8 +63,7 @@ const filesActionsStore = new FilesActionsStore(
|
||||
selectedFolderStore,
|
||||
settingsStore,
|
||||
dialogsStore,
|
||||
mediaViewerDataStore,
|
||||
infoPanelStore
|
||||
mediaViewerDataStore
|
||||
);
|
||||
|
||||
const versionHistoryStore = new VersionHistoryStore(filesStore);
|
||||
@ -80,8 +76,7 @@ const contextOptionsStore = new ContextOptionsStore(
|
||||
treeFoldersStore,
|
||||
uploadDataStore,
|
||||
versionHistoryStore,
|
||||
settingsStore,
|
||||
infoPanelStore
|
||||
settingsStore
|
||||
);
|
||||
|
||||
const hotkeyStore = new HotkeyStore(
|
||||
@ -106,7 +101,6 @@ const stores = {
|
||||
selectFolderDialogStore,
|
||||
contextOptionsStore,
|
||||
hotkeyStore,
|
||||
infoPanelStore,
|
||||
selectFileDialogStore,
|
||||
};
|
||||
|
||||
|
@ -22,5 +22,5 @@
|
||||
"Subscriptions": "Abunəliklər",
|
||||
"SystemTheme": "Sistem temasından istifadə edin",
|
||||
"TfaLoginSettings": "Daxilolma sazlamaları",
|
||||
"TwoFactorDescription": "Bütün istifadəçilər üçün ikili audentifikasiya (kod generasiyası ilə) inzibatçı tərəfindən yandırıldı."
|
||||
"TwoFactorDescription": "Bütün istifadəçilər üçün ikili autentifikasiya (kod generasiyası ilə) inzibatçı tərəfindən yandırıldı."
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"ResetApplicationDescription": "Audentifikasiya üçün tətbiq sıfırlanacaq.",
|
||||
"ResetApplicationDescription": "Autentifikasiya üçün tətbiq sıfırlanacaq.",
|
||||
"ResetApplicationTitle": "Tətbiq konfiqurasiyasını sıfırla"
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"Error403Text": "Təəssüf ki, giriş rədd edilmişdir.",
|
||||
"Error404Text": "Təəssüf ki, resurs tapıla bilmir.",
|
||||
"ErrorEmptyResponse": "Boş cavab",
|
||||
"ErrorInvalidHeader": "Yalnış e-poçt ünvanı və ya vaxtı bitmiş keçid",
|
||||
"ErrorInvalidHeader": "Yanlış e-poçt ünvanı və ya vaxtı bitmiş keçid",
|
||||
"ErrorInvalidText": "10 saniyədə <1>giriş səhifəsinə</1> yönləndiriləcəksiniz",
|
||||
"ErrorOfflineText": "İnternet bağlantısı tapılmadı."
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
"ChangeLogoButton": "Loqonu dəyişin",
|
||||
"ChangeOwner": "Portal sahibini dəyişin",
|
||||
"Characters": "İşarələrin {{length}}",
|
||||
"ChooseOwner": "Sahibi seçinr",
|
||||
"ChooseOwner": "Sahibi seçin",
|
||||
"ClearBackupList": "Bütün ehtiyat nüsxələri silin",
|
||||
"CompanyNameForCanvasLogo": "Şirkət adı",
|
||||
"ConfirmEmailSended": "Təsdiqləmə e-məktubu {{ownerName}} göndərilmişdir",
|
||||
|
@ -116,8 +116,12 @@ const Layout = (props) => {
|
||||
// height = window.screen.availHeight - correctorTabletSafari;
|
||||
// }
|
||||
// }
|
||||
const isSmartBanner =
|
||||
document.getElementsByClassName("smartbanner-container")[0].nodeName ===
|
||||
"DIV";
|
||||
const bannerHeight = isSmartBanner ? 80 : 0;
|
||||
|
||||
let vh = (height - 48) * 0.01;
|
||||
let vh = (height - 48 - bannerHeight) * 0.01;
|
||||
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
||||
|
||||
setContentHeight(height);
|
||||
|
@ -15,7 +15,7 @@
|
||||
line-height: 80px;
|
||||
font-family: Helvetica Neue, sans-serif;
|
||||
background: #f4f4f4;
|
||||
z-index: 9998;
|
||||
z-index: 100;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
overflow: hidden;
|
||||
-webkit-text-size-adjust: none;
|
||||
|
@ -15,7 +15,7 @@
|
||||
"PasswordRecoveryTitle": "Parolun bərpa edilməsi",
|
||||
"Register": "Qeydiyyatdan keç",
|
||||
"RegisterSendButton": "Sorğunu göndər",
|
||||
"RegisterTextBodyAfterDomainsList": "Qeydiyyatdan keçmək üçün, elektron poçt ünvanınıı daxil edin və Sorğunu göndər düyməsinə basın.",
|
||||
"RegisterTextBodyAfterDomainsList": "Qeydiyyatdan keçmək üçün, elektron poçt ünvanını daxil edin və Sorğunu göndər düyməsinə basın.",
|
||||
"RegisterTextBodyBeforeDomainsList": "Elektron poçtu olan istifadəçilər üçün qeydiyyat mümkündür",
|
||||
"RegisterTitle": "Sorğunun qeydiyyatı",
|
||||
"RegistrationEmail": "Sizin qeydiyyat elektron poçtunuz",
|
||||
|
@ -16713,7 +16713,7 @@ react-draggable@^4.4.3:
|
||||
clsx "^1.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-dropzone@^11.2.4:
|
||||
react-dropzone@^11.4.2:
|
||||
version "11.7.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.7.1.tgz#3851bb75b26af0bf1b17ce1449fd980e643b9356"
|
||||
integrity sha512-zxCMwhfPy1olUEbw3FLNPLhAm/HnaYH5aELIEglRbqabizKAdHs0h+WuyOpmA+v1JXn0++fpQDdNfUagWt5hJQ==
|
||||
|
Loading…
Reference in New Issue
Block a user