Merge branch 'release/rc-v1.2.0' into feature/static-versioned
This commit is contained in:
commit
0cb238e5d3
@ -3,7 +3,7 @@
|
||||
"AdvancedSettings": "Advanced Settings",
|
||||
"AdvancedSettingsTooltip": "Hide default authentication page and automatically redirect to SSO service",
|
||||
"AttributeMatching": "Attribute Mapping",
|
||||
"AttributeMatchingTooltip": "The correspondence of the single sign-on attributes to the fields of the portal 'People' module",
|
||||
"AttributeMatchingTooltip": "The correspondence of the Single Sign-On attributes to the entries of the 'Accounts' section",
|
||||
"Binding": "Binding:",
|
||||
"CertificateExist": "Certificate with same action type already exists",
|
||||
"ConfirmationText": "All the data you entered will be lost. Are you sure you want to continue?",
|
||||
|
@ -3,7 +3,7 @@
|
||||
"AdvancedSettings": "Дополнительно",
|
||||
"AdvancedSettingsTooltip": "Скрыть страницу аутентификации по умолчанию и автоматически перенаправлять на сервис SSO",
|
||||
"AttributeMatching": "Сопоставление аттрибутов:",
|
||||
"AttributeMatchingTooltip": "Соответствие атрибутов единого входа полям в модуле портала 'Люди'",
|
||||
"AttributeMatchingTooltip": "Соответствие атрибутов единого входа записям раздела 'Аккаунты'",
|
||||
"Binding": "Привязка:",
|
||||
"CertificateExist": "Сертификат с таким же типом действия уже существует",
|
||||
"ConfirmationText": "Все введенные данные будут потеряны. Вы уверены, что хотите продолжить?",
|
||||
|
@ -17,10 +17,10 @@ const StyledWrapper = styled.div`
|
||||
`;
|
||||
|
||||
const DocspaceLogo = (props) => {
|
||||
const { className, whiteLabelLogoUrls, userTheme } = props;
|
||||
const { className, whiteLabelLogoUrls, theme } = props;
|
||||
|
||||
const logo = getLogoFromPath(
|
||||
userTheme === "Dark"
|
||||
!theme.isBase
|
||||
? whiteLabelLogoUrls[1]?.path?.dark
|
||||
: whiteLabelLogoUrls[1]?.path?.light
|
||||
);
|
||||
@ -33,12 +33,11 @@ const DocspaceLogo = (props) => {
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore, userStore } = auth;
|
||||
const { whiteLabelLogoUrls } = settingsStore;
|
||||
const { userTheme } = userStore;
|
||||
const { settingsStore } = auth;
|
||||
const { whiteLabelLogoUrls, theme } = settingsStore;
|
||||
|
||||
return {
|
||||
whiteLabelLogoUrls,
|
||||
userTheme,
|
||||
theme,
|
||||
};
|
||||
})(observer(DocspaceLogo));
|
||||
|
@ -23,7 +23,7 @@ import AppLoader from "@docspace/common/components/AppLoader";
|
||||
import Snackbar from "@docspace/components/snackbar";
|
||||
import moment from "moment";
|
||||
import ReactSmartBanner from "./components/SmartBanner";
|
||||
import { useThemeDetector } from "SRC_DIR/helpers/utils";
|
||||
import { useThemeDetector } from "@docspace/common/utils/useThemeDetector";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import IndicatorLoader from "./components/IndicatorLoader";
|
||||
import DialogsWrapper from "./components/dialogs/DialogsWrapper";
|
||||
|
@ -21,7 +21,6 @@ const CreateEvent = ({
|
||||
templateId,
|
||||
fromTemplate,
|
||||
onClose,
|
||||
|
||||
setIsLoading,
|
||||
createFile,
|
||||
createFolder,
|
||||
@ -36,7 +35,7 @@ const CreateEvent = ({
|
||||
|
||||
isPrivacy,
|
||||
isDesktop,
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
|
||||
clearActiveOperations,
|
||||
fileCopyAs,
|
||||
@ -49,6 +48,7 @@ const CreateEvent = ({
|
||||
|
||||
setEventDialogVisible,
|
||||
eventDialogVisible,
|
||||
createWithoutDialog,
|
||||
}) => {
|
||||
const [headerTitle, setHeaderTitle] = React.useState(null);
|
||||
const [startValue, setStartValue] = React.useState("");
|
||||
@ -74,7 +74,12 @@ const CreateEvent = ({
|
||||
}
|
||||
|
||||
setHeaderTitle(defaultName);
|
||||
setEventDialogVisible(true);
|
||||
|
||||
if (!createWithoutDialog) {
|
||||
setEventDialogVisible(true);
|
||||
} else {
|
||||
onSave(null, title || defaultName);
|
||||
}
|
||||
|
||||
return () => {
|
||||
setEventDialogVisible(false);
|
||||
@ -120,7 +125,7 @@ const CreateEvent = ({
|
||||
addActiveItems(null, [folder.id]);
|
||||
setCreatedItem({ id: createdFolderId, type: "folder" });
|
||||
})
|
||||
.then(() => editCompleteAction(item, type, true))
|
||||
.then(() => completeAction(item, type, true))
|
||||
.catch((e) => toastr.error(e))
|
||||
.finally(() => {
|
||||
const folderIds = [+id];
|
||||
@ -140,7 +145,7 @@ const CreateEvent = ({
|
||||
|
||||
open && openDocEditor(file.id, file.providerKey, tab);
|
||||
})
|
||||
.then(() => editCompleteAction(item, type))
|
||||
.then(() => completeAction(item, type))
|
||||
.catch((err) => {
|
||||
let errorMessage = "";
|
||||
if (typeof err === "object") {
|
||||
@ -198,10 +203,9 @@ const CreateEvent = ({
|
||||
createdFileId = file.id;
|
||||
setCreatedItem({ id: createdFileId, type: "file" });
|
||||
addActiveItems([file.id]);
|
||||
|
||||
return open && openDocEditor(file.id, file.providerKey, tab);
|
||||
})
|
||||
.then(() => editCompleteAction(item, type))
|
||||
.then(() => completeAction(item, type))
|
||||
.catch((e) => toastr.error(e))
|
||||
.finally(() => {
|
||||
const fileIds = [+id];
|
||||
@ -237,7 +241,7 @@ const CreateEvent = ({
|
||||
|
||||
return open && openDocEditor(file.id, file.providerKey, tab);
|
||||
})
|
||||
.then(() => editCompleteAction(item, type))
|
||||
.then(() => completeAction(item, type))
|
||||
.catch((e) => toastr.error(e))
|
||||
.finally(() => {
|
||||
const fileIds = [+id];
|
||||
@ -267,6 +271,7 @@ const CreateEvent = ({
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
onClose={onCloseAction}
|
||||
isCreateDialog={true}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -294,7 +299,7 @@ export default inject(
|
||||
|
||||
const { gallerySelected, setGallerySelected } = oformsStore;
|
||||
|
||||
const { editCompleteAction } = filesActionsStore;
|
||||
const { completeAction } = filesActionsStore;
|
||||
|
||||
const { clearActiveOperations, fileCopyAs } = uploadDataStore;
|
||||
|
||||
@ -313,6 +318,8 @@ export default inject(
|
||||
eventDialogVisible,
|
||||
} = dialogsStore;
|
||||
|
||||
const { createWithoutDialog } = filesStore;
|
||||
|
||||
return {
|
||||
setEventDialogVisible,
|
||||
eventDialogVisible,
|
||||
@ -331,7 +338,7 @@ export default inject(
|
||||
isDesktop: isDesktopClient,
|
||||
isPrivacy: isPrivacyFolder,
|
||||
isTrashFolder: isRecycleBinFolder,
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
|
||||
clearActiveOperations,
|
||||
fileCopyAs,
|
||||
@ -341,6 +348,8 @@ export default inject(
|
||||
|
||||
replaceFileStream,
|
||||
setEncryptionAccess,
|
||||
|
||||
createWithoutDialog,
|
||||
};
|
||||
}
|
||||
)(observer(CreateEvent));
|
||||
|
@ -164,7 +164,7 @@ export default inject(
|
||||
uploadRoomLogo,
|
||||
addLogoToRoom,
|
||||
fetchFiles,
|
||||
addFile,
|
||||
addItem,
|
||||
} = filesStore;
|
||||
const { createTag, fetchTags } = tagsStore;
|
||||
|
||||
|
@ -19,7 +19,7 @@ const RenameEvent = ({
|
||||
updateFile,
|
||||
renameFolder,
|
||||
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
clearActiveOperations,
|
||||
|
||||
setEventDialogVisible,
|
||||
@ -54,7 +54,7 @@ const RenameEvent = ({
|
||||
|
||||
onClose();
|
||||
|
||||
return editCompleteAction(item, type);
|
||||
return completeAction(item, type);
|
||||
} else {
|
||||
timerId = setTimeout(() => {
|
||||
isFile ? addActiveItems([item.id]) : addActiveItems(null, [item.id]);
|
||||
@ -63,7 +63,7 @@ const RenameEvent = ({
|
||||
|
||||
isFile
|
||||
? updateFile(item.id, value)
|
||||
.then(() => editCompleteAction(item, type))
|
||||
.then(() => completeAction(item, type))
|
||||
.then(() =>
|
||||
toastr.success(
|
||||
t("FileRenamed", {
|
||||
@ -74,7 +74,7 @@ const RenameEvent = ({
|
||||
)
|
||||
.catch((err) => {
|
||||
toastr.error(err);
|
||||
editCompleteAction(item, type);
|
||||
completeAction(item, type);
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(timerId);
|
||||
@ -84,7 +84,7 @@ const RenameEvent = ({
|
||||
onClose();
|
||||
})
|
||||
: renameFolder(item.id, value)
|
||||
.then(() => editCompleteAction(item, type))
|
||||
.then(() => completeAction(item, type))
|
||||
.then(() => {
|
||||
if (selectedFolderId === item.id) {
|
||||
setSelectedFolder({ title: value });
|
||||
@ -98,7 +98,7 @@ const RenameEvent = ({
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(err);
|
||||
editCompleteAction(item, type);
|
||||
completeAction(item, type);
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(timerId);
|
||||
@ -146,7 +146,7 @@ export default inject(
|
||||
|
||||
const { id, setSelectedFolder } = selectedFolderStore;
|
||||
|
||||
const { editCompleteAction } = filesActionsStore;
|
||||
const { completeAction } = filesActionsStore;
|
||||
|
||||
const { clearActiveOperations } = uploadDataStore;
|
||||
const { setEventDialogVisible, eventDialogVisible } = dialogsStore;
|
||||
@ -157,7 +157,7 @@ export default inject(
|
||||
updateFile,
|
||||
renameFolder,
|
||||
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
|
||||
clearActiveOperations,
|
||||
setEventDialogVisible,
|
||||
|
@ -6,6 +6,8 @@ import ModalDialog from "@docspace/components/modal-dialog";
|
||||
import TextInput from "@docspace/components/text-input";
|
||||
import Button from "@docspace/components/button";
|
||||
import ComboBox from "@docspace/components/combobox";
|
||||
import Checkbox from "@docspace/components/checkbox";
|
||||
import Box from "@docspace/components/box";
|
||||
|
||||
const Dialog = ({
|
||||
t,
|
||||
@ -19,9 +21,17 @@ const Dialog = ({
|
||||
onSave,
|
||||
onCancel,
|
||||
onClose,
|
||||
isCreateDialog,
|
||||
createWithoutDialog,
|
||||
setCreateWithoutDialog,
|
||||
}) => {
|
||||
const [value, setValue] = useState("");
|
||||
const [isDisabled, setIsDisabled] = useState(false);
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
createWithoutDialog && isCreateDialog && setIsChecked(createWithoutDialog);
|
||||
}, [isCreateDialog, createWithoutDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
let input = document?.getElementById("create-text-input");
|
||||
@ -67,24 +77,31 @@ const Dialog = ({
|
||||
const onSaveAction = useCallback(
|
||||
(e) => {
|
||||
setIsDisabled(true);
|
||||
isCreateDialog && setCreateWithoutDialog(isChecked);
|
||||
onSave && onSave(e, value);
|
||||
},
|
||||
[onSave, value]
|
||||
[onSave, isCreateDialog, value, isChecked]
|
||||
);
|
||||
|
||||
const onCancelAction = useCallback((e) => {
|
||||
onCancel && onCancel(e);
|
||||
setCreateWithoutDialog(false);
|
||||
}, []);
|
||||
|
||||
const onCloseAction = useCallback(
|
||||
(e) => {
|
||||
if (!isDisabled) {
|
||||
onClose && onClose(e);
|
||||
setCreateWithoutDialog(false);
|
||||
}
|
||||
},
|
||||
[isDisabled]
|
||||
);
|
||||
|
||||
const onChangeCheckbox = () => {
|
||||
isCreateDialog && setIsChecked((val) => !val);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialog
|
||||
visible={visible}
|
||||
@ -106,6 +123,16 @@ const Dialog = ({
|
||||
onFocus={onFocus}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
{isCreateDialog && (
|
||||
<Box displayProp="flex" alignItems="center" paddingProp="16px 0 0">
|
||||
<Checkbox
|
||||
label={t("Common:DontAskAgain")}
|
||||
isChecked={isChecked}
|
||||
onChange={onChangeCheckbox}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{options && (
|
||||
<ComboBox
|
||||
style={{ marginTop: "16px" }}
|
||||
@ -118,7 +145,7 @@ const Dialog = ({
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
key="GlobalSendBtn"
|
||||
label={t("Common:SaveButton")}
|
||||
label={isCreateDialog ? t("Common:Create") : t("Common:Save")}
|
||||
size="normal"
|
||||
scale
|
||||
primary
|
||||
@ -139,8 +166,9 @@ const Dialog = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
export default inject(({ auth, filesStore }) => {
|
||||
const { folderFormValidation } = auth.settingsStore;
|
||||
const { createWithoutDialog, setCreateWithoutDialog } = filesStore;
|
||||
|
||||
return { folderFormValidation };
|
||||
return { folderFormValidation, createWithoutDialog, setCreateWithoutDialog };
|
||||
})(observer(Dialog));
|
||||
|
@ -121,7 +121,6 @@ const HeaderComponent = ({
|
||||
theme,
|
||||
toggleArticleOpen,
|
||||
logoUrl,
|
||||
userTheme,
|
||||
...props
|
||||
}) => {
|
||||
const { t } = useTranslation("Common");
|
||||
@ -200,7 +199,7 @@ const HeaderComponent = ({
|
||||
}, [history]);
|
||||
|
||||
const logo = getLogoFromPath(
|
||||
userTheme === "Dark" ? logoUrl?.path?.dark : logoUrl?.path?.light
|
||||
!theme.isBase ? logoUrl?.path?.dark : logoUrl?.path?.light
|
||||
);
|
||||
|
||||
return (
|
||||
@ -362,6 +361,5 @@ export default inject(({ auth }) => {
|
||||
currentProductId,
|
||||
toggleArticleOpen,
|
||||
//currentProductName: (product && product.title) || "",
|
||||
userTheme: user.theme,
|
||||
};
|
||||
})(observer(HeaderComponent));
|
||||
|
@ -22,7 +22,7 @@ const ConvertPasswordDialogComponent = (props) => {
|
||||
setFormCreationInfo,
|
||||
setPasswordEntryProcess,
|
||||
isDesktop,
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
fileCopyAs,
|
||||
} = props;
|
||||
const inputRef = React.useRef(null);
|
||||
@ -129,7 +129,7 @@ const ConvertPasswordDialogComponent = (props) => {
|
||||
open && openDocEditor(file.id, file.providerKey, tab);
|
||||
})
|
||||
.then(() => {
|
||||
editCompleteAction(fileInfo);
|
||||
completeAction(fileInfo);
|
||||
})
|
||||
.catch((err) => {
|
||||
let errorMessage = "";
|
||||
@ -221,27 +221,25 @@ const ConvertPasswordDialogComponent = (props) => {
|
||||
</ModalDialog.Body>
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<StyledComponent isTabletView={isTabletView}>
|
||||
<div className="convert-password_footer">
|
||||
<Button
|
||||
id="convert-password-dialog_button-accept"
|
||||
className="convert-password-dialog_button"
|
||||
key="ContinueButton"
|
||||
label={t("Common:SaveButton")}
|
||||
size="small"
|
||||
primary
|
||||
onClick={onConvert}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
className="convert-password-dialog_button"
|
||||
key="CloseButton"
|
||||
label={t("Common:CloseButton")}
|
||||
size="small"
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
</StyledComponent>
|
||||
<Button
|
||||
id="convert-password-dialog_button-accept"
|
||||
className="convert-password-dialog_button"
|
||||
key="ContinueButton"
|
||||
label={t("Common:SaveButton")}
|
||||
size="normal"
|
||||
scale
|
||||
primary
|
||||
onClick={onConvert}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
className="convert-password-dialog_button"
|
||||
key="CloseButton"
|
||||
label={t("Common:CloseButton")}
|
||||
scale
|
||||
size="normal"
|
||||
onClick={onClose}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialog>
|
||||
);
|
||||
@ -263,7 +261,7 @@ export default inject(
|
||||
} = dialogsStore;
|
||||
const { copyAsAction, fileCopyAs } = uploadDataStore;
|
||||
const { setPasswordEntryProcess } = filesStore;
|
||||
const { editCompleteAction } = filesActionsStore;
|
||||
const { completeAction } = filesActionsStore;
|
||||
const { settingsStore } = auth;
|
||||
const { isTabletView, isDesktopClient } = settingsStore;
|
||||
|
||||
@ -277,7 +275,7 @@ export default inject(
|
||||
setFormCreationInfo,
|
||||
setPasswordEntryProcess,
|
||||
isDesktop: isDesktopClient,
|
||||
editCompleteAction,
|
||||
completeAction,
|
||||
};
|
||||
}
|
||||
)(observer(ConvertPasswordDialog));
|
||||
|
@ -47,7 +47,7 @@ export const onConvertFiles = (e, resolve) => {
|
||||
if (entry.isFile) {
|
||||
entry.file(
|
||||
(file) => {
|
||||
addFile(file, entry.fullPath);
|
||||
addItem(file, entry.fullPath);
|
||||
callback();
|
||||
},
|
||||
() => {
|
||||
@ -110,7 +110,7 @@ export const onConvertFiles = (e, resolve) => {
|
||||
const entry = item.webkitGetAsEntry();
|
||||
if (entry) {
|
||||
if (entry.isFile) {
|
||||
addFile(item.getAsFile(), entry.fullPath);
|
||||
addItem(item.getAsFile(), entry.fullPath);
|
||||
} else {
|
||||
entries.push(entry);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import authStore from "@docspace/common/store/AuthStore";
|
||||
import { toCommunityHostname } from "@docspace/common/utils";
|
||||
import history from "@docspace/common/history";
|
||||
import { useEffect, useState } from "react";
|
||||
import { CategoryType } from "./constants";
|
||||
import { FolderType } from "@docspace/common/constants";
|
||||
|
||||
@ -81,38 +80,6 @@ export const getPasswordErrorMessage = (t, settings) => {
|
||||
} ${settings.specSymbols ? t("Common:PasswordLimitSpecialSymbols") : ""}`;
|
||||
};
|
||||
|
||||
export const useThemeDetector = () => {
|
||||
const isDesktopClient = window["AscDesktopEditor"] !== undefined;
|
||||
const [systemTheme, setSystemTheme] = useState(
|
||||
isDesktopClient
|
||||
? window.RendererProcessVariable?.theme?.type === "dark"
|
||||
? "Dark"
|
||||
: "Base"
|
||||
: window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "Dark"
|
||||
: "Base"
|
||||
);
|
||||
|
||||
const systemThemeListener = (e) => {
|
||||
setSystemTheme(e.matches ? "Dark" : "Base");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isDesktopClient) return;
|
||||
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
mediaQuery.addListener(systemThemeListener);
|
||||
|
||||
return () => {
|
||||
if (isDesktopClient) return;
|
||||
|
||||
mediaQuery.removeListener(systemThemeListener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return systemTheme;
|
||||
};
|
||||
|
||||
export const getCategoryType = (location) => {
|
||||
let categoryType = CategoryType.Shared;
|
||||
const { pathname } = location;
|
||||
|
@ -77,7 +77,6 @@ const AboutContent = (props) => {
|
||||
companyInfoSettingsData,
|
||||
previewData,
|
||||
whiteLabelLogoUrls,
|
||||
userTheme,
|
||||
} = props;
|
||||
const { t } = useTranslation("About");
|
||||
const license = "AGPL-3.0";
|
||||
@ -103,7 +102,7 @@ const AboutContent = (props) => {
|
||||
: companyInfoSettingsData?.address;
|
||||
|
||||
const logo = getLogoFromPath(
|
||||
userTheme === "Dark"
|
||||
!theme.isBase
|
||||
? whiteLabelLogoUrls[6]?.path.dark
|
||||
: whiteLabelLogoUrls[6]?.path.light
|
||||
);
|
||||
@ -242,15 +241,13 @@ const AboutContent = (props) => {
|
||||
};
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore, userStore } = auth;
|
||||
const { settingsStore } = auth;
|
||||
|
||||
const { theme, companyInfoSettingsData, whiteLabelLogoUrls } = settingsStore;
|
||||
const { userTheme } = userStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
companyInfoSettingsData,
|
||||
whiteLabelLogoUrls,
|
||||
userTheme,
|
||||
};
|
||||
})(observer(AboutContent));
|
||||
|
@ -28,6 +28,8 @@ const CommonSettings = ({
|
||||
|
||||
t,
|
||||
showTitle,
|
||||
createWithoutDialog,
|
||||
setCreateWithoutDialog,
|
||||
}) => {
|
||||
const [isLoadingFavorites, setIsLoadingFavorites] = React.useState(false);
|
||||
const [isLoadingRecent, setIsLoadingRecent] = React.useState(false);
|
||||
@ -68,6 +70,10 @@ const CommonSettings = ({
|
||||
[setIsLoadingRecent, setRecentSetting]
|
||||
);
|
||||
|
||||
const onChangeCheckbox = () => {
|
||||
setCreateWithoutDialog(!createWithoutDialog);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledSettings showTitle={showTitle}>
|
||||
<Box className="settings-section">
|
||||
@ -76,6 +82,12 @@ const CommonSettings = ({
|
||||
{t("Common:Common")}
|
||||
</Heading>
|
||||
)}
|
||||
<ToggleButton
|
||||
className="toggle-btn"
|
||||
label={t("Common:DontAskAgain")}
|
||||
onChange={onChangeCheckbox}
|
||||
isChecked={createWithoutDialog}
|
||||
/>
|
||||
<ToggleButton
|
||||
className="toggle-btn"
|
||||
label={t("OriginalCopy")}
|
||||
@ -143,50 +155,55 @@ const CommonSettings = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth, settingsStore, treeFoldersStore }) => {
|
||||
const {
|
||||
storeOriginalFiles,
|
||||
confirmDelete,
|
||||
updateIfExist,
|
||||
forcesave,
|
||||
export default inject(
|
||||
({ auth, settingsStore, treeFoldersStore, filesStore }) => {
|
||||
const {
|
||||
storeOriginalFiles,
|
||||
confirmDelete,
|
||||
updateIfExist,
|
||||
forcesave,
|
||||
|
||||
setUpdateIfExist,
|
||||
setStoreOriginal,
|
||||
setUpdateIfExist,
|
||||
setStoreOriginal,
|
||||
|
||||
setConfirmDelete,
|
||||
setConfirmDelete,
|
||||
|
||||
setForceSave,
|
||||
setForceSave,
|
||||
|
||||
favoritesSection,
|
||||
recentSection,
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
} = settingsStore;
|
||||
favoritesSection,
|
||||
recentSection,
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
} = settingsStore;
|
||||
|
||||
const { myFolderId, commonFolderId } = treeFoldersStore;
|
||||
const { myFolderId, commonFolderId } = treeFoldersStore;
|
||||
const { setCreateWithoutDialog, createWithoutDialog } = filesStore;
|
||||
|
||||
return {
|
||||
storeOriginalFiles,
|
||||
confirmDelete,
|
||||
updateIfExist,
|
||||
forceSave: forcesave,
|
||||
return {
|
||||
storeOriginalFiles,
|
||||
confirmDelete,
|
||||
updateIfExist,
|
||||
forceSave: forcesave,
|
||||
|
||||
myFolderId,
|
||||
commonFolderId,
|
||||
isVisitor: auth.userStore.user.isVisitor,
|
||||
favoritesSection,
|
||||
recentSection,
|
||||
myFolderId,
|
||||
commonFolderId,
|
||||
isVisitor: auth.userStore.user.isVisitor,
|
||||
favoritesSection,
|
||||
recentSection,
|
||||
|
||||
setUpdateIfExist,
|
||||
setStoreOriginal,
|
||||
setUpdateIfExist,
|
||||
setStoreOriginal,
|
||||
|
||||
setConfirmDelete,
|
||||
setConfirmDelete,
|
||||
|
||||
setForceSave,
|
||||
setForceSave,
|
||||
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
myFolderId,
|
||||
commonFolderId,
|
||||
};
|
||||
})(observer(CommonSettings));
|
||||
setFavoritesSetting,
|
||||
setRecentSetting,
|
||||
myFolderId,
|
||||
commonFolderId,
|
||||
setCreateWithoutDialog,
|
||||
createWithoutDialog,
|
||||
};
|
||||
}
|
||||
)(observer(CommonSettings));
|
||||
|
@ -160,8 +160,19 @@ class ContextOptionsStore {
|
||||
this.settingsStore.extsWebRestrictedEditing[0];
|
||||
|
||||
this.uploadDataStore.copyAsAction(id, newTitle, folderId).catch((err) => {
|
||||
if (err.indexOf("password") == -1) {
|
||||
toastr.error(err, t("Common:Warning"));
|
||||
let errorMessage = "";
|
||||
if (typeof err === "object") {
|
||||
errorMessage =
|
||||
err?.response?.data?.error?.message ||
|
||||
err?.statusText ||
|
||||
err?.message ||
|
||||
"";
|
||||
} else {
|
||||
errorMessage = err;
|
||||
}
|
||||
|
||||
if (errorMessage.indexOf("password") == -1) {
|
||||
toastr.error(errorMessage, t("Common:Warning"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -563,13 +563,12 @@ class FilesActionStore {
|
||||
return this.downloadFiles(fileIds, folderIds, label);
|
||||
};
|
||||
|
||||
editCompleteAction = async (selectedItem, type, isFolder = false) => {
|
||||
if (type === FileAction.Create) {
|
||||
this.filesStore.addFile(selectedItem, isFolder);
|
||||
}
|
||||
|
||||
if (type === FileAction.Create || type === FileAction.Rename) {
|
||||
type === FileAction.Rename &&
|
||||
completeAction = async (selectedItem, type, isFolder = false) => {
|
||||
switch (type) {
|
||||
case FileAction.Create:
|
||||
this.filesStore.addItem(selectedItem, isFolder);
|
||||
break;
|
||||
case FileAction.Rename:
|
||||
this.onSelectItem(
|
||||
{
|
||||
id: selectedItem.id,
|
||||
@ -577,6 +576,9 @@ class FilesActionStore {
|
||||
},
|
||||
false
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ import debounce from "lodash.debounce";
|
||||
|
||||
const { FilesFilter, RoomsFilter } = api;
|
||||
const storageViewAs = localStorage.getItem("viewAs");
|
||||
const storageCheckbox = JSON.parse(localStorage.getItem("createWithoutDialog"));
|
||||
|
||||
let requestCounter = 0;
|
||||
|
||||
@ -48,6 +49,7 @@ class FilesStore {
|
||||
|
||||
isLoaded = false;
|
||||
isLoading = false;
|
||||
createWithoutDialog = storageCheckbox ? true : false;
|
||||
|
||||
viewAs =
|
||||
isMobile && storageViewAs !== "tile" ? "row" : storageViewAs || "table";
|
||||
@ -397,6 +399,11 @@ class FilesStore {
|
||||
localStorage.setItem("viewAs", viewAs);
|
||||
};
|
||||
|
||||
setCreateWithoutDialog = (checked) => {
|
||||
this.createWithoutDialog = checked;
|
||||
localStorage.setItem("createWithoutDialog", JSON.stringify(checked));
|
||||
};
|
||||
|
||||
setPageItemsLength = (pageItemsLength) => {
|
||||
this.pageItemsLength = pageItemsLength;
|
||||
};
|
||||
@ -478,7 +485,19 @@ class FilesStore {
|
||||
if (!this.isEditor) {
|
||||
requests.push(
|
||||
getPortalCultures(),
|
||||
this.treeFoldersStore.fetchTreeFolders()
|
||||
this.treeFoldersStore.fetchTreeFolders().then((treeFolders) => {
|
||||
if (!treeFolders || !treeFolders.length) return;
|
||||
|
||||
const trashFolder = treeFolders.find(
|
||||
(f) => f.rootFolderType == FolderType.TRASH
|
||||
);
|
||||
|
||||
if (!trashFolder) return;
|
||||
|
||||
const isEmpty = !trashFolder.foldersCount && !trashFolder.filesCount;
|
||||
|
||||
this.setTrashIsEmpty(isEmpty);
|
||||
})
|
||||
);
|
||||
|
||||
if (isDesktopClient) {
|
||||
@ -486,7 +505,6 @@ class FilesStore {
|
||||
}
|
||||
}
|
||||
requests.push(getFilesSettings());
|
||||
requests.push(this.getIsEmptyTrash());
|
||||
|
||||
return Promise.all(requests).then(() => this.setIsInit(true));
|
||||
};
|
||||
@ -1823,19 +1841,48 @@ class FilesStore {
|
||||
scrollElm && scrollElm.scrollTo(0, 0);
|
||||
};
|
||||
|
||||
addFile = (item, isFolder) => {
|
||||
addItem = (item, isFolder) => {
|
||||
const { socketHelper } = this.authStore.settingsStore;
|
||||
|
||||
if (isFolder) {
|
||||
const foundIndex = this.folders.findIndex((x) => x.id === item?.id);
|
||||
if (foundIndex > -1) return;
|
||||
|
||||
this.folders.unshift(item);
|
||||
|
||||
console.log("[WS] subscribe to folder changes", item.id, item.title);
|
||||
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: {
|
||||
roomParts: `DIR-${item.id}`,
|
||||
individual: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const foundIndex = this.files.findIndex((x) => x.id === item?.id);
|
||||
if (foundIndex > -1) return;
|
||||
|
||||
console.log("[WS] subscribe to file changes", item.id, item.title);
|
||||
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: { roomParts: `FILE-${item.id}`, individual: true },
|
||||
});
|
||||
|
||||
this.files.unshift(item);
|
||||
}
|
||||
const { isRoomsFolder, isArchiveFolder } = this.treeFoldersStore;
|
||||
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
|
||||
const filter = isRooms ? this.roomsFilter.clone() : this.filter.clone();
|
||||
|
||||
filter.total += 1;
|
||||
|
||||
if (isRooms) this.setRoomsFilter(filter);
|
||||
else this.setFilter(filter);
|
||||
|
||||
isFolder ? this.folders.unshift(item) : this.files.unshift(item);
|
||||
|
||||
this.scrollToTop();
|
||||
};
|
||||
|
||||
@ -2791,19 +2838,19 @@ class FilesStore {
|
||||
setCreatedItem = (createdItem) => {
|
||||
this.createdItem = createdItem;
|
||||
|
||||
const { socketHelper } = this.authStore.settingsStore;
|
||||
if (createdItem?.type == "file") {
|
||||
console.log(
|
||||
"[WS] subscribe to file's changes",
|
||||
createdItem.id,
|
||||
createdItem.title
|
||||
);
|
||||
// const { socketHelper } = this.authStore.settingsStore;
|
||||
// if (createdItem?.type == "file") {
|
||||
// console.log(
|
||||
// "[WS] subscribe to file's changes",
|
||||
// createdItem.id,
|
||||
// createdItem.title
|
||||
// );
|
||||
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: { roomParts: `FILE-${createdItem.id}`, individual: true },
|
||||
});
|
||||
}
|
||||
// socketHelper.emit({
|
||||
// command: "subscribe",
|
||||
// data: { roomParts: `FILE-${createdItem.id}`, individual: true },
|
||||
// });
|
||||
// }
|
||||
};
|
||||
|
||||
setScrollToItem = (item) => {
|
||||
|
@ -1080,9 +1080,7 @@ class UploadDataStore {
|
||||
const { fetchFiles, filter } = this.filesStore;
|
||||
|
||||
return fileCopyAs(fileId, title, folderId, enableExternalExt, password)
|
||||
.then(() => {
|
||||
fetchFiles(folderId, filter, true, true);
|
||||
})
|
||||
.then(() => fetchFiles(folderId, filter, true, true))
|
||||
.catch((err) => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
|
@ -175,36 +175,27 @@ export function getFoldersTree() {
|
||||
const folders = sortInDisplayOrder(response);
|
||||
|
||||
return folders.map((data, index) => {
|
||||
const type = +data.current.rootFolderType;
|
||||
const { new: newItems, pathParts, current, folders, files } = data;
|
||||
const { foldersCount, filesCount } = current;
|
||||
const { parentId, title, id, rootFolderType, security } = current;
|
||||
|
||||
const type = +rootFolderType;
|
||||
|
||||
const name = getFolderClassNameByType(type);
|
||||
const isRecycleBinFolder = type === FolderType.TRASH;
|
||||
|
||||
return {
|
||||
id: data.current.id,
|
||||
id,
|
||||
key: `0-${index}`,
|
||||
parentId: data.current.parentId,
|
||||
title: data.current.title,
|
||||
parentId,
|
||||
title,
|
||||
rootFolderType: type,
|
||||
folderClassName: name,
|
||||
// folders: !isRecycleBinFolder
|
||||
// ? data.folders.map((folder) => {
|
||||
// return {
|
||||
// id: folder.id,
|
||||
// title: folder.title,
|
||||
// access: folder.access,
|
||||
// foldersCount: folder.foldersCount,
|
||||
// rootFolderType: folder.rootFolderType,
|
||||
// providerKey: folder.providerKey,
|
||||
// newItems: folder.new,
|
||||
// };
|
||||
// })
|
||||
// : null,
|
||||
folders: null,
|
||||
pathParts: data.pathParts,
|
||||
foldersCount: !isRecycleBinFolder
|
||||
? data.current.foldersCount || data.folders.length
|
||||
: null,
|
||||
newItems: data.new,
|
||||
security: data.current.security,
|
||||
pathParts,
|
||||
foldersCount,
|
||||
filesCount,
|
||||
newItems,
|
||||
security,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ const ArticleHeader = ({
|
||||
onClick,
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
userTheme,
|
||||
theme,
|
||||
...rest
|
||||
}) => {
|
||||
const history = useHistory();
|
||||
@ -27,14 +27,12 @@ const ArticleHeader = ({
|
||||
const isTabletView = (isTabletUtils() || isTablet) && !isMobileOnly;
|
||||
const onLogoClick = () => history.push("/");
|
||||
|
||||
const burgerLogo =
|
||||
userTheme === "Dark"
|
||||
? getLogoFromPath(whiteLabelLogoUrls[5].path.dark)
|
||||
: getLogoFromPath(whiteLabelLogoUrls[5].path.light);
|
||||
const logo =
|
||||
userTheme === "Dark"
|
||||
? getLogoFromPath(whiteLabelLogoUrls[0].path.dark)
|
||||
: getLogoFromPath(whiteLabelLogoUrls[0].path.light);
|
||||
const burgerLogo = !theme.isBase
|
||||
? getLogoFromPath(whiteLabelLogoUrls[5].path.dark)
|
||||
: getLogoFromPath(whiteLabelLogoUrls[5].path.light);
|
||||
const logo = !theme.isBase
|
||||
? getLogoFromPath(whiteLabelLogoUrls[0].path.dark)
|
||||
: getLogoFromPath(whiteLabelLogoUrls[0].path.light);
|
||||
|
||||
if (isMobileOnly) return <></>;
|
||||
return (
|
||||
@ -73,13 +71,12 @@ ArticleHeader.propTypes = {
|
||||
ArticleHeader.displayName = "Header";
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore, userStore } = auth;
|
||||
const { isBurgerLoading, whiteLabelLogoUrls } = settingsStore;
|
||||
const { userTheme } = userStore;
|
||||
const { settingsStore } = auth;
|
||||
const { isBurgerLoading, whiteLabelLogoUrls, theme } = settingsStore;
|
||||
|
||||
return {
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
userTheme,
|
||||
theme,
|
||||
};
|
||||
})(observer(ArticleHeader));
|
||||
|
@ -116,20 +116,6 @@ class UserStore {
|
||||
get isAuthenticated() {
|
||||
return !!this.user;
|
||||
}
|
||||
|
||||
get userTheme() {
|
||||
const systemTheme =
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "Dark"
|
||||
: "Light";
|
||||
const theme = this.user?.theme || systemTheme;
|
||||
|
||||
if (theme === "System") {
|
||||
return systemTheme;
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
export default UserStore;
|
||||
|
33
packages/common/utils/useThemeDetector.js
Normal file
33
packages/common/utils/useThemeDetector.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const useThemeDetector = () => {
|
||||
const isDesktopClient = window["AscDesktopEditor"] !== undefined;
|
||||
const [systemTheme, setSystemTheme] = useState(
|
||||
isDesktopClient
|
||||
? window?.RendererProcessVariable?.theme?.type === "dark"
|
||||
? "Dark"
|
||||
: "Base"
|
||||
: window?.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "Dark"
|
||||
: "Base"
|
||||
);
|
||||
|
||||
const systemThemeListener = (e) => {
|
||||
setSystemTheme(e.matches ? "Dark" : "Base");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isDesktopClient) return;
|
||||
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
mediaQuery.addListener(systemThemeListener);
|
||||
|
||||
return () => {
|
||||
if (isDesktopClient) return;
|
||||
|
||||
mediaQuery.removeListener(systemThemeListener);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return systemTheme;
|
||||
};
|
@ -13,6 +13,7 @@ import { getBgPattern, getLogoFromPath } from "@docspace/common/utils";
|
||||
import { useMounted } from "../helpers/useMounted";
|
||||
import useIsomorphicLayoutEffect from "../hooks/useIsomorphicLayoutEffect";
|
||||
import LoginContainer from "@docspace/common/components/LoginContainer";
|
||||
import { useThemeDetector } from "@docspace/common/utils/useThemeDetector";
|
||||
|
||||
interface IBarProp {
|
||||
t: TFuncType;
|
||||
@ -40,6 +41,7 @@ const Form: React.FC = ({ theme, setTheme, logoUrls }) => {
|
||||
|
||||
const email = "test@onlyoffice.com"; //TODO: get email from form
|
||||
const validCode = "123456"; //TODO: get from api
|
||||
const systemTheme = typeof window !== "undefined" && useThemeDetector();
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
const theme =
|
||||
@ -50,6 +52,11 @@ const Form: React.FC = ({ theme, setTheme, logoUrls }) => {
|
||||
setTheme(theme);
|
||||
}, []);
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (systemTheme === "Base") setTheme(Base);
|
||||
else setTheme(Dark);
|
||||
}, [systemTheme]);
|
||||
|
||||
const onSubmit = (code: number | string) => {
|
||||
if (code !== validCode) {
|
||||
setInvalidCode(true);
|
||||
|
@ -25,6 +25,7 @@ import { useMounted } from "../helpers/useMounted";
|
||||
import { getBgPattern } from "@docspace/common/utils";
|
||||
import useIsomorphicLayoutEffect from "../hooks/useIsomorphicLayoutEffect";
|
||||
import { getLogoFromPath } from "@docspace/common/utils";
|
||||
import { useThemeDetector } from "@docspace/common/utils/useThemeDetector";
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
@ -50,6 +51,7 @@ const Login: React.FC<ILoginProps> = ({
|
||||
|
||||
const { t } = useTranslation(["Login", "Common"]);
|
||||
const mounted = useMounted();
|
||||
const systemTheme = typeof window !== "undefined" && useThemeDetector();
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
const theme =
|
||||
@ -60,6 +62,11 @@ const Login: React.FC<ILoginProps> = ({
|
||||
setTheme(theme);
|
||||
}, []);
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
if (systemTheme === "Base") setTheme(Base);
|
||||
else setTheme(Dark);
|
||||
}, [systemTheme]);
|
||||
|
||||
const ssoExists = () => {
|
||||
if (ssoUrl) return true;
|
||||
else return false;
|
||||
|
@ -189,7 +189,7 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
return;
|
||||
}
|
||||
|
||||
var needToMark = new List<FileEntry<TTo>>();
|
||||
var needToMark = new List<FileEntry>();
|
||||
|
||||
var moveOrCopyFoldersTask = await MoveOrCopyFoldersAsync(scope, Folders, toFolder, _copy, parentFolders);
|
||||
var moveOrCopyFilesTask = await MoveOrCopyFilesAsync(scope, Files, toFolder, _copy, parentFolders);
|
||||
@ -200,13 +200,20 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
var ntm = needToMark.Distinct();
|
||||
foreach (var n in ntm)
|
||||
{
|
||||
await fileMarker.MarkAsNewAsync(n);
|
||||
if (n is FileEntry<T> entry1)
|
||||
{
|
||||
await fileMarker.MarkAsNewAsync(entry1);
|
||||
}
|
||||
else if (n is FileEntry<TTo> entry2)
|
||||
{
|
||||
await fileMarker.MarkAsNewAsync(entry2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<List<FileEntry<TTo>>> MoveOrCopyFoldersAsync<TTo>(IServiceScope scope, List<T> folderIds, Folder<TTo> toFolder, bool copy, IEnumerable<Folder<TTo>> toFolderParents, bool checkPermissions = true)
|
||||
private async Task<List<FileEntry>> MoveOrCopyFoldersAsync<TTo>(IServiceScope scope, List<T> folderIds, Folder<TTo> toFolder, bool copy, IEnumerable<Folder<TTo>> toFolderParents, bool checkPermissions = true)
|
||||
{
|
||||
var needToMark = new List<FileEntry<TTo>>();
|
||||
var needToMark = new List<FileEntry>();
|
||||
|
||||
if (folderIds.Count == 0)
|
||||
{
|
||||
@ -230,6 +237,7 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
var folder = await FolderDao.GetFolderAsync(folderId);
|
||||
|
||||
var isRoom = DocSpaceHelper.IsRoom(folder.FolderType);
|
||||
var isThirdPartyRoom = isRoom && folder.ProviderEntry;
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
@ -396,10 +404,9 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
|
||||
TTo newFolderId = default;
|
||||
|
||||
if (isRoom && folder.ProviderEntry)
|
||||
if (isThirdPartyRoom)
|
||||
{
|
||||
await ProviderDao.UpdateProviderInfoAsync(folder.ProviderId, toFolder.FolderType);
|
||||
newFolderId = (TTo)Convert.ChangeType(folder, typeof(TTo));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -428,8 +435,6 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
}
|
||||
}
|
||||
|
||||
newFolder = await folderDao.GetFolderAsync(newFolderId);
|
||||
|
||||
if (isRoom)
|
||||
{
|
||||
if (toFolder.FolderType == FolderType.Archive)
|
||||
@ -447,14 +452,23 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
}
|
||||
|
||||
|
||||
if (isToFolder)
|
||||
if (isToFolder && toFolder.FolderType != FolderType.Archive)
|
||||
{
|
||||
needToMark.Add(newFolder);
|
||||
if (isThirdPartyRoom)
|
||||
{
|
||||
needToMark.Add(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
newFolder = await folderDao.GetFolderAsync(newFolderId);
|
||||
needToMark.Add(newFolder);
|
||||
}
|
||||
}
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
sb.Append($"folder_{newFolderId}{SplitChar}");
|
||||
var id = isThirdPartyRoom ? folder.Id.ToString() : newFolderId.ToString();
|
||||
sb.Append($"folder_{id}{SplitChar}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,11 +52,16 @@ public class FileConverterQueue<T>
|
||||
{
|
||||
var task = PeekTask(file);
|
||||
|
||||
if (Contains(task))
|
||||
if (task != null)
|
||||
{
|
||||
return;
|
||||
if (task.Progress != 100)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dequeue(task);
|
||||
}
|
||||
|
||||
|
||||
var queueResult = new FileConverterOperationResult
|
||||
{
|
||||
Source = JsonSerializer.Serialize(new { id = file.Id, version = file.Version }),
|
||||
@ -137,15 +142,13 @@ public class FileConverterQueue<T>
|
||||
public async Task<FileConverterOperationResult> GetStatusAsync(KeyValuePair<File<T>, bool> pair, FileSecurity fileSecurity)
|
||||
{
|
||||
var file = pair.Key;
|
||||
var operation = PeekTask(pair.Key);
|
||||
var operation = PeekTask(file);
|
||||
|
||||
if (operation != null && (pair.Value || await fileSecurity.CanReadAsync(file)))
|
||||
{
|
||||
if (operation.Progress == 100)
|
||||
{
|
||||
var task = PeekTask(file);
|
||||
|
||||
Dequeue(task);
|
||||
{
|
||||
Dequeue(operation);
|
||||
}
|
||||
|
||||
return operation;
|
||||
@ -183,21 +186,6 @@ public class FileConverterQueue<T>
|
||||
}, options);
|
||||
}
|
||||
|
||||
private bool Contains(FileConverterOperationResult val)
|
||||
{
|
||||
if (val == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var queueTasks = LoadFromCache();
|
||||
|
||||
return queueTasks.Any(x =>
|
||||
{
|
||||
return String.Compare(x.Source, val.Source) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
private bool IsOrphanCacheItem(FileConverterOperationResult x)
|
||||
{
|
||||
return !string.IsNullOrEmpty(x.Processed)
|
||||
@ -213,7 +201,7 @@ public class FileConverterQueue<T>
|
||||
|
||||
SaveToCache(listTasks);
|
||||
|
||||
return queueTasks;
|
||||
return listTasks;
|
||||
}
|
||||
|
||||
private void SaveToCache(IEnumerable<FileConverterOperationResult> queueTasks)
|
||||
|
@ -137,13 +137,13 @@ public class FilesModule : FeedModule
|
||||
.Where(f => f.ShareRecord == null)
|
||||
.ToListAsync();
|
||||
|
||||
var folderIDs = files.Select(r => r.File.ParentId).ToList();
|
||||
var folderIDs = files.Select(r => r.File.ParentId).Distinct().ToList();
|
||||
var folders = await _folderDao.GetFoldersAsync(folderIDs, checkShare: false).ToListAsync();
|
||||
var roomsIds = await _folderDao.GetParentRoomsAsync(folderIDs).ToDictionaryAsync(k => k.FolderId, v => v.ParentRoomId);
|
||||
|
||||
return files.Select(f => new Tuple<Feed.Aggregator.Feed, object>(ToFeed(f, folders.FirstOrDefault(r => r.Id.Equals(f.File.ParentId)),
|
||||
roomsIds.GetValueOrDefault(f.File.ParentId)), f));
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IEnumerable<int>> GetTenantsWithFeeds(DateTime fromTime)
|
||||
{
|
||||
|
@ -77,6 +77,7 @@
|
||||
"DocSpaceAdmin": "DocSpace admin",
|
||||
"Documents": "Documents",
|
||||
"DomainIpAddress": "Domains as IP addresses are not supported",
|
||||
"DontAskAgain": "Don't ask file name again on creation",
|
||||
"Done": "Done",
|
||||
"Download": "Download",
|
||||
"Duplicate": "Create copy",
|
||||
|
@ -77,6 +77,7 @@
|
||||
"DocSpaceAdmin": "DocSpace администратор",
|
||||
"Documents": "Документы",
|
||||
"DomainIpAddress": "IP адрес в качестве домена не поддерживается",
|
||||
"DontAskAgain": "Больше не запрашивать имя файла при создани",
|
||||
"Done": "Успешно",
|
||||
"Download": "Скачать",
|
||||
"Duplicate": "Создать копию",
|
||||
|
Loading…
Reference in New Issue
Block a user