Merge branch 'hotfix/v2.6.1' into bugfix/Bug69601
This commit is contained in:
commit
df02095c37
@ -117,6 +117,7 @@
|
||||
"OpenLocation": "Open location",
|
||||
"PasswordAccess": "Password access",
|
||||
"PasswordLink": "Add a password to protect your link.",
|
||||
"PasswordProtectedFiles": "Please <0>enter a password</0> for the protected files to continue",
|
||||
"PasswordSuccessfullyCopied": "Password successfully copied",
|
||||
"Pin": "Pin",
|
||||
"PinToTop": "Pin to top",
|
||||
|
@ -62,21 +62,14 @@ export default function withFileActions(WrappedFileItem) {
|
||||
};
|
||||
|
||||
onDropZoneUpload = (files, uploadToFolder) => {
|
||||
const { t, dragging, setDragging, startUpload, uploadEmptyFolders } =
|
||||
const { t, dragging, setDragging, startUpload, createFoldersTree } =
|
||||
this.props;
|
||||
|
||||
dragging && setDragging(false);
|
||||
|
||||
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);
|
||||
createFoldersTree(files, uploadToFolder).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
};
|
||||
|
||||
onDrop = (items) => {
|
||||
@ -371,7 +364,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
onSelectItem,
|
||||
//setNewBadgeCount,
|
||||
openFileAction,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
} = filesActionsStore;
|
||||
const { setSharingPanelVisible } = dialogsStore;
|
||||
const {
|
||||
@ -475,7 +468,7 @@ export default function withFileActions(WrappedFileItem) {
|
||||
dragging,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
draggable,
|
||||
setTooltipPosition,
|
||||
setStartDrag,
|
||||
|
@ -68,7 +68,7 @@ const Item = ({
|
||||
onBadgeClick,
|
||||
showDragItems,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
setDragging,
|
||||
showBadge,
|
||||
labelBadge,
|
||||
@ -86,18 +86,12 @@ const Item = ({
|
||||
const onDropZoneUpload = React.useCallback(
|
||||
(files, uploadToFolder) => {
|
||||
dragging && setDragging(false);
|
||||
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);
|
||||
createFoldersTree(files, uploadToFolder).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
},
|
||||
[t, dragging, setDragging, startUpload, uploadEmptyFolders],
|
||||
[t, dragging, setDragging, startUpload, createFoldersTree],
|
||||
);
|
||||
|
||||
const onDrop = React.useCallback(
|
||||
@ -193,7 +187,7 @@ const Items = ({
|
||||
dragging,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
isVisitor,
|
||||
isCollaborator,
|
||||
isAdmin,
|
||||
@ -326,7 +320,7 @@ const Items = ({
|
||||
t={t}
|
||||
setDragging={setDragging}
|
||||
startUpload={startUpload}
|
||||
uploadEmptyFolders={uploadEmptyFolders}
|
||||
createFoldersTree={createFoldersTree}
|
||||
item={item}
|
||||
setBufferSelection={setBufferSelection}
|
||||
dragging={dragging}
|
||||
@ -388,7 +382,7 @@ const Items = ({
|
||||
showText,
|
||||
setDragging,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
trashIsEmpty,
|
||||
isAdmin,
|
||||
isVisitor,
|
||||
@ -449,7 +443,7 @@ export default inject(
|
||||
const { id, access: folderAccess } = selectedFolderStore;
|
||||
const {
|
||||
moveDragItems,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
deleteAction,
|
||||
emptyTrashInProgress,
|
||||
} = filesActionsStore;
|
||||
@ -478,7 +472,7 @@ export default inject(
|
||||
setBufferSelection,
|
||||
deleteAction,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
setEmptyTrashDialogVisible,
|
||||
trashIsEmpty,
|
||||
|
||||
|
@ -70,6 +70,7 @@ import { resendInvitesAgain } from "@docspace/shared/api/people";
|
||||
import { getCorrectFourValuesStyle } from "@docspace/shared/utils";
|
||||
import { ArticleButtonLoader } from "@docspace/shared/skeletons/article";
|
||||
import { isMobile, isTablet } from "react-device-detect";
|
||||
import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event";
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
font-weight: 700;
|
||||
@ -180,6 +181,7 @@ const ArticleMainButtonContent = (props) => {
|
||||
|
||||
parentRoomType,
|
||||
isFolder,
|
||||
createFoldersTree,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -239,8 +241,12 @@ const ArticleMainButtonContent = (props) => {
|
||||
);
|
||||
|
||||
const onFileChange = React.useCallback(
|
||||
(e) => {
|
||||
startUpload(e.target.files, null, t);
|
||||
async (e) => {
|
||||
const files = await getFilesFromEvent(e);
|
||||
|
||||
createFoldersTree(files).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
},
|
||||
[startUpload, t],
|
||||
);
|
||||
@ -249,7 +255,7 @@ const ArticleMainButtonContent = (props) => {
|
||||
if (isPrivacy) {
|
||||
encryptionUploadDialog((encryptedFile, encrypted) => {
|
||||
encryptedFile.encrypted = encrypted;
|
||||
startUpload([encryptedFile], null, t);
|
||||
startUpload([encryptedFile], null, t); // TODO: createFoldersTree
|
||||
});
|
||||
} else {
|
||||
inputFilesElement.current.click();
|
||||
@ -901,6 +907,7 @@ export default inject(
|
||||
versionHistoryStore,
|
||||
userStore,
|
||||
currentTariffStatusStore,
|
||||
filesActionsStore,
|
||||
}) => {
|
||||
const { showArticleLoader } = clientLoadingStore;
|
||||
const { mainButtonMobileVisible } = filesStore;
|
||||
@ -945,6 +952,8 @@ export default inject(
|
||||
|
||||
const { frameConfig, isFrame } = settingsStore;
|
||||
|
||||
const { createFoldersTree } = filesActionsStore;
|
||||
|
||||
return {
|
||||
isGracePeriod,
|
||||
setInviteUsersWarningDialogVisible,
|
||||
@ -997,6 +1006,7 @@ export default inject(
|
||||
isFolder,
|
||||
selectFileFormRoomDialogVisible,
|
||||
setSelectFileFormRoomDialogVisible,
|
||||
createFoldersTree,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -38,6 +38,7 @@ import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import RoomsFilter from "@docspace/shared/api/rooms/filter";
|
||||
|
||||
import { RoomSearchArea } from "@docspace/shared/enums";
|
||||
import { frameCallEvent } from "@docspace/shared/utils/common";
|
||||
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
|
||||
import { CategoryType } from "SRC_DIR/helpers/constants";
|
||||
|
||||
@ -60,6 +61,8 @@ const RoomNoAccessContainer = (props) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
React.useEffect(() => {
|
||||
frameCallEvent({ event: "onNoAccess" });
|
||||
|
||||
const timer = setTimeout(onGoToShared, 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
@ -88,7 +88,7 @@ const ExternalLinks = ({
|
||||
copyLink(link.shareLink);
|
||||
}
|
||||
} else {
|
||||
!externalLinksVisible ? editLink() : disableLink();
|
||||
!externalLinksVisible ? await editLink() : await disableLink();
|
||||
}
|
||||
onChangeExternalLinksVisible(!externalLinksVisible);
|
||||
} catch (error) {
|
||||
@ -98,9 +98,10 @@ const ExternalLinks = ({
|
||||
}
|
||||
};
|
||||
|
||||
const disableLink = () => {
|
||||
setInvitationLinks(roomId, "Invite", 0, shareLinks[0].id);
|
||||
setShareLinks([]);
|
||||
const disableLink = async () => {
|
||||
shareLinks?.length &&
|
||||
(await setInvitationLinks(roomId, "Invite", 0, shareLinks[0].id));
|
||||
return setShareLinks([]);
|
||||
};
|
||||
|
||||
const editLink = async () => {
|
||||
@ -120,7 +121,7 @@ const ExternalLinks = ({
|
||||
|
||||
copyLink(shareLink);
|
||||
setShareLinks([activeLink]);
|
||||
setActiveLink(activeLink);
|
||||
return setActiveLink(activeLink);
|
||||
};
|
||||
|
||||
const onSelectAccess = async (access) => {
|
||||
|
@ -54,7 +54,10 @@ export const GreetingContainer = styled.div`
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
p {
|
||||
.invitation-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -65,15 +68,13 @@ export const GreetingContainer = styled.div`
|
||||
|
||||
.portal-logo {
|
||||
width: 100%;
|
||||
max-width: 386px;
|
||||
height: 44px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 16px;
|
||||
height: 26.56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.injected-svg {
|
||||
height: 26.56px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -485,7 +485,7 @@ const CreateUserForm = (props) => {
|
||||
<PortalLogo className="portal-logo" />
|
||||
{linkData.type === "LinkInvite" && (
|
||||
<div className="tooltip">
|
||||
<Text fontSize="16px">
|
||||
<Text fontSize="16px" as="div" className="invitation-text">
|
||||
{roomName ? (
|
||||
<Trans
|
||||
t={t}
|
||||
|
@ -97,6 +97,12 @@ const StyledForm = styled(Box)`
|
||||
.set-app-description {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
|
||||
.portal-logo {
|
||||
margin: 0 auto;
|
||||
max-width: 386px;
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
.set-app-title {
|
||||
|
@ -52,7 +52,7 @@ const useFiles = ({
|
||||
dragging,
|
||||
setDragging,
|
||||
disableDrag,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
startUpload,
|
||||
|
||||
fetchFiles,
|
||||
@ -118,16 +118,9 @@ const useFiles = ({
|
||||
|
||||
if (disableDrag) return;
|
||||
|
||||
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);
|
||||
createFoldersTree(files, uploadToFolder).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, uploadToFolder, t);
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
|
@ -264,8 +264,8 @@ const StyledProperties = styled.div`
|
||||
grid-template-columns: 120px 1fr;
|
||||
grid-column-gap: 24px;
|
||||
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-align: baseline;
|
||||
align-items: baseline;
|
||||
|
||||
.property-title {
|
||||
font-size: 13px;
|
||||
|
@ -138,15 +138,8 @@ class InsideGroupTableHeader extends React.Component {
|
||||
newFilter.sortBy = sortBy;
|
||||
|
||||
if (sortBy === "AZ") {
|
||||
if (
|
||||
newFilter.sortBy !== "lastname" &&
|
||||
newFilter.sortBy !== "firstname"
|
||||
) {
|
||||
newFilter.sortBy = "firstname";
|
||||
} else if (newFilter.sortBy === "lastname") {
|
||||
newFilter.sortBy = "firstname";
|
||||
} else {
|
||||
newFilter.sortBy = "lastname";
|
||||
if (newFilter.sortBy !== "displayname") {
|
||||
newFilter.sortBy = "displayname";
|
||||
}
|
||||
newFilter.sortOrder =
|
||||
newFilter.sortOrder === "ascending" ? "descending" : "ascending";
|
||||
@ -176,10 +169,7 @@ class InsideGroupTableHeader extends React.Component {
|
||||
} = this.props;
|
||||
const { sortOrder } = filter;
|
||||
|
||||
const sortBy =
|
||||
filter.sortBy === "firstname" || filter.sortBy === "lastname"
|
||||
? "AZ"
|
||||
: filter.sortBy;
|
||||
const sortBy = filter.sortBy === "displayname" ? "AZ" : filter.sortBy;
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
|
@ -143,7 +143,7 @@ class PeopleTableHeader extends React.Component {
|
||||
|
||||
if (
|
||||
newFilter.sortBy === sortBy ||
|
||||
(sortBy === "AZ" && newFilter.sortBy === "firstname")
|
||||
(sortBy === "AZ" && newFilter.sortBy === "displayname")
|
||||
) {
|
||||
newFilter.sortOrder =
|
||||
newFilter.sortOrder === "ascending" ? "descending" : "ascending";
|
||||
@ -151,7 +151,7 @@ class PeopleTableHeader extends React.Component {
|
||||
newFilter.sortBy = sortBy;
|
||||
|
||||
if (sortBy === "AZ") {
|
||||
newFilter.sortBy = "firstname";
|
||||
newFilter.sortBy = "displayname";
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,10 +178,7 @@ class PeopleTableHeader extends React.Component {
|
||||
} = this.props;
|
||||
const { sortOrder } = filter;
|
||||
|
||||
const sortBy =
|
||||
filter.sortBy === "firstname" || filter.sortBy === "lastname"
|
||||
? "AZ"
|
||||
: filter.sortBy;
|
||||
const sortBy = filter.sortBy === "displayname" ? "AZ" : filter.sortBy;
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
|
@ -1961,16 +1961,9 @@ const SectionFilterContent = ({
|
||||
const options = [];
|
||||
|
||||
const firstName = {
|
||||
id: "sort-by_first-name",
|
||||
key: "firstname",
|
||||
label: t("Common:FirstName"),
|
||||
default: true,
|
||||
};
|
||||
|
||||
const lastName = {
|
||||
id: "sort-by_last-name",
|
||||
key: "lastname",
|
||||
label: t("Common:LastName"),
|
||||
id: "sort-by_displayname",
|
||||
key: "displayname",
|
||||
label: t("Common:Name"),
|
||||
default: true,
|
||||
};
|
||||
|
||||
@ -2012,7 +2005,7 @@ const SectionFilterContent = ({
|
||||
hideableColumns.Storage = storage;
|
||||
}
|
||||
|
||||
options.push(firstName, lastName, type, department, email);
|
||||
options.push(firstName, type, department, email);
|
||||
if (showStorageInfo) options.push(storage);
|
||||
|
||||
return options;
|
||||
|
@ -50,6 +50,7 @@ import {
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
import TariffBar from "SRC_DIR/components/TariffBar";
|
||||
import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-files-from-event";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
@ -225,6 +226,7 @@ const SectionHeaderContent = (props) => {
|
||||
getHeaderOptions,
|
||||
setBufferSelection,
|
||||
setGroupsBufferSelection,
|
||||
createFoldersTree,
|
||||
} = props;
|
||||
|
||||
const location = useLocation();
|
||||
@ -239,8 +241,12 @@ const SectionHeaderContent = (props) => {
|
||||
const isSettingsPage = location.pathname.includes("/settings");
|
||||
|
||||
const onFileChange = React.useCallback(
|
||||
(e) => {
|
||||
startUpload(e.target.files, null, t);
|
||||
async (e) => {
|
||||
const files = await getFilesFromEvent(e);
|
||||
|
||||
createFoldersTree(files).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
},
|
||||
[startUpload, t],
|
||||
);
|
||||
@ -639,6 +645,7 @@ export default inject(
|
||||
moveToRoomsPage,
|
||||
onClickBack,
|
||||
moveToPublicRoom,
|
||||
createFoldersTree,
|
||||
} = filesActionsStore;
|
||||
|
||||
const { setIsVisible, isVisible } = infoPanelStore;
|
||||
@ -802,6 +809,7 @@ export default inject(
|
||||
getHeaderOptions,
|
||||
setBufferSelection,
|
||||
setGroupsBufferSelection,
|
||||
createFoldersTree,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -82,7 +82,7 @@ const PureHome = (props) => {
|
||||
startUpload,
|
||||
setDragging,
|
||||
dragging,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
disableDrag,
|
||||
uploaded,
|
||||
converted,
|
||||
@ -182,7 +182,7 @@ const PureHome = (props) => {
|
||||
dragging,
|
||||
setDragging,
|
||||
disableDrag,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
startUpload,
|
||||
fetchFiles,
|
||||
fetchRooms,
|
||||
@ -543,7 +543,7 @@ export default inject(
|
||||
const { setUploadPanelVisible, startUpload, uploaded, converted } =
|
||||
uploadDataStore;
|
||||
|
||||
const { uploadEmptyFolders, onClickBack } = filesActionsStore;
|
||||
const { createFoldersTree, onClickBack } = filesActionsStore;
|
||||
|
||||
const selectionLength = isProgressFinished ? selection.length : null;
|
||||
const selectionTitle = isProgressFinished
|
||||
@ -635,7 +635,7 @@ export default inject(
|
||||
|
||||
setUploadPanelVisible,
|
||||
startUpload,
|
||||
uploadEmptyFolders,
|
||||
createFoldersTree,
|
||||
|
||||
setToPreviewFile,
|
||||
setIsPreview,
|
||||
|
@ -130,6 +130,7 @@ const Manager = (props) => {
|
||||
);
|
||||
const [selectedColumns, setSelectedColumns] = useState([
|
||||
{ key: "Name", label: t("Common:Name") },
|
||||
{ key: "Size", label: t("Common:Size") },
|
||||
{ key: "Type", label: t("Common:Type") },
|
||||
{ key: "Tags", label: t("Common:Tags") },
|
||||
]);
|
||||
|
@ -125,6 +125,17 @@ class EditGroupStore {
|
||||
|
||||
const addedIds = Array.from(this.addedMembersMap.keys());
|
||||
const removedIds = Array.from(this.removedMembersMap.keys());
|
||||
const oldManager = this.group.manager;
|
||||
const oldManagerRemovedButRemainsAsMember =
|
||||
oldManager &&
|
||||
oldManager.id !== this.manager?.id &&
|
||||
!this.removedMembersMap.has(oldManager.id);
|
||||
|
||||
// Requires when new group is without manager and old manager moved to members. updateGroup api method doesn't provide possibility to do it without setting new manager
|
||||
if (this.manager === null && oldManagerRemovedButRemainsAsMember) {
|
||||
await api.groups.removeGroupMembers(this.group.id, [oldManager.id]);
|
||||
addedIds.push(oldManager.id);
|
||||
}
|
||||
|
||||
await updateGroup(
|
||||
this.group?.id,
|
||||
|
@ -229,13 +229,17 @@ class FilesActionStore {
|
||||
let level = { result };
|
||||
try {
|
||||
folders.forEach((folder) => {
|
||||
folder.path
|
||||
.split("/")
|
||||
.filter((name) => name !== "")
|
||||
.reduce((r, name, i, a) => {
|
||||
const folderPath = folder.path.split("/").filter((name) => name !== "");
|
||||
|
||||
folderPath.reduce((r, name, i, a) => {
|
||||
if (!r[name]) {
|
||||
r[name] = { result: [] };
|
||||
r.result.push({ name, children: r[name].result });
|
||||
r.result.push({
|
||||
name,
|
||||
children: r[name].result,
|
||||
isFile: folderPath.length - 1 === i && !folder.isEmptyDirectory,
|
||||
file: folder,
|
||||
});
|
||||
}
|
||||
|
||||
return r[name];
|
||||
@ -247,52 +251,67 @@ class FilesActionStore {
|
||||
return result;
|
||||
};
|
||||
|
||||
createFolderTree = async (treeList, parentFolderId) => {
|
||||
createFolderTree = async (treeList, parentFolderId, filesList) => {
|
||||
if (!treeList || !treeList.length) return;
|
||||
|
||||
for (let i = 0; i < treeList.length; i++) {
|
||||
const treeNode = treeList[i];
|
||||
const isFile = treeList[i].isFile;
|
||||
|
||||
// console.log(
|
||||
// `createFolderTree parent id = ${parentFolderId} name '${treeNode.name}': `,
|
||||
// treeNode.children
|
||||
// );
|
||||
|
||||
if (isFile) {
|
||||
treeList[i].file.parentFolderId = parentFolderId;
|
||||
filesList.push(treeList[i].file);
|
||||
continue;
|
||||
}
|
||||
|
||||
const folder = await createFolder(parentFolderId, treeNode.name);
|
||||
const parentId = folder.id;
|
||||
|
||||
if (treeNode.children.length == 0) continue;
|
||||
|
||||
await this.createFolderTree(treeNode.children, parentId);
|
||||
await this.createFolderTree(treeNode.children, parentId, filesList);
|
||||
}
|
||||
|
||||
return treeList;
|
||||
};
|
||||
|
||||
uploadEmptyFolders = async (emptyFolders, folderId) => {
|
||||
//console.log("uploadEmptyFolders", emptyFolders, folderId);
|
||||
createFoldersTree = async (files, folderId) => {
|
||||
//console.log("createFoldersTree", files, folderId);
|
||||
|
||||
const { secondaryProgressDataStore } = this.uploadDataStore;
|
||||
const { setSecondaryProgressBarData, clearSecondaryProgressData } =
|
||||
secondaryProgressDataStore;
|
||||
const { primaryProgressDataStore } = this.uploadDataStore;
|
||||
|
||||
const { setPrimaryProgressBarData, clearPrimaryProgressData } =
|
||||
primaryProgressDataStore;
|
||||
|
||||
const operationId = uniqueid("operation_");
|
||||
|
||||
const toFolderId = folderId ? folderId : this.selectedFolderStore.id;
|
||||
|
||||
setSecondaryProgressBarData({
|
||||
icon: "file",
|
||||
setPrimaryProgressBarData({
|
||||
icon: "upload",
|
||||
visible: true,
|
||||
percent: 0,
|
||||
label: "",
|
||||
alert: false,
|
||||
operationId,
|
||||
});
|
||||
|
||||
const tree = this.convertToTree(emptyFolders);
|
||||
await this.createFolderTree(tree, toFolderId);
|
||||
const tree = this.convertToTree(files);
|
||||
|
||||
const filesList = [];
|
||||
await this.createFolderTree(tree, toFolderId, filesList);
|
||||
|
||||
this.updateCurrentFolder(null, [folderId], null, operationId);
|
||||
|
||||
setTimeout(() => clearSecondaryProgressData(operationId), TIMEOUT);
|
||||
if (!filesList.length) {
|
||||
setTimeout(() => clearPrimaryProgressData(), TIMEOUT);
|
||||
}
|
||||
|
||||
return filesList;
|
||||
};
|
||||
|
||||
updateFilesAfterDelete = (operationId) => {
|
||||
|
@ -683,9 +683,8 @@ class HotkeyStore {
|
||||
};
|
||||
|
||||
uploadClipboardFiles = async (t, event) => {
|
||||
const { uploadEmptyFolders } = this.filesActionsStore;
|
||||
const { createFoldersTree } = this.filesActionsStore;
|
||||
const { startUpload } = this.uploadDataStore;
|
||||
const currentFolderId = this.selectedFolderStore.id;
|
||||
|
||||
if (this.filesStore.hotkeysClipboard.length) {
|
||||
return this.moveFilesFromClipboard(t);
|
||||
@ -693,16 +692,9 @@ class HotkeyStore {
|
||||
|
||||
const files = await getFilesFromEvent(event);
|
||||
|
||||
const emptyFolders = files.filter((f) => f.isEmptyDirectory);
|
||||
|
||||
if (emptyFolders.length > 0) {
|
||||
uploadEmptyFolders(emptyFolders, currentFolderId).then(() => {
|
||||
const onlyFiles = files.filter((f) => !f.isEmptyDirectory);
|
||||
if (onlyFiles.length > 0) startUpload(onlyFiles, currentFolderId, t);
|
||||
createFoldersTree(files, uploadToFolder).then((f) => {
|
||||
if (f.length > 0) startUpload(f, null, t);
|
||||
});
|
||||
} else {
|
||||
startUpload(files, currentFolderId, t);
|
||||
}
|
||||
};
|
||||
|
||||
get countTilesInRow() {
|
||||
|
@ -489,7 +489,7 @@ class LdapFormStore {
|
||||
completed: true,
|
||||
percents: 100,
|
||||
certificateConfirmRequest: null,
|
||||
error: "",
|
||||
error: t("Common:UnexpectedError"),
|
||||
};
|
||||
}
|
||||
|
||||
@ -518,7 +518,6 @@ class LdapFormStore {
|
||||
toastr.success(t("Common:SuccessfullyCompletedOperation"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toastr.error(error);
|
||||
this.endProcess();
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ class ProfileActionsStore {
|
||||
|
||||
let bookTraining = null;
|
||||
|
||||
if (!isMobile && this.isTeamTrainingAlertAvailable) {
|
||||
if (!isMobile && this.authStore.isTeamTrainingAlertAvailable) {
|
||||
bookTraining = {
|
||||
key: "user-menu-book-training",
|
||||
icon: BookTrainingReactSvgUrl,
|
||||
|
@ -25,9 +25,11 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
import { Trans } from "react-i18next";
|
||||
import { TIMEOUT } from "@docspace/client/src/helpers/filesConstants";
|
||||
import uniqueid from "lodash/uniqueId";
|
||||
import sumBy from "lodash/sumBy";
|
||||
import uniqBy from "lodash/uniqBy";
|
||||
import { ConflictResolveType } from "@docspace/shared/enums";
|
||||
import {
|
||||
getFileInfo,
|
||||
@ -57,6 +59,8 @@ import {
|
||||
getCategoryTypeByFolderType,
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { globalColors } from "@docspace/shared/themes";
|
||||
|
||||
class UploadDataStore {
|
||||
settingsStore;
|
||||
@ -636,7 +640,7 @@ class UploadDataStore {
|
||||
|
||||
if (this.uploaded || (this.isParallel && allFilesIsUploaded)) {
|
||||
this.setConversionPercent(100);
|
||||
this.finishUploadFiles();
|
||||
this.finishUploadFiles(t);
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.converted = true;
|
||||
@ -773,7 +777,8 @@ class UploadDataStore {
|
||||
file: file,
|
||||
uniqueId: uniqueid("download_row-key_"),
|
||||
fileId: null,
|
||||
toFolderId,
|
||||
// toFolderId,
|
||||
toFolderId: file.parentFolderId,
|
||||
action: "upload",
|
||||
error: file.size ? null : t("Files:EmptyFile"),
|
||||
fileInfo: null,
|
||||
@ -1263,7 +1268,7 @@ class UploadDataStore {
|
||||
let files = this.files;
|
||||
|
||||
if (files.length === 0 || this.filesSize === 0) {
|
||||
return this.finishUploadFiles();
|
||||
return this.finishUploadFiles(t);
|
||||
}
|
||||
|
||||
const progressData = {
|
||||
@ -1310,7 +1315,7 @@ class UploadDataStore {
|
||||
}
|
||||
|
||||
if (!this.filesToConversion.length) {
|
||||
this.finishUploadFiles();
|
||||
this.finishUploadFiles(t);
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
@ -1372,7 +1377,7 @@ class UploadDataStore {
|
||||
toFolderId,
|
||||
fileName,
|
||||
fileSize,
|
||||
relativePath,
|
||||
"", // relativePath,
|
||||
file.encrypted,
|
||||
file.lastModifiedDate,
|
||||
createNewIfExist,
|
||||
@ -1512,7 +1517,7 @@ class UploadDataStore {
|
||||
|
||||
if (allFilesIsUploaded) {
|
||||
if (!this.filesToConversion.length) {
|
||||
this.finishUploadFiles();
|
||||
this.finishUploadFiles(t);
|
||||
} else {
|
||||
runInAction(() => {
|
||||
this.uploaded = true;
|
||||
@ -1542,7 +1547,7 @@ class UploadDataStore {
|
||||
});
|
||||
};
|
||||
|
||||
finishUploadFiles = () => {
|
||||
finishUploadFiles = (t) => {
|
||||
const { fetchFiles, filter } = this.filesStore;
|
||||
const { withPaging } = this.settingsStore;
|
||||
|
||||
@ -1554,7 +1559,7 @@ class UploadDataStore {
|
||||
this.asyncUploadObj = {};
|
||||
|
||||
for (let item of this.tempFiles) {
|
||||
const { uploadFiles, folderId, t } = item;
|
||||
const { uploadFiles, folderId } = item;
|
||||
this.startUpload(uploadFiles, folderId, t);
|
||||
}
|
||||
this.tempFiles = [];
|
||||
@ -1562,12 +1567,36 @@ class UploadDataStore {
|
||||
return;
|
||||
}
|
||||
|
||||
const totalErrorsCount = sumBy(this.files, (f) => {
|
||||
f.error && toastr.error(f.error);
|
||||
return f.error ? 1 : 0;
|
||||
});
|
||||
const filesWithErrors = this.files.filter((f) => f.error);
|
||||
|
||||
const totalErrorsCount = filesWithErrors.length;
|
||||
|
||||
if (totalErrorsCount > 0) {
|
||||
const uniqErrors = uniqBy(filesWithErrors, "error");
|
||||
uniqErrors.forEach((f) =>
|
||||
f.error.indexOf("password") > -1
|
||||
? toastr.warning(
|
||||
<Trans
|
||||
i18nKey="Files:PasswordProtectedFiles"
|
||||
t={t}
|
||||
components={[
|
||||
<Link
|
||||
isHovered
|
||||
color={globalColors.link}
|
||||
onClick={() => {
|
||||
toastr.clear();
|
||||
this.setUploadPanelVisible(true);
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
/>,
|
||||
null,
|
||||
60000,
|
||||
true,
|
||||
)
|
||||
: toastr.error(f.error),
|
||||
);
|
||||
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarShowError(true); // for empty file
|
||||
this.primaryProgressDataStore.setPrimaryProgressBarErrors(
|
||||
totalErrorsCount,
|
||||
|
@ -146,6 +146,14 @@ export const addGroupMembers = (groupId: string, members: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const removeGroupMembers = (groupId: string, membersIds: string[]) => {
|
||||
return request({
|
||||
method: "delete",
|
||||
url: `/group/${groupId}/members`,
|
||||
data: { id: groupId, members: membersIds },
|
||||
}) as Promise<TGroup>;
|
||||
};
|
||||
|
||||
// * Delete
|
||||
|
||||
export const deleteGroup = (groupId: string) => {
|
||||
|
@ -29,7 +29,7 @@ import { getObjectByLocation, toUrlParams } from "../../utils/common";
|
||||
const DEFAULT_PAGE = 0;
|
||||
const DEFAULT_PAGE_COUNT = 25;
|
||||
const DEFAULT_TOTAL = 0;
|
||||
const DEFAULT_SORT_BY = "firstname";
|
||||
const DEFAULT_SORT_BY = "displayname";
|
||||
const DEFAULT_SORT_ORDER = "ascending";
|
||||
const DEFAULT_EMPLOYEE_STATUS = null;
|
||||
const DEFAULT_ACTIVATION_STATUS = null;
|
||||
|
@ -29,7 +29,7 @@ import moment from "moment";
|
||||
export const getCalendarYears = (observedDate: moment.Moment) => {
|
||||
const years = [];
|
||||
const selectedYear = observedDate.year();
|
||||
const firstYear = selectedYear - (selectedYear % 10) - 1;
|
||||
const firstYear = selectedYear - 1;
|
||||
|
||||
for (let i = firstYear; i <= firstYear + 15; i += 1) {
|
||||
years.push(moment(i, "YYYY").format("YYYY"));
|
||||
|
@ -40,7 +40,7 @@ const StyledErrorContainer = styled.div<{ isEditor: boolean }>`
|
||||
css`
|
||||
position: absolute;
|
||||
`}
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
@ -996,6 +996,7 @@ export const ImageViewer = ({
|
||||
onDoubleClick={handleDoubleTapOrClick}
|
||||
onLoad={imageLoaded}
|
||||
onError={onError}
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
/>
|
||||
</ImageWrapper>
|
||||
</ImageViewerContainer>
|
||||
|
@ -36,7 +36,9 @@ export const PlayerBigPlayButton = ({
|
||||
if (!visible) return;
|
||||
|
||||
return (
|
||||
<WrapperPlayerBigPlayButton>
|
||||
<WrapperPlayerBigPlayButton
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
>
|
||||
<BigIconPlay onClick={onClick} />
|
||||
</WrapperPlayerBigPlayButton>
|
||||
);
|
||||
|
@ -406,6 +406,10 @@ export const ViewerPlayer = ({
|
||||
const percent = Number(event.target.value);
|
||||
const newCurrentTime = (percent / 100) * videoRef.current.duration;
|
||||
|
||||
const videoCurrentTime = videoRef.current.currentTime;
|
||||
|
||||
if (Math.abs(newCurrentTime - videoCurrentTime) <= 0.1) return;
|
||||
|
||||
handleProgress();
|
||||
setTimeline(percent);
|
||||
setCurrentTime(newCurrentTime);
|
||||
@ -653,6 +657,7 @@ export const ViewerPlayer = ({
|
||||
onDurationChange={handleDurationChange}
|
||||
onLoadedMetadata={handleLoadedMetaDataVideo}
|
||||
onPlay={() => setIsPlaying(true)}
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
/>
|
||||
<PlayerBigPlayButton
|
||||
onClick={handleBigPlayButtonClick}
|
||||
|
@ -79,7 +79,8 @@ const ControlButtons = ({
|
||||
onClick={onNavigationButtonClick}
|
||||
/>
|
||||
) : null;
|
||||
const children = tariffBar ? React.cloneElement(tariffBar, { title }) : null;
|
||||
const children =
|
||||
tariffBar && !isFrame ? React.cloneElement(tariffBar, { title }) : null;
|
||||
const isTabletView = isTablet();
|
||||
|
||||
const contextOptionsFolder = getContextOptionsFolder();
|
||||
|
@ -145,3 +145,7 @@ export interface SectionProps {
|
||||
isDesktop?: boolean;
|
||||
getContextModel?: () => ContextMenuModel[];
|
||||
}
|
||||
|
||||
export interface SectionContextMenuProps {
|
||||
getContextModel: () => ContextMenuModel[];
|
||||
}
|
||||
|
@ -29,14 +29,13 @@ import { useLocation } from "react-router-dom";
|
||||
|
||||
// import { inject, observer } from "mobx-react";
|
||||
|
||||
import { ContextMenu } from "@docspace/shared/components/context-menu";
|
||||
|
||||
import {
|
||||
StyledDropZoneBody,
|
||||
StyledSpacer,
|
||||
StyledSectionBody,
|
||||
} from "../Section.styled";
|
||||
import { SectionBodyProps } from "../Section.types";
|
||||
import SectionContextMenu from "./SectionContextMenu";
|
||||
|
||||
const SectionBody = React.memo(
|
||||
({
|
||||
@ -53,49 +52,9 @@ const SectionBody = React.memo(
|
||||
getContextModel,
|
||||
}: SectionBodyProps) => {
|
||||
const focusRef = React.useRef<HTMLDivElement | null>(null);
|
||||
const cmRef = React.useRef<null | {
|
||||
show: (e: React.MouseEvent | MouseEvent) => void;
|
||||
hide: (e: React.MouseEvent | MouseEvent) => void;
|
||||
toggle: (e: React.MouseEvent | MouseEvent) => boolean;
|
||||
getVisible: () => boolean;
|
||||
}>(null);
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
const onContextMenu = React.useCallback(
|
||||
(e: MouseEvent | React.MouseEvent<Element, MouseEvent>) => {
|
||||
const bodyElem = document.getElementsByClassName(
|
||||
"section-body",
|
||||
)[0] as HTMLDivElement;
|
||||
|
||||
const target = e.target as Node;
|
||||
|
||||
if (
|
||||
!getContextModel ||
|
||||
!getContextModel() ||
|
||||
!bodyElem ||
|
||||
!bodyElem.contains(target)
|
||||
)
|
||||
return;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// if (cmRef.current) cmRef.current.toggle(e);
|
||||
if (cmRef.current) {
|
||||
if (!isOpen) cmRef?.current?.show(e);
|
||||
else cmRef?.current?.hide(e);
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
},
|
||||
[getContextModel, isOpen],
|
||||
);
|
||||
|
||||
const onHide = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const focusSectionBody = React.useCallback(() => {
|
||||
if (focusRef.current) focusRef.current.focus({ preventScroll: true });
|
||||
}, []);
|
||||
@ -108,14 +67,6 @@ const SectionBody = React.memo(
|
||||
[focusSectionBody],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
document.addEventListener("contextmenu", onContextMenu);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("contextmenu", onContextMenu);
|
||||
};
|
||||
}, [onContextMenu]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!autoFocus) return;
|
||||
|
||||
@ -145,16 +96,6 @@ const SectionBody = React.memo(
|
||||
}
|
||||
: {};
|
||||
|
||||
const contextBlock = (
|
||||
<ContextMenu
|
||||
ref={cmRef}
|
||||
onHide={onHide}
|
||||
getContextModel={getContextModel}
|
||||
withBackdrop
|
||||
model={[]}
|
||||
/>
|
||||
);
|
||||
|
||||
return uploadFiles ? (
|
||||
<StyledDropZoneBody
|
||||
isDropZone
|
||||
@ -179,7 +120,7 @@ const SectionBody = React.memo(
|
||||
</div>
|
||||
)}
|
||||
|
||||
{contextBlock}
|
||||
<SectionContextMenu getContextModel={getContextModel} />
|
||||
</StyledDropZoneBody>
|
||||
) : (
|
||||
<StyledSectionBody
|
||||
@ -200,7 +141,7 @@ const SectionBody = React.memo(
|
||||
) : (
|
||||
<div className="section-wrapper">{children}</div>
|
||||
)}
|
||||
{contextBlock}
|
||||
<SectionContextMenu getContextModel={getContextModel} />
|
||||
</StyledSectionBody>
|
||||
);
|
||||
},
|
||||
|
@ -0,0 +1,80 @@
|
||||
import React from "react";
|
||||
import { ContextMenu } from "@docspace/shared/components/context-menu";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { SectionContextMenuProps } from "../Section.types";
|
||||
|
||||
const areEqual = (
|
||||
prevProps: SectionContextMenuProps,
|
||||
nextProps: SectionContextMenuProps,
|
||||
) => {
|
||||
if (!isEqual(prevProps, nextProps)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
const SectionContextMenu = React.memo(
|
||||
({ getContextModel }: SectionContextMenuProps) => {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
||||
const cmRef = React.useRef<null | {
|
||||
show: (e: React.MouseEvent | MouseEvent) => void;
|
||||
hide: (e: React.MouseEvent | MouseEvent) => void;
|
||||
toggle: (e: React.MouseEvent | MouseEvent) => boolean;
|
||||
getVisible: () => boolean;
|
||||
}>(null);
|
||||
|
||||
const onHide = () => {
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const onContextMenu = React.useCallback(
|
||||
(e: MouseEvent | React.MouseEvent<Element, MouseEvent>) => {
|
||||
const bodyElem = document.getElementsByClassName(
|
||||
"section-body",
|
||||
)[0] as HTMLDivElement;
|
||||
|
||||
const target = e.target as Node;
|
||||
|
||||
if (
|
||||
!getContextModel ||
|
||||
!getContextModel() ||
|
||||
!bodyElem ||
|
||||
!bodyElem.contains(target)
|
||||
)
|
||||
return;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// if (cmRef.current) cmRef.current.toggle(e);
|
||||
if (cmRef.current) {
|
||||
if (!isOpen) cmRef?.current?.show(e);
|
||||
else cmRef?.current?.hide(e);
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
},
|
||||
[getContextModel, isOpen],
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
document.addEventListener("contextmenu", onContextMenu);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("contextmenu", onContextMenu);
|
||||
};
|
||||
}, [onContextMenu]);
|
||||
|
||||
return (
|
||||
<ContextMenu
|
||||
ref={cmRef}
|
||||
onHide={onHide}
|
||||
getContextModel={getContextModel}
|
||||
withBackdrop
|
||||
model={[]}
|
||||
/>
|
||||
);
|
||||
},
|
||||
areEqual,
|
||||
);
|
||||
SectionContextMenu.displayName = "SectionContextMenu";
|
||||
|
||||
export default SectionContextMenu;
|
@ -75,6 +75,7 @@ export type TFrameEvents = {
|
||||
onAuthSuccess: null | ((e: Event) => void);
|
||||
onSignOut: null | ((e: Event) => void);
|
||||
onDownload: null | ((e: Event) => void);
|
||||
onNoAccess: null | ((e: Event) => void);
|
||||
};
|
||||
|
||||
export type TFrameConfig = {
|
||||
@ -96,6 +97,7 @@ export type TFrameConfig = {
|
||||
showSelectorCancel: boolean;
|
||||
showSelectorHeader: boolean;
|
||||
showHeader: boolean;
|
||||
showHeaderBanner: string;
|
||||
showTitle: boolean;
|
||||
showMenu: boolean;
|
||||
showFilter: boolean;
|
||||
|
@ -220,10 +220,12 @@ class AxiosClient {
|
||||
}
|
||||
|
||||
const loginURL = combineUrl(proxyURL, "/login");
|
||||
|
||||
if (!this.isSSR) {
|
||||
switch (error.response?.status) {
|
||||
case 401: {
|
||||
if (options.skipUnauthorized) return Promise.resolve();
|
||||
if (options.skipUnauthorized || window?.ClientConfig?.isFrame)
|
||||
return Promise.resolve();
|
||||
if (options.skipLogout) return Promise.reject(error);
|
||||
|
||||
const opt: AxiosRequestConfig = {
|
||||
@ -244,14 +246,13 @@ class AxiosClient {
|
||||
break;
|
||||
case 403: {
|
||||
const pathname = window.location.pathname;
|
||||
const isFrame = window?.ClientConfig?.isFrame;
|
||||
|
||||
const isArchived = pathname.indexOf("/rooms/archived") !== -1;
|
||||
|
||||
const isRooms =
|
||||
pathname.indexOf("/rooms/shared") !== -1 || isArchived;
|
||||
|
||||
if (isRooms && !skipRedirect && !isFrame) {
|
||||
if (isRooms && !skipRedirect && !window?.ClientConfig?.isFrame) {
|
||||
setTimeout(() => {
|
||||
window.DocSpace.navigate(isArchived ? "/archived" : "/");
|
||||
}, 1000);
|
||||
|
@ -53,7 +53,7 @@
|
||||
showSignOut: true,
|
||||
destroyText: "",
|
||||
viewAs: "row", //TODO: ["row", "table", "tile"]
|
||||
viewTableColumns: "Name,Type,Tags",
|
||||
viewTableColumns: "Name,Size,Type,Tags",
|
||||
checkCSP: true,
|
||||
disableActionButton: false,
|
||||
showSettings: false,
|
||||
@ -97,6 +97,8 @@
|
||||
onAuthSuccess: null,
|
||||
onSignOut: null,
|
||||
onDownload: null,
|
||||
onNoAccess: null,
|
||||
onContentReady: null,
|
||||
},
|
||||
};
|
||||
|
||||
@ -813,7 +815,10 @@
|
||||
targetFrame.style.height = this.config.height;
|
||||
targetFrame.parentNode.style.height = "inherit";
|
||||
|
||||
if (loader) loader.remove();
|
||||
if (loader) {
|
||||
loader.remove();
|
||||
this.config.events.onContentReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user