Merge branch 'hotfix/v2.6.1' into feature/update-langs_2.6.1
This commit is contained in:
commit
dcc6aceb61
@ -254,7 +254,7 @@ const Badges = ({
|
||||
</BadgeWrapper>
|
||||
)}
|
||||
|
||||
{isEditing && !isVisitor && !(isRecentTab && !canEditing) && (
|
||||
{isEditing && !(isRecentTab && !canEditing) && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
isEditing={isEditing}
|
||||
|
@ -60,8 +60,9 @@ const SimulatePassword = memo(
|
||||
isDisabled = false,
|
||||
hasError = false,
|
||||
forwardedRef,
|
||||
inputValue,
|
||||
}) => {
|
||||
const [password, setPassword] = useState("");
|
||||
const [password, setPassword] = useState(inputValue ?? "");
|
||||
const [caretPosition, setCaretPosition] = useState();
|
||||
const [inputType, setInputType] = useState("password");
|
||||
|
||||
@ -143,6 +144,10 @@ const SimulatePassword = memo(
|
||||
isDisabled && inputType !== "password" && setInputType("password");
|
||||
}, [isDisabled]);
|
||||
|
||||
useEffect(() => {
|
||||
setPassword(inputValue);
|
||||
}, [inputValue]);
|
||||
|
||||
return (
|
||||
<StyledBody
|
||||
className="conversation-password-wrapper"
|
||||
|
@ -337,10 +337,14 @@ export default inject<TStore>(
|
||||
} = filesStore;
|
||||
|
||||
const files = items
|
||||
? items.filter((f) => (f.fileExst || f.contentLength) && f)
|
||||
? items.filter((f) => {
|
||||
if (f.isFile || f.fileExst || f.contentLength) return f;
|
||||
})
|
||||
: [];
|
||||
const folders = items
|
||||
? items.filter((f) => !f.fileExst && !f.contentLength && f)
|
||||
? items.filter((f) => {
|
||||
if (!f.fileExst && !f.contentLength && !f.isFile) return f;
|
||||
})
|
||||
: [];
|
||||
|
||||
return {
|
||||
|
@ -24,15 +24,15 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useRef } from "react";
|
||||
import ToggleBlock from "./ToggleBlock";
|
||||
import { PasswordInput } from "@docspace/shared/components/password-input";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
|
||||
import { FieldContainer } from "@docspace/shared/components/field-container";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import SimulatePassword from "../../../components/SimulatePassword";
|
||||
import { getNewPassword } from "@docspace/shared/utils";
|
||||
|
||||
const PasswordAccessBlock = (props) => {
|
||||
const {
|
||||
@ -45,14 +45,12 @@ const PasswordAccessBlock = (props) => {
|
||||
setIsPasswordValid,
|
||||
} = props;
|
||||
|
||||
const passwordInputRef = useRef(null);
|
||||
|
||||
const onGeneratePasswordClick = () => {
|
||||
passwordInputRef.current.onGeneratePassword();
|
||||
const password = getNewPassword();
|
||||
setPasswordValue(password);
|
||||
};
|
||||
|
||||
const onCleanClick = () => {
|
||||
passwordInputRef.current.setState((s) => ({ ...s, value: "" })); //TODO: PasswordInput bug
|
||||
setPasswordValue("");
|
||||
};
|
||||
|
||||
@ -64,8 +62,8 @@ const PasswordAccessBlock = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onChangePassword = (e) => {
|
||||
setPasswordValue(e.target.value);
|
||||
const onChangePassword = (password) => {
|
||||
setPasswordValue(password);
|
||||
setIsPasswordValid(true);
|
||||
};
|
||||
|
||||
@ -80,18 +78,13 @@ const PasswordAccessBlock = (props) => {
|
||||
errorMessage={t("Common:RequiredField")}
|
||||
className="edit-link_password-block"
|
||||
>
|
||||
<PasswordInput
|
||||
// scale //doesn't work
|
||||
// tabIndex={3}
|
||||
// simpleView
|
||||
// passwordSettings={{ minLength: 0 }}
|
||||
<SimulatePassword
|
||||
className="edit-link_password-input"
|
||||
ref={passwordInputRef}
|
||||
simpleView
|
||||
isDisabled={isLoading}
|
||||
hasError={!isPasswordValid}
|
||||
inputValue={passwordValue}
|
||||
onChange={onChangePassword}
|
||||
inputMaxWidth="100%"
|
||||
/>
|
||||
</FieldContainer>
|
||||
|
||||
|
@ -116,74 +116,76 @@ const RoomPassword = (props) => {
|
||||
|
||||
return (
|
||||
<StyledPage>
|
||||
<StyledContent className="public-room-content">
|
||||
<StyledBody>
|
||||
<PortalLogo className="portal-logo" />
|
||||
<div className="public-room-page">
|
||||
<StyledContent className="public-room-content">
|
||||
<StyledBody>
|
||||
<PortalLogo className="portal-logo" />
|
||||
|
||||
<FormWrapper>
|
||||
<div className="password-form">
|
||||
<Text fontSize="16px" fontWeight="600">
|
||||
{t("UploadPanel:EnterPassword")}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
fontSize="13px"
|
||||
fontWeight="400"
|
||||
className="public-room-text"
|
||||
>
|
||||
{t("Common:NeedPassword")}:
|
||||
</Text>
|
||||
<div className="public-room-name">
|
||||
<PublicRoomIcon className="public-room-icon" />
|
||||
<Text
|
||||
className="public-room-text"
|
||||
fontSize="15px"
|
||||
fontWeight="600"
|
||||
>
|
||||
{roomTitle}
|
||||
<FormWrapper>
|
||||
<div className="password-form">
|
||||
<Text fontSize="16px" fontWeight="600">
|
||||
{t("UploadPanel:EnterPassword")}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
fontSize="13px"
|
||||
fontWeight="400"
|
||||
className="public-room-text"
|
||||
>
|
||||
{t("Common:NeedPassword")}:
|
||||
</Text>
|
||||
<div className="public-room-name">
|
||||
<PublicRoomIcon className="public-room-icon" />
|
||||
<Text
|
||||
className="public-room-text"
|
||||
fontSize="15px"
|
||||
fontWeight="600"
|
||||
>
|
||||
{roomTitle}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<FieldContainer
|
||||
isVertical={true}
|
||||
labelVisible={false}
|
||||
hasError={!!errorMessage}
|
||||
errorMessage={errorMessage}
|
||||
>
|
||||
<PasswordInput
|
||||
simpleView
|
||||
id="password"
|
||||
inputName="password"
|
||||
placeholder={t("Common:Password")}
|
||||
type="password"
|
||||
inputValue={password}
|
||||
hasError={!!errorMessage}
|
||||
size="large"
|
||||
scale
|
||||
tabIndex={1}
|
||||
autoComplete="current-password"
|
||||
onChange={onChangePassword}
|
||||
onKeyDown={onKeyPress}
|
||||
isDisabled={isLoading}
|
||||
isDisableTooltip
|
||||
forwardedRef={inputRef}
|
||||
isAutoFocussed
|
||||
/>
|
||||
</FieldContainer>
|
||||
</div>
|
||||
|
||||
<FieldContainer
|
||||
isVertical={true}
|
||||
labelVisible={false}
|
||||
hasError={!!errorMessage}
|
||||
errorMessage={errorMessage}
|
||||
>
|
||||
<PasswordInput
|
||||
simpleView
|
||||
id="password"
|
||||
inputName="password"
|
||||
placeholder={t("Common:Password")}
|
||||
type="password"
|
||||
inputValue={password}
|
||||
hasError={!!errorMessage}
|
||||
size="large"
|
||||
scale
|
||||
tabIndex={1}
|
||||
autoComplete="current-password"
|
||||
onChange={onChangePassword}
|
||||
onKeyDown={onKeyPress}
|
||||
isDisabled={isLoading}
|
||||
isDisableTooltip
|
||||
forwardedRef={inputRef}
|
||||
isAutoFocussed
|
||||
/>
|
||||
</FieldContainer>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
primary
|
||||
size="medium"
|
||||
scale
|
||||
label={t("Common:ContinueButton")}
|
||||
tabIndex={5}
|
||||
onClick={onSubmit}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</FormWrapper>
|
||||
</StyledBody>
|
||||
</StyledContent>
|
||||
<Button
|
||||
primary
|
||||
size="medium"
|
||||
scale
|
||||
label={t("Common:ContinueButton")}
|
||||
tabIndex={5}
|
||||
onClick={onSubmit}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</FormWrapper>
|
||||
</StyledBody>
|
||||
</StyledContent>
|
||||
</div>
|
||||
</StyledPage>
|
||||
);
|
||||
};
|
||||
|
@ -26,20 +26,32 @@
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
import { mobile, tablet } from "@docspace/shared/utils";
|
||||
import BackgroundPatternReactSvgUrl from "PUBLIC_DIR/images/background.pattern.react.svg?url";
|
||||
|
||||
export const StyledPage = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
max-width: 960px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-image: url("${BackgroundPatternReactSvgUrl}");
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
|
||||
.public-room-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 0 auto;
|
||||
max-width: 960px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
background-image: none;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
@ -64,6 +76,7 @@ export const StyledPage = styled.div`
|
||||
}
|
||||
|
||||
.public-room-content {
|
||||
width: 100%;
|
||||
padding-top: 9%;
|
||||
justify-content: unset;
|
||||
min-height: unset;
|
||||
|
@ -188,7 +188,11 @@ class ContextOptionsStore {
|
||||
};
|
||||
|
||||
onClickLinkFillForm = (item) => {
|
||||
if (!item.startFilling && item.isPDFForm)
|
||||
const isFormRoom =
|
||||
this.selectedFolderStore?.roomType === RoomsType.FormRoom ||
|
||||
this.selectedFolderStore?.parentRoomType === FolderType.FormRoom;
|
||||
|
||||
if (!item.startFilling && item.isPDFForm && !isFormRoom)
|
||||
return this.dialogsStore.setFillPDFDialogData(true, item);
|
||||
|
||||
return this.gotoDocEditor(false, item);
|
||||
@ -1553,7 +1557,7 @@ class ContextOptionsStore {
|
||||
if (primaryLink) {
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
item.shared
|
||||
? toastr.success(t("Files:LinkSuccessfullyCopied"))
|
||||
? toastr.success(t("Common:LinkSuccessfullyCopied"))
|
||||
: toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
setShareChanged(true);
|
||||
}
|
||||
|
@ -2176,7 +2176,7 @@ class FilesStore {
|
||||
fileOptions = this.removeOptions(fileOptions, ["download"]);
|
||||
}
|
||||
|
||||
if (!isPdf || item.startFilling || item.isForm) {
|
||||
if (!isPdf || (shouldFillForm && canFillForm)) {
|
||||
fileOptions = this.removeOptions(fileOptions, ["open-pdf"]);
|
||||
}
|
||||
|
||||
|
@ -693,7 +693,10 @@ class UploadDataStore {
|
||||
let conflicts = await checkIsFileExist(toFolderId, filesArray);
|
||||
const folderInfo = await getFolderInfo(toFolderId);
|
||||
|
||||
conflicts = conflicts.map((fileTitle) => ({ title: fileTitle }));
|
||||
conflicts = conflicts.map((fileTitle) => ({
|
||||
title: fileTitle,
|
||||
isFile: true,
|
||||
}));
|
||||
|
||||
if (conflicts.length > 0) {
|
||||
this.setConflictDialogData(conflicts, {
|
||||
|
@ -2,5 +2,6 @@
|
||||
"DeepLinkText": "You can open the document on the portal or in the mobile application",
|
||||
"OpenInApp": "Open in the app",
|
||||
"OpeningDocument": "Opening a document",
|
||||
"StayInBrowser": "Stay in the browser"
|
||||
"StayInBrowser": "Stay in the browser",
|
||||
"RememberChoice": "Remember the choice when opening documents next time"
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ const DeepLink = ({
|
||||
</StyledBodyWrapper>
|
||||
<StyledActionsWrapper>
|
||||
<Checkbox
|
||||
label={t("Common:Remember")}
|
||||
label={t("DeepLink:RememberChoice")}
|
||||
isChecked={isRemember}
|
||||
onChange={onChangeCheckbox}
|
||||
/>
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
@ -49,6 +49,7 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { TData } from "@docspace/shared/components/toast/Toast.type";
|
||||
|
||||
import { getLogoUrl } from "@docspace/shared/utils";
|
||||
import { frameCallCommand } from "@docspace/shared/utils/common";
|
||||
import { useTheme } from "styled-components";
|
||||
import { ValidationStatus, WhiteLabelLogoType } from "@docspace/shared/enums";
|
||||
import { validatePublicRoomPassword } from "@docspace/shared/api/rooms";
|
||||
@ -64,6 +65,8 @@ const FilePassword = ({ shareKey, title, entryTitle }: FilePasswordProps) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
|
||||
useEffect(() => frameCallCommand("setIsLoaded"), []);
|
||||
|
||||
const onChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setPassword(e.target.value);
|
||||
!passwordValid && setPasswordValid(true);
|
||||
|
@ -24,6 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { TError } from "../../utils/axiosClient";
|
||||
import { TariffState } from "../../enums";
|
||||
|
||||
export type TQuotas = { id: number; quantity: number };
|
||||
@ -129,5 +130,5 @@ export type TTenantExtra = {
|
||||
|
||||
export type TRestoreProgress = {
|
||||
progress: number;
|
||||
error?: any;
|
||||
error?: TError;
|
||||
};
|
||||
|
@ -79,6 +79,7 @@ class TableHeaderComponent extends React.Component<
|
||||
columnInfoPanelStorageName,
|
||||
sortBy,
|
||||
sorted,
|
||||
resetColumnsSize,
|
||||
} = this.props;
|
||||
|
||||
if (columnStorageName === prevProps.columnStorageName) {
|
||||
@ -106,6 +107,13 @@ class TableHeaderComponent extends React.Component<
|
||||
}
|
||||
}
|
||||
|
||||
const storageSize =
|
||||
!resetColumnsSize && localStorage.getItem(columnStorageName);
|
||||
|
||||
if (columns.length !== prevProps.columns.length && !storageSize) {
|
||||
return this.resetColumns();
|
||||
}
|
||||
|
||||
this.onResize();
|
||||
}
|
||||
|
||||
|
@ -183,3 +183,66 @@ export const getLastColumn = (tableStorageName: string) => {
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const getNewPassword = (
|
||||
settings: {
|
||||
minLength?: number;
|
||||
upperCase?: boolean;
|
||||
digits?: boolean;
|
||||
specSymbols?: boolean;
|
||||
digitsRegexStr?: string;
|
||||
upperCaseRegexStr?: string;
|
||||
specSymbolsRegexStr?: string;
|
||||
allowedCharactersRegexStr?: string;
|
||||
},
|
||||
generatorSpecial: string = "!@#$%^&*",
|
||||
) => {
|
||||
const passwordSettings = settings ?? {
|
||||
minLength: 8,
|
||||
upperCase: false,
|
||||
digits: false,
|
||||
specSymbols: false,
|
||||
digitsRegexStr: "(?=.*\\d)",
|
||||
upperCaseRegexStr: "(?=.*[A-Z])",
|
||||
specSymbolsRegexStr: "(?=.*[\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E])",
|
||||
};
|
||||
|
||||
const length = passwordSettings?.minLength || 0;
|
||||
const string = "abcdefghijklmnopqrstuvwxyz";
|
||||
const numeric = "0123456789";
|
||||
const special = generatorSpecial || "";
|
||||
|
||||
let password = "";
|
||||
let character = "";
|
||||
|
||||
while (password.length < length) {
|
||||
const a = Math.ceil(string.length * Math.random() * Math.random());
|
||||
const b = Math.ceil(numeric.length * Math.random() * Math.random());
|
||||
const c = Math.ceil(special.length * Math.random() * Math.random());
|
||||
|
||||
let hold = string.charAt(a);
|
||||
|
||||
if (passwordSettings?.upperCase) {
|
||||
hold = password.length % 2 === 0 ? hold.toUpperCase() : hold;
|
||||
}
|
||||
|
||||
character += hold;
|
||||
|
||||
if (passwordSettings?.digits) {
|
||||
character += numeric.charAt(b);
|
||||
}
|
||||
|
||||
if (passwordSettings?.specSymbols) {
|
||||
character += special.charAt(c);
|
||||
}
|
||||
|
||||
password = character;
|
||||
}
|
||||
|
||||
password = password
|
||||
.split("")
|
||||
.sort(() => 0.5 - Math.random())
|
||||
.join("");
|
||||
|
||||
return password.substring(0, length);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user